sobjects/ldapparser.py
changeset 8188 1867e252e487
child 8250 171a9d6bff8f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sobjects/ldapparser.py	Tue Jan 31 21:43:24 2012 +0100
@@ -0,0 +1,99 @@
+# copyright 2011-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of CubicWeb.
+#
+# CubicWeb is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
+"""cubicweb ldap feed source
+
+unlike ldapuser source, this source is copy based and will import ldap content
+(beside passwords for authentication) into the system source.
+"""
+from base64 import b64decode
+
+from logilab.common.decorators import cached
+
+from cubicweb.server.sources import datafeed
+
+class DataFeedlDAPParser(datafeed.DataFeedParser):
+    __regid__ = 'ldapfeed'
+
+    def process(self, url, raise_on_error=False, partialcommit=True):
+        """IDataFeedParser main entry point"""
+        source = self.source
+        searchstr = '(&%s)' % ''.join(source.base_filters)
+        try:
+            ldap_emailattr = source.user_rev_attrs['email']
+        except KeyError:
+            ldap_emailattr = None
+        for userdict in source._search(self._cw, source.user_base_dn,
+                                       source.user_base_scope, searchstr):
+            entity = self.extid2entity(userdict['dn'], 'CWUser', **userdict)
+            if not self.created_during_pull(entity):
+                self.notify_updated(entity)
+                attrs = dict( (k, v) for k, v in userdict.iteritems()
+                              if not k in ('dn', 'email') )
+                self.update_if_necessary(entity, attrs)
+                self._process_email(entity, userdict)
+
+    def before_entity_copy(self, entity, sourceparams):
+        if entity.__regid__ == 'EmailAddress':
+            entity.cw_edited['address'] = sourceparams['address']
+        else:
+            for ldapattr, cwattr in self.source.user_attrs.iteritems():
+                if cwattr != 'email':
+                    entity.cw_edited[cwattr] = sourceparams[ldapattr]
+        return entity
+
+    def after_entity_copy(self, entity, sourceparams):
+        super(DataFeedlDAPParser, self).after_entity_copy(entity, sourceparams)
+        if entity.__regid__ == 'EmailAddress':
+            return
+        groups = [self._get_group(n) for n in self.source.user_default_groups]
+        entity.set_relations(in_group=groups)
+        self._process_email(entity, sourceparams)
+
+    def is_deleted(self, extid, etype, eid):
+        try:
+            extid, _ = extid.rsplit('@@', 1)
+        except ValueError:
+            pass
+        return self.source.object_exists_in_ldap(extid)
+
+    def _process_email(self, entity, userdict):
+        try:
+            emailaddrs = userdict[self.source.user_rev_attrs['email']]
+        except KeyError:
+            return # no email for that user, nothing to do
+        if not isinstance(emailaddrs, list):
+            emailaddrs = [emailaddrs]
+        for emailaddr in emailaddrs:
+            # search for existant email first, may be coming from another source
+            rset = self._cw.execute('EmailAddress X WHERE X address %(addr)s',
+                                   {'addr': emailaddr})
+            if not rset:
+                # not found, create it. first forge an external id
+                emailextid = userdict['dn'] + '@@' + emailaddr
+                email = self.extid2entity(emailextid, 'EmailAddress',
+                                          address=emailaddr)
+                if entity.primary_email:
+                    entity.set_relations(use_email=email)
+                else:
+                    entity.set_relations(primary_email=email)
+            # XXX else check use_email relation?
+
+    @cached
+    def _get_group(self, name):
+        return self._cw.execute('Any X WHERE X is CWGroup, X name %(name)s',
+                                {'name': name}).get_entity(0, 0)