15 # |
15 # |
16 # You should have received a copy of the GNU Lesser General Public License along |
16 # You should have received a copy of the GNU Lesser General Public License along |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
18 """cubicweb ldap feed source""" |
18 """cubicweb ldap feed source""" |
19 |
19 |
|
20 import ldap |
|
21 from ldap.filter import filter_format |
|
22 |
20 from cubicweb.cwconfig import merge_options |
23 from cubicweb.cwconfig import merge_options |
21 from cubicweb.server.sources import datafeed |
24 from cubicweb.server.sources import datafeed |
22 from cubicweb.server import ldaputils |
25 from cubicweb.server import ldaputils, utils |
|
26 from cubicweb import Binary |
23 |
27 |
|
28 _ = unicode |
|
29 |
|
30 # search scopes |
|
31 ldapscope = {'BASE': ldap.SCOPE_BASE, |
|
32 'ONELEVEL': ldap.SCOPE_ONELEVEL, |
|
33 'SUBTREE': ldap.SCOPE_SUBTREE} |
24 |
34 |
25 class LDAPFeedSource(ldaputils.LDAPSourceMixIn, |
35 class LDAPFeedSource(ldaputils.LDAPSourceMixIn, |
26 datafeed.DataFeedSource): |
36 datafeed.DataFeedSource): |
27 """LDAP feed source: unlike ldapuser source, this source is copy based and |
37 """LDAP feed source: unlike ldapuser source, this source is copy based and |
28 will import ldap content (beside passwords for authentication) into the |
38 will import ldap content (beside passwords for authentication) into the |
29 system source. |
39 system source. |
30 """ |
40 """ |
31 support_entities = {'CWUser': False} |
41 support_entities = {'CWUser': False} |
32 use_cwuri_as_url = False |
42 use_cwuri_as_url = False |
33 |
43 |
|
44 options_group = ( |
|
45 ('group-base-dn', |
|
46 {'type' : 'string', |
|
47 'default': '', |
|
48 'help': 'base DN to lookup for groups; disable group importation mechanism if unset', |
|
49 'group': 'ldap-source', 'level': 1, |
|
50 }), |
|
51 ('group-scope', |
|
52 {'type' : 'choice', |
|
53 'default': 'ONELEVEL', |
|
54 'choices': ('BASE', 'ONELEVEL', 'SUBTREE'), |
|
55 'help': 'group search scope (valid values: "BASE", "ONELEVEL", "SUBTREE")', |
|
56 'group': 'ldap-source', 'level': 1, |
|
57 }), |
|
58 ('group-classes', |
|
59 {'type' : 'csv', |
|
60 'default': ('top', 'posixGroup'), |
|
61 'help': 'classes of group', |
|
62 'group': 'ldap-source', 'level': 1, |
|
63 }), |
|
64 ('group-filter', |
|
65 {'type': 'string', |
|
66 'default': '', |
|
67 'help': 'additional filters to be set in the ldap query to find valid groups', |
|
68 'group': 'ldap-source', 'level': 2, |
|
69 }), |
|
70 ('group-attrs-map', |
|
71 {'type' : 'named', |
|
72 'default': {'cn': 'name', 'memberUid': 'member'}, |
|
73 'help': 'map from ldap group attributes to cubicweb attributes', |
|
74 'group': 'ldap-source', 'level': 1, |
|
75 }), |
|
76 ) |
|
77 |
34 options = merge_options(datafeed.DataFeedSource.options |
78 options = merge_options(datafeed.DataFeedSource.options |
35 + ldaputils.LDAPSourceMixIn.options, |
79 + ldaputils.LDAPSourceMixIn.options |
36 optgroup='ldap-source') |
80 + options_group, |
|
81 optgroup='ldap-source',) |
37 |
82 |
|
83 def update_config(self, source_entity, typedconfig): |
|
84 """update configuration from source entity. `typedconfig` is config |
|
85 properly typed with defaults set |
|
86 """ |
|
87 super(LDAPFeedSource, self).update_config(source_entity, typedconfig) |
|
88 self.group_base_dn = str(typedconfig['group-base-dn']) |
|
89 self.group_base_scope = ldapscope[typedconfig['group-scope']] |
|
90 self.group_attrs = typedconfig['group-attrs-map'] |
|
91 self.group_attrs = {'dn': 'eid', 'modifyTimestamp': 'modification_date'} |
|
92 self.group_attrs.update(typedconfig['group-attrs-map']) |
|
93 self.group_rev_attrs = dict((v, k) for k, v in self.group_attrs.iteritems()) |
|
94 self.group_base_filters = [filter_format('(%s=%s)', ('objectClass', o)) |
|
95 for o in typedconfig['group-classes']] |
|
96 if typedconfig['group-filter']: |
|
97 self.group_base_filters.append(typedconfig['group-filter']) |
|
98 |
|
99 def _process_ldap_item(self, dn, iterator): |
|
100 itemdict = super(LDAPFeedSource, self)._process_ldap_item(dn, iterator) |
|
101 # we expect memberUid to be a list of user ids, make sure of it |
|
102 member = self.group_rev_attrs['member'] |
|
103 if isinstance(itemdict.get(member), basestring): |
|
104 itemdict[member] = [itemdict[member]] |
|
105 return itemdict |