1 """cubicweb ldap user source |
1 """cubicweb ldap user source |
2 |
2 |
3 this source is for now limited to a read-only EUser source |
3 this source is for now limited to a read-only EUser source |
4 |
4 |
5 :organization: Logilab |
5 :organization: Logilab |
6 :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
6 :copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
7 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
7 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
8 |
8 |
9 |
9 |
10 Part of the code is coming form Zope's LDAPUserFolder |
10 Part of the code is coming form Zope's LDAPUserFolder |
11 |
11 |
18 WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
19 WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
20 FOR A PARTICULAR PURPOSE. |
20 FOR A PARTICULAR PURPOSE. |
21 """ |
21 """ |
22 |
22 |
23 from mx.DateTime import now, DateTimeDelta |
|
24 |
|
25 from logilab.common.textutils import get_csv |
23 from logilab.common.textutils import get_csv |
26 from rql.nodes import Relation, VariableRef, Constant, Function |
24 from rql.nodes import Relation, VariableRef, Constant, Function |
27 |
25 |
28 import ldap |
26 import ldap |
29 from ldap.ldapobject import ReconnectLDAPObject |
27 from ldap.ldapobject import ReconnectLDAPObject |
30 from ldap.filter import filter_format, escape_filter_chars |
28 from ldap.filter import filter_format, escape_filter_chars |
31 from ldapurl import LDAPUrl |
29 from ldapurl import LDAPUrl |
32 |
30 |
33 from cubicweb.common import AuthenticationError, UnknownEid, RepositoryError |
31 from cubicweb import AuthenticationError, UnknownEid, RepositoryError |
34 from cubicweb.server.sources import AbstractSource, TrFunc, GlobTrFunc, ConnectionWrapper |
|
35 from cubicweb.server.utils import cartesian_product |
32 from cubicweb.server.utils import cartesian_product |
|
33 from cubicweb.server.sources import (AbstractSource, TrFunc, GlobTrFunc, |
|
34 ConnectionWrapper, TimedCache) |
36 |
35 |
37 # search scopes |
36 # search scopes |
38 BASE = ldap.SCOPE_BASE |
37 BASE = ldap.SCOPE_BASE |
39 ONELEVEL = ldap.SCOPE_ONELEVEL |
38 ONELEVEL = ldap.SCOPE_ONELEVEL |
40 SUBTREE = ldap.SCOPE_SUBTREE |
39 SUBTREE = ldap.SCOPE_SUBTREE |
47 MODES = { |
46 MODES = { |
48 0: (389, 'ldap'), |
47 0: (389, 'ldap'), |
49 1: (636, 'ldaps'), |
48 1: (636, 'ldaps'), |
50 2: (0, 'ldapi'), |
49 2: (0, 'ldapi'), |
51 } |
50 } |
52 |
|
53 class TimedCache(dict): |
|
54 def __init__(self, ttlm, ttls=0): |
|
55 # time to live in minutes |
|
56 self.ttl = DateTimeDelta(0, 0, ttlm, ttls) |
|
57 |
|
58 def __setitem__(self, key, value): |
|
59 dict.__setitem__(self, key, (now(), value)) |
|
60 |
|
61 def __getitem__(self, key): |
|
62 return dict.__getitem__(self, key)[1] |
|
63 |
|
64 def clear_expired(self): |
|
65 now_ = now() |
|
66 ttl = self.ttl |
|
67 for key, (timestamp, value) in self.items(): |
|
68 if now_ - timestamp > ttl: |
|
69 del self[key] |
|
70 |
51 |
71 class LDAPUserSource(AbstractSource): |
52 class LDAPUserSource(AbstractSource): |
72 """LDAP read-only EUser source""" |
53 """LDAP read-only EUser source""" |
73 support_entities = {'EUser': False} |
54 support_entities = {'EUser': False} |
74 |
55 |