Skip to content
Permalink
Browse files

Allow LDAP config to use multiple LDAP attributes for emailAddresses …

…(so that both primary address and email aliases may be used for principal-property-search and faulting in individual records).

git-svn-id: https://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk@9424 e27351fd-9f3e-4f54-a53b-843176b1656c
  • Loading branch information...
m0rgen committed Jul 11, 2012
1 parent a68cd71 commit fcffe3b77a4cb49d4de6fe6afba54f9d2f5b6e80
@@ -267,7 +267,9 @@
<key>fullName</key>
<string>cn</string>
<key>emailAddresses</key>
<string>mail</string>
<array>
<string>mail</string>
</array>
<key>firstName</key>
<string>givenName</string>
<key>lastName</key>
@@ -291,7 +293,9 @@
<key>fullName</key>
<string>cn</string>
<key>emailAddresses</key>
<string>mail</string>
<array>
<string>mail</string>
</array>
<key>firstName</key>
<string>givenName</string>
<key>lastName</key>
@@ -118,7 +118,7 @@ def __init__(self, params):
"mapping" : { # maps internal record names to LDAP
"recordName": "uid",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail"], # multiple LDAP fields supported
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -131,7 +131,7 @@ def __init__(self, params):
"mapping" : { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail"], # multiple LDAP fields supported
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -146,7 +146,7 @@ def __init__(self, params):
"mapping" : { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail"], # multiple LDAP fields supported
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -161,7 +161,7 @@ def __init__(self, params):
"mapping" : { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail"], # multiple LDAP fields supported
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -235,9 +235,14 @@ def __init__(self, params):
attrSet.add(self.rdnSchema[recordType]["attr"])
if self.rdnSchema[recordType].get("calendarEnabledAttr", False):
attrSet.add(self.rdnSchema[recordType]["calendarEnabledAttr"])
for attr in self.rdnSchema[recordType]["mapping"].values():
if attr:
attrSet.add(attr)
for attrList in self.rdnSchema[recordType]["mapping"].values():
if attrList:
# Since emailAddresses can map to multiple LDAP fields,
# support either string or list
if isinstance(attrList, str):
attrList = [attrList]
for attr in attrList:
attrSet.add(attr)
# Also put the guidAttr attribute into the mappings for each type
# so recordsMatchingFields can query on guid
self.rdnSchema[recordType]["mapping"]["guid"] = self.rdnSchema["guidAttr"]
@@ -646,9 +651,10 @@ def _getMultipleLdapAttributes(self, attrs, *keys):
"""
results = []
for key in keys:
values = attrs.get(key)
if values is not None:
results += values
if key:
values = attrs.get(key)
if values is not None:
results += values
return results


@@ -686,7 +692,13 @@ def _ldapResultToRecord(self, dn, attrs, recordType):
raise MissingGuidException()

# Find or build email
emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["emailAddresses"]))
# (The emailAddresses mapping is a list of ldap fields)
emailAddressesMappedTo = self.rdnSchema[recordType]["mapping"]["emailAddresses"]
# Supporting either string or list for emailAddresses:
if isinstance(emailAddressesMappedTo, str):
emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["emailAddresses"]))
else:
emailAddresses = set(self._getMultipleLdapAttributes(attrs, *self.rdnSchema[recordType]["mapping"]["emailAddresses"]))
emailSuffix = self.rdnSchema[recordType]["emailSuffix"]

if len(emailAddresses) == 0 and emailSuffix:
@@ -885,7 +897,16 @@ def queryDirectory(self, recordTypes, indexType, indexKey):
ldapEsc(email)
)
else:
filterstr = "(&%s(mail=%s))" % (filterstr, ldapEsc(email))
# emailAddresses can map to multiple LDAP fields
ldapFields = self.rdnSchema[recordType]["mapping"]["emailAddresses"]
if isinstance(ldapFields, str):
subfilter = "(%s=%s)" % (ldapFields, ldapEsc(email))
else:
subfilter = []
for ldapField in ldapFields:
subfilter.append("(%s=%s)" % (ldapField, ldapEsc(email)))
subfilter = "(|%s)" % ("".join(subfilter))
filterstr = "(&%s%s)" % (filterstr, subfilter)

elif indexType == self.INDEX_TYPE_AUTHID:
return
@@ -1157,7 +1178,13 @@ def buildFilter(recordType, mapping, fields, operand="or", optimizeMultiName=Fal
if ldapField:
combined.setdefault(field, []).append((value, caseless, matchType))
value = _convertValue(value, matchType)
converted.append("(%s=%s)" % (ldapField, value))
if isinstance(ldapField, str):
converted.append("(%s=%s)" % (ldapField, value))
else:
subConverted = []
for lf in ldapField:
subConverted.append("(%s=%s)" % (lf, value))
converted.append("(|%s)" % "".join(subConverted))

if len(converted) == 0:
return None
@@ -631,7 +631,7 @@ def enabledForCalendaring(self, request, tag):
if record.enabledForCalendaring:
return tag.fillSlots(
calendarUserAddresses=formatLinks(
resource.calendarUserAddresses()
sorted(resource.calendarUserAddresses())
),
calendarHomes=formatLinks(resource.calendarHomeURLs())
)
@@ -755,7 +755,7 @@ def readProperty(self, property, request):

elif name == "email-address-set":
returnValue(customxml.EmailAddressSet(
*[customxml.EmailAddressProperty(addr) for addr in self.record.emailAddresses]
*[customxml.EmailAddressProperty(addr) for addr in sorted(self.record.emailAddresses)]
))

result = (yield super(DirectoryPrincipalResource, self).readProperty(property, request))
@@ -410,7 +410,7 @@ def setUp(self):
"mapping": { # maps internal record names to LDAP
"recordName": "uid",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail", "emailAliases"],
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -423,7 +423,7 @@ def setUp(self):
"mapping": { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail", "emailAliases"],
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -438,7 +438,7 @@ def setUp(self):
"mapping": { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail", "emailAliases"],
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -453,7 +453,7 @@ def setUp(self):
"mapping": { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail", "emailAliases"],
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -1908,7 +1908,7 @@ def readProperty(self, property, request):

elif name == "calendar-user-address-set":
returnValue(caldavxml.CalendarUserAddressSet(
*[element.HRef(uri) for uri in self.calendarUserAddresses()]
*[element.HRef(uri) for uri in sorted(self.calendarUserAddresses())]
))

elif name == "schedule-inbox-URL":
@@ -97,7 +97,7 @@
"mapping" : { # maps internal record names to LDAP
"recordName": "uid",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail"],
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -110,7 +110,7 @@
"mapping" : { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail"],
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -125,7 +125,7 @@
"mapping" : { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail"],
"firstName" : "givenName",
"lastName" : "sn",
},
@@ -140,7 +140,7 @@
"mapping" : { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
"emailAddresses" : "mail",
"emailAddresses" : ["mail"],
"firstName" : "givenName",
"lastName" : "sn",
},

0 comments on commit fcffe3b

Please sign in to comment.
You can’t perform that action at this time.