From ebe828dd47f52d71a62fbece16f90c901cd94c1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20M=C3=A4der?= <maeder@phys.ethz.ch>
Date: Mon, 26 Feb 2018 19:57:06 +0100
Subject: [PATCH] Add abstraction classes Group, User

---
 bin/showgroup.py     | 18 +++++++++++++----
 lib/isg/argparser.py |  2 ++
 lib/isg/dphysldap.py | 46 +++++++++++++++++++++++++++++++++++---------
 3 files changed, 53 insertions(+), 13 deletions(-)

diff --git a/bin/showgroup.py b/bin/showgroup.py
index 7aec2cb..cba5972 100755
--- a/bin/showgroup.py
+++ b/bin/showgroup.py
@@ -12,6 +12,7 @@ OPTS['access'] = 'accessRight'
 OPTS['blocked'] = 'blocked'
 OPTS['home'] = 'homeDirectory'
 OPTS['shell'] = 'loginShell'
+OPTS['report'] = ['reportEnabled', 'reportUid']
 OPTS['mail'] = 'mail'
 OPTS['telephone'] = 'telephoneNumber'
 
@@ -24,7 +25,12 @@ def main():
 
     ldap = dphysldap.Ldap()
 
-    groups = dphysldap.Groups(ldap, ['cn', 'gidNumber', 'memberUid'])
+    group_attrs = ['cn', 'gidNumber', 'owner', 'memberUid']
+
+    if args['report']:
+        group_attrs.extend(OPTS['report'])
+
+    groups = dphysldap.Groups(ldap, group_attrs)
     groups.search(args['group'])
 
     if not groups:
@@ -36,11 +42,15 @@ def main():
 
     else:
         group = groups[0]
-        cn = group['cn']
-        gid = group['gidNumber']
         members = group['memberUid']
 
-        print('Members of {} ({}):'.format(cn, gid))
+        print('Group {} ({}):'.format(group['cn'], group['gidNumber']))
+        print('Owner: {}'.format(group['owner']))
+        print('Report: {}'.format(group['reportEnabled']))
+        print('Reported to: {}'.format(group['reportUid']))
+        print('Members:')
+
+        del OPTS['report']
 
         attrs = ['uid', 'uidNumber', 'gecos']
         attrs.extend([v for k, v in OPTS.items() if args[k]])
diff --git a/lib/isg/argparser.py b/lib/isg/argparser.py
index 4866bdb..923265c 100644
--- a/lib/isg/argparser.py
+++ b/lib/isg/argparser.py
@@ -13,6 +13,8 @@ def simple(description, arg=None, arg_help='', opts=dict()):
         parser.add_argument(arg, help=arg_help)
 
     for k, v in opts.items():
+        if isinstance(v, list):
+            v = ', '.join(v)
         parser.add_argument('-' + k[:1], '--' + k, dest=k,
                             action='store_const', const=True,
                             help='Show ' + v)
diff --git a/lib/isg/dphysldap.py b/lib/isg/dphysldap.py
index d840718..8fa44b5 100644
--- a/lib/isg/dphysldap.py
+++ b/lib/isg/dphysldap.py
@@ -30,27 +30,34 @@ class AttributeValue(list):
         return delimit.join([str(e) for e in self])
 
 
-class Entry(collections.abc.Mapping):
+class Entry(collections.abc.MutableMapping):
     """
     Abstraction class for LDAP Entry imitating dict
     """
     def __init__(self, *args, **kwargs):
-        self._dict = dict(*args, **kwargs)
+        self._dict = dict()
+        self.update(dict(*args, **kwargs))
 
     def __getitem__(self, key):
+        return self._dict[key]
+
+    def __setitem__(self, key, value):
         """
         If value is a list, convert it to AttributeValue
         """
-        value = self._dict[key]
         if isinstance(value, list):
-            return AttributeValue(value)
-        return value
+            self._dict[key] = AttributeValue(value)
+        else:
+            self._dict[key] = value
+
+    def __delitem__(self, key):
+        del self._dict[key]
 
     def __iter__(self):
         return iter(self._dict)
 
     def __len__(self):
-        return len(self._storage)
+        return len(self._dict)
     
     def __str__(self):
         """
@@ -59,6 +66,25 @@ class Entry(collections.abc.Mapping):
         return '\n'.join([': '.join([k, str(v)]) for k, v in self.items() if v])
 
 
+class Group(Entry):
+    """
+    Abstraction class for LDAP Group imitating Entry
+    """
+    def __init__(self, *args, **kwargs):
+        Entry.__init__(self, *args, **kwargs)
+        if 'owner' in self:
+            for i, owner in enumerate(self['owner']):
+                self['owner'][i] = owner.split('=', 1)[1].split(',', 1)[0]
+
+
+class User(Entry):
+    """
+    Abstraction class for LDAP User imitating Entry
+    """
+    def __init__(self, *args, **kwargs):
+        Entry.__init__(self, *args, **kwargs)
+
+
 class Ldap(object):
     """
     LDAP connection to random server in pool
@@ -104,7 +130,8 @@ class Ldap(object):
         """
         if not self.obj_user:
             self.obj_user = ldap3.ObjectDef(self.user_classes, self.connection)
-        return self.get_entries(self.obj_user, query=query, attributes=attributes)
+        entries = self.get_entries(self.obj_user, query=query, attributes=attributes)
+        return [User(e) for e in entries]
 
     def get_groups(self, query='', attributes=None):
         """
@@ -112,7 +139,8 @@ class Ldap(object):
         """
         if not self.obj_group:
             self.obj_group = ldap3.ObjectDef(self.group_classes, self.connection)
-        return self.get_entries(self.obj_group, query=query, attributes=attributes)
+        entries = self.get_entries(self.obj_group, query=query, attributes=attributes)
+        return [Group(e) for e in entries]
 
 
 class Groups(list):
@@ -134,7 +162,7 @@ class Groups(list):
         return tabulate.tabulate(table, tablefmt=FMT, headers=headers)
 
     #def sort(self, attr):
-    #    self = sorted(self, key=lambda k: k[attr])
+    #    self = sorted(self, key=lambda k: k[attr].__str__())
 
     def search(self, cn):
         """
-- 
GitLab