diff -r da46624a0880 -r 715b9eec6da9 server/sources/ldapfeed.py --- 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 . """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