[CalendarServer-changes] [12087] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Mar 12 11:19:24 PDT 2014
Revision: 12087
http://trac.calendarserver.org//changeset/12087
Author: sagen at apple.com
Date: 2013-12-13 13:51:30 -0800 (Fri, 13 Dec 2013)
Log Message:
-----------
LDAP support for structured locations
Modified Paths:
--------------
CalendarServer/trunk/conf/caldavd-test.plist
CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
Modified: CalendarServer/trunk/conf/caldavd-test.plist
===================================================================
--- CalendarServer/trunk/conf/caldavd-test.plist 2013-12-13 18:21:26 UTC (rev 12086)
+++ CalendarServer/trunk/conf/caldavd-test.plist 2013-12-13 21:51:30 UTC (rev 12087)
@@ -284,29 +284,20 @@
<string>mail</string>
<string>mailAlias</string>
</array>
- <key>firstName</key>
- <string></string>
- <key>lastName</key>
- <string></string>
</dict>
</dict>
<key>locations</key>
<dict>
<key>rdn</key>
<string>ou=locations</string>
+ <key>associatedAddressAttr</key>
+ <string></string>
<key>mapping</key>
<dict>
<key>recordName</key>
<string>cn</string>
<key>fullName</key>
<string>cn</string>
- <key>emailAddresses</key>
- <array>
- </array>
- <key>firstName</key>
- <string></string>
- <key>lastName</key>
- <string></string>
</dict>
</dict>
<key>resources</key>
@@ -319,15 +310,24 @@
<string>cn</string>
<key>fullName</key>
<string>cn</string>
- <key>emailAddresses</key>
- <array>
- </array>
- <key>firstName</key>
- <string></string>
- <key>lastName</key>
- <string></string>
</dict>
</dict>
+ <key>addresses</key>
+ <dict>
+ <key>rdn</key>
+ <string>ou=buildings</string>
+ <key>geoAttr</key>
+ <string></string>
+ <key>streetAddressAttr</key>
+ <string></string>
+ <key>mapping</key>
+ <dict>
+ <key>recordName</key>
+ <string>cn</string>
+ <key>fullName</key>
+ <string>cn</string>
+ </dict>
+ </dict>
</dict>
<key>groupSchema</key>
<dict>
Modified: CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py 2013-12-13 18:21:26 UTC (rev 12086)
+++ CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py 2013-12-13 21:51:30 UTC (rev 12087)
@@ -113,8 +113,6 @@
"guidAttr": "entryUUID",
"users": {
"rdn": "ou=People",
- "attr": "uid", # used only to synthesize email address
- "emailSuffix": None, # used only to synthesize email address
"filter": None, # additional filter for this type
"loginEnabledAttr" : "", # attribute controlling login
"loginEnabledValue" : "yes", # "True" value of above attribute
@@ -130,8 +128,6 @@
},
"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
"mapping" : { # maps internal record names to LDAP
"recordName": "cn",
@@ -143,23 +139,18 @@
},
"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
"calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
"calendarEnabledValue" : "yes", # "True" value of above attribute
+ "associatedAddressAttr" : "",
"mapping" : { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : ["mail"], # multiple LDAP fields supported
- "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
"calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
"calendarEnabledValue" : "yes", # "True" value of above attribute
@@ -167,10 +158,18 @@
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : ["mail"], # multiple LDAP fields supported
- "firstName" : "givenName",
- "lastName" : "sn",
},
},
+ "addresses": {
+ "rdn": "ou=Buildings",
+ "filter": None, # additional filter for this type
+ "streetAddressAttr" : "",
+ "geoAttr" : "",
+ "mapping" : { # maps internal record names to LDAP
+ "recordName": "cn",
+ "fullName" : "cn",
+ },
+ },
},
"groupSchema": {
"membersAttr": "member", # how members are specified
@@ -238,8 +237,10 @@
for recordType in self.recordTypes():
if self.rdnSchema[recordType]["attr"]:
attrSet.add(self.rdnSchema[recordType]["attr"])
- if self.rdnSchema[recordType].get("calendarEnabledAttr", False):
- attrSet.add(self.rdnSchema[recordType]["calendarEnabledAttr"])
+ for n in ("calendarEnabledAttr", "associatedAddressAttr",
+ "streetAddressAttr", "geoAttr"):
+ if self.rdnSchema[recordType].get(n, False):
+ attrSet.add(self.rdnSchema[recordType][n])
for attrList in self.rdnSchema[recordType]["mapping"].values():
if attrList:
# Since emailAddresses can map to multiple LDAP fields,
@@ -304,7 +305,7 @@
# Build filter
filterstr = "(!(objectClass=organizationalUnit))"
- typeFilter = self.rdnSchema[recordType]["filter"]
+ typeFilter = self.rdnSchema[recordType].get("filter", "")
if typeFilter:
filterstr = "(&%s%s)" % (filterstr, typeFilter)
@@ -778,6 +779,7 @@
enabledForAddressBooks = None
uid = None
enabledForLogin = True
+ extras = {}
shortNames = tuple(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["recordName"]))
if not shortNames:
@@ -794,17 +796,17 @@
# Find or build email
# (The emailAddresses mapping is a list of ldap fields)
- emailAddressesMappedTo = self.rdnSchema[recordType]["mapping"]["emailAddresses"]
+ emailAddressesMappedTo = self.rdnSchema[recordType]["mapping"].get("emailAddresses", "")
# Supporting either string or list for emailAddresses:
if isinstance(emailAddressesMappedTo, str):
- emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["emailAddresses"]))
+ emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"].get("emailAddresses", "")))
else:
emailAddresses = set(self._getMultipleLdapAttributes(attrs, *self.rdnSchema[recordType]["mapping"]["emailAddresses"]))
- emailSuffix = self.rdnSchema[recordType]["emailSuffix"]
+ emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
if len(emailAddresses) == 0 and emailSuffix:
emailPrefix = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType]["attr"])
+ self.rdnSchema[recordType].get("attr", "cn"))
emailAddresses.add(emailPrefix + emailSuffix)
proxyGUIDs = ()
@@ -890,6 +892,25 @@
autoAcceptGroup = self._getUniqueLdapAttribute(attrs,
self.resourceSchema["autoAcceptGroupAttr"])
+ if recordType == self.recordType_locations:
+ if self.rdnSchema[recordType]["associatedAddressAttr"]:
+ associatedAddress = self._getUniqueLdapAttribute(attrs,
+ self.rdnSchema[recordType]["associatedAddressAttr"])
+ if associatedAddress:
+ extras["associatedAddress"] = associatedAddress
+
+ elif recordType == self.recordType_addresses:
+ if self.rdnSchema[recordType].get("geoAttr", ""):
+ geo = self._getUniqueLdapAttribute(attrs,
+ self.rdnSchema[recordType]["geoAttr"])
+ if geo:
+ extras["geo"] = geo
+ if self.rdnSchema[recordType].get("streetAddressAttr", ""):
+ street = self._getUniqueLdapAttribute(attrs,
+ self.rdnSchema[recordType]["streetAddressAttr"])
+ if street:
+ extras["streetAddress"] = street
+
serverID = None
if self.poddingSchema["serverIdAttr"]:
serverID = self._getUniqueLdapAttribute(attrs,
@@ -911,6 +932,7 @@
extProxies=proxyGUIDs,
extReadOnlyProxies=readOnlyProxyGUIDs,
attrs=attrs,
+ **extras
)
if self.augmentService is not None:
@@ -981,7 +1003,7 @@
# Build filter
filterstr = "(!(objectClass=organizationalUnit))"
- typeFilter = self.rdnSchema[recordType]["filter"]
+ typeFilter = self.rdnSchema[recordType].get("filter", "")
if typeFilter:
filterstr = "(&%s%s)" % (filterstr, typeFilter)
@@ -1003,17 +1025,17 @@
elif indexType == self.INDEX_TYPE_CUA:
# indexKey is of the form "mailto:test at example.net"
email = indexKey[7:] # strip "mailto:"
- emailSuffix = self.rdnSchema[recordType]["emailSuffix"]
+ emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
if emailSuffix is not None and email.partition("@")[2] == emailSuffix:
filterstr = "(&%s(|(&(!(mail=*))(%s=%s))(mail=%s)))" % (
filterstr,
- self.rdnSchema[recordType]["attr"],
+ self.rdnSchema[recordType].get("attr", "cn"),
email.partition("@")[0],
ldapEsc(email)
)
else:
# emailAddresses can map to multiple LDAP fields
- ldapFields = self.rdnSchema[recordType]["mapping"]["emailAddresses"]
+ ldapFields = self.rdnSchema[recordType]["mapping"].get("emailAddresses", "")
if isinstance(ldapFields, str):
if ldapFields:
subfilter = "(%s=%s)" % (ldapFields, ldapEsc(email))
@@ -1108,7 +1130,7 @@
typeCounts[recordType] = 0
base = self.typeDNs[recordType]
scope = ldap.SCOPE_SUBTREE
- extraFilter = self.rdnSchema[recordType]["filter"]
+ extraFilter = self.rdnSchema[recordType].get("filter", "")
filterstr = buildFilterFromTokens(recordType, self.rdnSchema[recordType]["mapping"],
tokens, extra=extraFilter)
@@ -1509,7 +1531,7 @@
guid, shortNames, authIDs, fullName,
firstName, lastName, emailAddresses,
uid, dn, memberGUIDs, extProxies, extReadOnlyProxies,
- attrs
+ attrs, **kwargs
):
super(LdapDirectoryRecord, self).__init__(
service=service,
@@ -1524,6 +1546,7 @@
extProxies=extProxies,
extReadOnlyProxies=extReadOnlyProxies,
uid=uid,
+ **kwargs
)
# Save attributes of dn and attrs in case you might need them later
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py 2013-12-13 18:21:26 UTC (rev 12086)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py 2013-12-13 21:51:30 UTC (rev 12087)
@@ -541,8 +541,6 @@
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : ["mail", "emailAliases"],
- "firstName" : "givenName",
- "lastName" : "sn",
},
},
"locations": {
@@ -552,12 +550,11 @@
"filter": "(objectClass=apple-resource)", # additional filter for this type
"calendarEnabledAttr" : "", # attribute controlling calendaring
"calendarEnabledValue" : "yes", # "True" value of above attribute
+ "associatedAddressAttr" : "assocAddr",
"mapping": { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "", # old style, single string
- "firstName" : "givenName",
- "lastName" : "sn",
},
},
"resources": {
@@ -571,10 +568,17 @@
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : [], # new style, array
- "firstName" : "givenName",
- "lastName" : "sn",
},
},
+ "addresses": {
+ "rdn": "cn=Buildings",
+ "geoAttr" : "coordinates",
+ "streetAddressAttr" : "postal",
+ "mapping": { # maps internal record names to LDAP
+ "recordName": "cn",
+ "fullName" : "cn",
+ },
+ },
},
"groupSchema": {
"membersAttr": "uniqueMember", # how members are specified
@@ -1514,6 +1518,39 @@
self.service.recordType_users)
self.assertEquals(record.guid, guid.upper())
+ # Location with associated Address
+
+ dn = "cn=odtestlocation,cn=locations,dc=example,dc=com"
+ guid = "D3094652-344B-4633-8DB8-09639FA00FB6"
+ attrs = {
+ "apple-generateduid": [guid],
+ "cn": ["odtestlocation"],
+ "assocAddr" : ["6C6CD280-E6E3-11DF-9492-0800200C9A66"],
+ }
+ record = self.service._ldapResultToRecord(dn, attrs,
+ self.service.recordType_locations)
+ self.assertEquals(record.extras, {
+ "associatedAddress": "6C6CD280-E6E3-11DF-9492-0800200C9A66"
+ })
+
+ # Address with street and geo
+
+ dn = "cn=odtestaddress,cn=buildings,dc=example,dc=com"
+ guid = "6C6CD280-E6E3-11DF-9492-0800200C9A66"
+ attrs = {
+ "apple-generateduid": [guid],
+ "cn": ["odtestaddress"],
+ "coordinates" : ["geo:1,2"],
+ "postal" : ["1 Infinite Loop, Cupertino, CA"],
+ }
+ record = self.service._ldapResultToRecord(dn, attrs,
+ self.service.recordType_addresses)
+ self.assertEquals(record.extras, {
+ "geo": "geo:1,2",
+ "streetAddress" : "1 Infinite Loop, Cupertino, CA",
+ })
+
+
def test_listRecords(self):
"""
listRecords makes an LDAP query (with fake results in this test)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/e76771fe/attachment.html>
More information about the calendarserver-changes
mailing list