[CalendarServer-changes] [7827] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Jul 27 13:15:00 PDT 2011


Revision: 7827
          http://trac.macosforge.org/projects/calendarserver/changeset/7827
Author:   sagen at apple.com
Date:     2011-07-27 13:14:57 -0700 (Wed, 27 Jul 2011)
Log Message:
-----------
LDAP attribute mapping is now configurable per record-type

Modified Paths:
--------------
    CalendarServer/trunk/conf/caldavd-test.plist
    CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
    CalendarServer/trunk/twistedcaldav/stdconfig.py

Modified: CalendarServer/trunk/conf/caldavd-test.plist
===================================================================
--- CalendarServer/trunk/conf/caldavd-test.plist	2011-07-27 06:06:15 UTC (rev 7826)
+++ CalendarServer/trunk/conf/caldavd-test.plist	2011-07-27 20:14:57 UTC (rev 7827)
@@ -257,12 +257,23 @@
             <string></string>
             <key>filter</key>
             <string></string>
-            <key>recordName</key>
-            <string>uid</string>
             <key>loginEnabledAttr</key>
             <string></string>
             <key>loginEnabledValue</key>
             <string>yes</string>
+            <key>mapping</key>
+            <dict>
+              <key>recordName</key>
+              <string>uid</string>
+              <key>fullName</key>
+              <string>cn</string>
+              <key>emailAddresses</key>
+              <string>mail</string>
+              <key>firstName</key>
+              <string>givenName</string>
+              <key>lastName</key>
+              <string>sn</string>
+            </dict>
           </dict>
           <key>groups</key>
           <dict>
@@ -274,20 +285,20 @@
             <string></string>
             <key>filter</key>
             <string></string>
-            <key>recordName</key>
-            <string>cn</string>
+            <key>mapping</key>
+            <dict>
+              <key>recordName</key>
+              <string>cn</string>
+              <key>fullName</key>
+              <string>cn</string>
+              <key>emailAddresses</key>
+              <string>mail</string>
+              <key>firstName</key>
+              <string>givenName</string>
+              <key>lastName</key>
+              <string>sn</string>
+            </dict>
           </dict>
-          <key>attributeMapping</key>
-          <dict>
-            <key>fullName</key>
-            <string>cn</string>
-            <key>emailAddresses</key>
-            <string>mail</string>
-            <key>firstName</key>
-            <string>givenName</string>
-            <key>lastName</key>
-            <string>sn</string>
-          </dict>
         </dict>
         <key>groupSchema</key>
         <dict>

Modified: CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py	2011-07-27 06:06:15 UTC (rev 7826)
+++ CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py	2011-07-27 20:14:57 UTC (rev 7827)
@@ -102,30 +102,54 @@
                     "attr": "uid", # used only to synthesize email address
                     "emailSuffix": None, # used only to synthesize email address
                     "filter": None, # additional filter for this type
-                    "recordName": "uid", # uniquely identifies user records
                     "loginEnabledAttr" : "", # attribute controlling login
                     "loginEnabledValue" : "yes", # value of above attribute
+                    "mapping" : { # maps internal record names to LDAP
+                        "recordName": "uid",
+                        "fullName" : "cn",
+                        "emailAddresses" : "mail",
+                        "firstName" : "givenName",
+                        "lastName" : "sn",
+                    },
                 },
                 "groups": {
                     "rdn": "ou=Group",
                     "attr": "cn", # used only to synthesize email address
                     "emailSuffix": None, # used only to synthesize email address
                     "filter": None, # additional filter for this type
-                    "recordName": "cn", # uniquely identifies group records
+                    "mapping" : { # maps internal record names to LDAP
+                        "recordName": "cn",
+                        "fullName" : "cn",
+                        "emailAddresses" : "mail",
+                        "firstName" : "givenName",
+                        "lastName" : "sn",
+                    },
                 },
                 "locations": {
                     "rdn": "ou=Places",
                     "attr": "cn", # used only to synthesize email address
                     "emailSuffix": None, # used only to synthesize email address
                     "filter": None, # additional filter for this type
-                    "recordName": "cn", # uniquely identifies location records
+                    "mapping" : { # maps internal record names to LDAP
+                        "recordName": "cn",
+                        "fullName" : "cn",
+                        "emailAddresses" : "mail",
+                        "firstName" : "givenName",
+                        "lastName" : "sn",
+                    },
                 },
                 "resources": {
                     "rdn": "ou=Resources",
                     "attr": "cn", # used only to synthesize email address
                     "emailSuffix": None, # used only to synthesize email address
                     "filter": None, # additional filter for this type
-                    "recordName": "cn", # uniquely identifies resource records
+                    "mapping" : { # maps internal record names to LDAP
+                        "recordName": "cn",
+                        "fullName" : "cn",
+                        "emailAddresses" : "mail",
+                        "firstName" : "givenName",
+                        "lastName" : "sn",
+                    },
                 },
             },
             "groupSchema": {
@@ -148,12 +172,6 @@
                 "serverIdAttr": None, # maps to augments server-id
                 "partitionIdAttr": None, # maps to augments partition-id
             },
-            "attributeMapping": { # maps internal record names to LDAP
-                "fullName" : "cn",
-                "emailAddresses" : "mail",
-                "firstName" : "givenName",
-                "lastName" : "sn",
-            },
         }
         ignored = None
         params = self.getParams(params, defaults, ignored)
@@ -177,21 +195,24 @@
         self.groupSchema = params["groupSchema"]
         self.resourceSchema = params["resourceSchema"]
         self.partitionSchema = params["partitionSchema"]
-        self.attributeMapping = params["attributeMapping"]
 
         self.base = ldap.dn.str2dn(self.rdnSchema["base"])
 
         # Certain attributes (such as entryUUID) may be hidden and not
         # returned by default when queried for all attributes. Therefore it is
         # necessary to explicitly pass all the possible attributes list
-        # for ldap searches
-        attrSet = set(["mail", "uid", "userid", "cn", "commonName",
-                       "displayName", "gecos", "givenName", "sn", "surname"])
+        # for ldap searches.  Dynamically build the attribute list based on
+        # config.
+        attrSet = set()
+
         if self.rdnSchema["guidAttr"]:
             attrSet.add(self.rdnSchema["guidAttr"])
         for recordType in self.recordTypes():
             if self.rdnSchema[recordType]["attr"]:
                 attrSet.add(self.rdnSchema[recordType]["attr"])
+            for attr in self.rdnSchema[recordType]["mapping"].values():
+                if attr:
+                    attrSet.add(attr)
         if self.groupSchema["membersAttr"]:
             attrSet.add(self.groupSchema["membersAttr"])
         if self.groupSchema["nestedGroupsAttr"]:
@@ -508,7 +529,7 @@
             guid = self._getUniqueLdapAttribute(attrs, guidAttr)
 
         # Find or build email
-        emailAddresses = self._getMultipleLdapAttributes(attrs, "mail")
+        emailAddresses = self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["emailAddresses"])
         emailSuffix = self.rdnSchema[recordType]["emailSuffix"]
 
 
@@ -523,17 +544,16 @@
         memberGUIDs = set()
 
         # LDAP attribute -> principal matchings
-        shortNames = (self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["recordName"]),)
+        shortNames = (self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["recordName"]),)
         if recordType == self.recordType_users:
-            fullName = self._getUniqueLdapAttribute(attrs, "cn", "commonName",
-                "displayName", "gecos")
-            firstName = self._getUniqueLdapAttribute(attrs, "givenName")
-            lastName = self._getUniqueLdapAttribute(attrs, "sn", "surname")
+            fullName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["fullName"])
+            firstName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["firstName"])
+            lastName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["lastName"])
             enabledForCalendaring = True
             enabledForAddressBooks = True
 
         elif recordType == self.recordType_groups:
-            fullName = self._getUniqueLdapAttribute(attrs, "cn")
+            fullName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["fullName"])
             enabledForCalendaring = False
             enabledForAddressBooks = False
             enabledForLogin = False
@@ -554,7 +574,7 @@
 
         elif recordType in (self.recordType_resources,
             self.recordType_locations):
-            fullName = self._getUniqueLdapAttribute(attrs, "cn")
+            fullName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["fullName"])
             enabledForCalendaring = True
             enabledForAddressBooks = False
             enabledForLogin = False
@@ -689,7 +709,7 @@
             elif indexType == self.INDEX_TYPE_SHORTNAME:
                 filter = "(&%s(%s=%s))" % (
                     filter,
-                    self.rdnSchema[recordType]["recordName"],
+                    self.rdnSchema[recordType]["mapping"]["recordName"],
                     indexKey
                 )
 
@@ -750,7 +770,7 @@
         self.log_debug("Peforming principal property search for %s" % (fields,))
         recordTypes = [recordType] if recordType else self.recordTypes()
         for recordType in recordTypes:
-            filter = buildFilter(self.attributeMapping, fields, operand=operand)
+            filter = buildFilter(self.rdnSchema[recordType]["mapping"], fields, operand=operand)
 
             if filter is not None:
 
@@ -776,6 +796,7 @@
 
                     record = self._ldapResultToRecord(dn, attrs, recordType)
                     records.append(record)
+                    print dn, attrs, record
 
         self.log_debug("Principal property search matched %d records" % (len(records),))
         return succeed(records)

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py	2011-07-27 06:06:15 UTC (rev 7826)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py	2011-07-27 20:14:57 UTC (rev 7827)
@@ -132,30 +132,54 @@
                         "attr": "uid", # used only to synthesize email address
                         "emailSuffix": None, # used only to synthesize email address
                         "filter": "(objectClass=apple-user)", # additional filter for this type
-                        "recordName": "uid", # uniquely identifies user records
                         "loginEnabledAttr" : "", # attribute controlling login
                         "loginEnabledValue" : "yes", # value of above attribute
+                        "mapping": { # maps internal record names to LDAP
+                            "recordName": "uid",
+                            "fullName" : "cn",
+                            "emailAddresses" : "mail",
+                            "firstName" : "givenName",
+                            "lastName" : "sn",
+                        },
                     },
                     "groups": {
                         "rdn": "cn=groups",
                         "attr": "cn", # used only to synthesize email address
                         "emailSuffix": None, # used only to synthesize email address
                         "filter": "(objectClass=apple-group)", # additional filter for this type
-                        "recordName": "cn", # uniquely identifies group records
+                        "mapping": { # maps internal record names to LDAP
+                            "recordName": "cn",
+                            "fullName" : "cn",
+                            "emailAddresses" : "mail",
+                            "firstName" : "givenName",
+                            "lastName" : "sn",
+                        },
                     },
                     "locations": {
                         "rdn": "cn=places",
                         "attr": "cn", # used only to synthesize email address
                         "emailSuffix": None, # used only to synthesize email address
                         "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "recordName": "cn", # uniquely identifies location records
+                        "mapping": { # maps internal record names to LDAP
+                            "recordName": "cn",
+                            "fullName" : "cn",
+                            "emailAddresses" : "mail",
+                            "firstName" : "givenName",
+                            "lastName" : "sn",
+                        },
                     },
                     "resources": {
                         "rdn": "cn=resources",
                         "attr": "cn", # used only to synthesize email address
                         "emailSuffix": None, # used only to synthesize email address
                         "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "recordName": "cn", # uniquely identifies resource records
+                        "mapping": { # maps internal record names to LDAP
+                            "recordName": "cn",
+                            "fullName" : "cn",
+                            "emailAddresses" : "mail",
+                            "firstName" : "givenName",
+                            "lastName" : "sn",
+                        },
                     },
                 },
                 "groupSchema": {
@@ -173,12 +197,6 @@
                     "serverIdAttr": "server-id", # maps to augments server-id
                     "partitionIdAttr": "partition-id", # maps to augments partition-id
                 },
-                "attributeMapping": { # maps internal record names to LDAP
-                    "fullName" : "cn",
-                    "emailAddresses" : "mail",
-                    "firstName" : "givenName",
-                    "lastName" : "sn",
-                },
             }
 
             self.service = LdapDirectoryService(params)
@@ -210,6 +228,7 @@
             self.assertEquals(record.emailAddresses,
                 set(['alternate at example.com', 'odtestamanda at example.com']))
             self.assertEquals(record.shortNames, ('odtestamanda',))
+            self.assertEquals(record.fullName, 'Amanda Test')
             self.assertEquals(record.firstName, 'Amanda')
             self.assertEquals(record.lastName, 'Test')
             self.assertEquals(record.serverID, None)

Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/stdconfig.py	2011-07-27 06:06:15 UTC (rev 7826)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py	2011-07-27 20:14:57 UTC (rev 7827)
@@ -78,30 +78,54 @@
                 "attr": "uid", # used only to synthesize email address
                 "emailSuffix": None, # used only to synthesize email address
                 "filter": None, # additional filter for this type
-                "recordName": "userid", # uniquely identifies user records
-                "loginEnabledAttr" : "loginEnabled", # attribute controlling login
+                "loginEnabledAttr" : "", # attribute controlling login
                 "loginEnabledValue" : "yes", # value of above attribute
+                "mapping" : { # maps internal record names to LDAP
+                    "recordName": "uid",
+                    "fullName" : "cn",
+                    "emailAddresses" : "mail",
+                    "firstName" : "givenName",
+                    "lastName" : "sn",
+                },
             },
             "groups": {
                 "rdn": "ou=Group",
                 "attr": "cn", # used only to synthesize email address
                 "emailSuffix": None, # used only to synthesize email address
                 "filter": None, # additional filter for this type
-                "recordName": "cn", # uniquely identifies group records
+                "mapping" : { # maps internal record names to LDAP
+                    "recordName": "cn",
+                    "fullName" : "cn",
+                    "emailAddresses" : "mail",
+                    "firstName" : "givenName",
+                    "lastName" : "sn",
+                },
             },
             "locations": {
-                "rdn": "ou=Locations",
+                "rdn": "ou=Places",
                 "attr": "cn", # used only to synthesize email address
                 "emailSuffix": None, # used only to synthesize email address
                 "filter": None, # additional filter for this type
-                "recordName": "cn", # uniquely identifies location records
+                "mapping" : { # maps internal record names to LDAP
+                    "recordName": "cn",
+                    "fullName" : "cn",
+                    "emailAddresses" : "mail",
+                    "firstName" : "givenName",
+                    "lastName" : "sn",
+                },
             },
             "resources": {
                 "rdn": "ou=Resources",
                 "attr": "cn", # used only to synthesize email address
                 "emailSuffix": None, # used only to synthesize email address
                 "filter": None, # additional filter for this type
-                "recordName": "cn", # uniquely identifies resource records
+                "mapping" : { # maps internal record names to LDAP
+                    "recordName": "cn",
+                    "fullName" : "cn",
+                    "emailAddresses" : "mail",
+                    "firstName" : "givenName",
+                    "lastName" : "sn",
+                },
             },
         },
         "groupSchema": {
@@ -116,12 +140,6 @@
             "serverIdAttr": None, # maps to augments server-id
             "partitionIdAttr": None, # maps to augments partition-id
         },
-        "attributeMapping": { # maps internal record names to LDAP
-            "fullName" : "cn",
-            "emailAddresses" : "mail",
-            "firstName" : "givenName",
-            "lastName" : "sn",
-        },
     },
 }
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110727/ca4ba039/attachment-0001.html>


More information about the calendarserver-changes mailing list