server/sources/ldapfeed.py
changeset 8922 715b9eec6da9
parent 8708 78a99960286a
child 8989 8742f4bf029f
--- a/server/sources/ldapfeed.py	Wed Apr 24 17:57:14 2013 +0200
+++ b/server/sources/ldapfeed.py	Wed Apr 24 18:11:37 2013 +0200
@@ -17,10 +17,20 @@
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """cubicweb ldap feed source"""
 
+import ldap
+from ldap.filter import filter_format
+
 from cubicweb.cwconfig import merge_options
 from cubicweb.server.sources import datafeed
-from cubicweb.server import ldaputils
+from cubicweb.server import ldaputils, utils
+from cubicweb import Binary
+
+_ = unicode
 
+# search scopes
+ldapscope = {'BASE': ldap.SCOPE_BASE,
+             'ONELEVEL': ldap.SCOPE_ONELEVEL,
+             'SUBTREE': ldap.SCOPE_SUBTREE}
 
 class LDAPFeedSource(ldaputils.LDAPSourceMixIn,
                      datafeed.DataFeedSource):
@@ -31,7 +41,65 @@
     support_entities = {'CWUser': False}
     use_cwuri_as_url = False
 
+    options_group = (
+        ('group-base-dn',
+         {'type' : 'string',
+          'default': '',
+          'help': 'base DN to lookup for groups; disable group importation mechanism if unset',
+          'group': 'ldap-source', 'level': 1,
+          }),
+        ('group-scope',
+         {'type' : 'choice',
+          'default': 'ONELEVEL',
+          'choices': ('BASE', 'ONELEVEL', 'SUBTREE'),
+          'help': 'group search scope (valid values: "BASE", "ONELEVEL", "SUBTREE")',
+          'group': 'ldap-source', 'level': 1,
+          }),
+        ('group-classes',
+         {'type' : 'csv',
+          'default': ('top', 'posixGroup'),
+          'help': 'classes of group',
+          'group': 'ldap-source', 'level': 1,
+          }),
+        ('group-filter',
+         {'type': 'string',
+          'default': '',
+          'help': 'additional filters to be set in the ldap query to find valid groups',
+          'group': 'ldap-source', 'level': 2,
+          }),
+        ('group-attrs-map',
+         {'type' : 'named',
+          'default': {'cn': 'name', 'memberUid': 'member'},
+          'help': 'map from ldap group attributes to cubicweb attributes',
+          'group': 'ldap-source', 'level': 1,
+          }),
+    )
+
     options = merge_options(datafeed.DataFeedSource.options
-                            + ldaputils.LDAPSourceMixIn.options,
-                            optgroup='ldap-source')
+                            + ldaputils.LDAPSourceMixIn.options
+                            + options_group,
+                            optgroup='ldap-source',)
 
+    def update_config(self, source_entity, typedconfig):
+        """update configuration from source entity. `typedconfig` is config
+        properly typed with defaults set
+        """
+        super(LDAPFeedSource, self).update_config(source_entity, typedconfig)
+        self.group_base_dn = str(typedconfig['group-base-dn'])
+        self.group_base_scope = ldapscope[typedconfig['group-scope']]
+        self.group_attrs = typedconfig['group-attrs-map']
+        self.group_attrs = {'dn': 'eid', 'modifyTimestamp': 'modification_date'}
+        self.group_attrs.update(typedconfig['group-attrs-map'])
+        self.group_rev_attrs = dict((v, k) for k, v in self.group_attrs.iteritems())
+        self.group_base_filters = [filter_format('(%s=%s)', ('objectClass', o))
+                                   for o in typedconfig['group-classes']]
+        if typedconfig['group-filter']:
+            self.group_base_filters.append(typedconfig['group-filter'])
+
+    def _process_ldap_item(self, dn, iterator):
+        itemdict = super(LDAPFeedSource, self)._process_ldap_item(dn, iterator)
+        # we expect memberUid to be a list of user ids, make sure of it
+        member = self.group_rev_attrs['member']
+        if isinstance(itemdict.get(member), basestring):
+            itemdict[member] = [itemdict[member]]
+        return itemdict