[CalendarServer-changes] [8274] CalendarServer/trunk/twistedcaldav/directory
source_changes at macosforge.org
source_changes at macosforge.org
Thu Nov 10 16:44:53 PST 2011
Revision: 8274
http://trac.macosforge.org/projects/calendarserver/changeset/8274
Author: sagen at apple.com
Date: 2011-11-10 16:44:52 -0800 (Thu, 10 Nov 2011)
Log Message:
-----------
Handle variable whitespace in DNs by normalizing them as soon as we retrieve them from LDAP.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/directory/directory.py
CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
Modified: CalendarServer/trunk/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/directory.py 2011-11-10 20:47:08 UTC (rev 8273)
+++ CalendarServer/trunk/twistedcaldav/directory/directory.py 2011-11-11 00:44:52 UTC (rev 8274)
@@ -637,10 +637,13 @@
self.log_info("Applying proxy assignment changes")
assignmentCount = 0
for principalUID, members in assignments:
- current = (yield self.proxyDB.getMembers(principalUID))
- if members != current:
- assignmentCount += 1
- yield self.proxyDB.setGroupMembers(principalUID, members)
+ try:
+ current = (yield self.proxyDB.getMembers(principalUID))
+ if members != current:
+ assignmentCount += 1
+ yield self.proxyDB.setGroupMembers(principalUID, members)
+ except Exception, e:
+ self.log_error("Unable to apply proxy assignment: principal=%s, members=%s, error=%s" % (principalUID, members, e))
self.log_info("Applied %d assignment%s to proxy database" %
(assignmentCount, "" if assignmentCount == 1 else "s"))
Modified: CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py 2011-11-10 20:47:08 UTC (rev 8273)
+++ CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py 2011-11-11 00:44:52 UTC (rev 8274)
@@ -314,6 +314,7 @@
numMissingGuids = 0
guidAttr = self.rdnSchema["guidAttr"]
for dn, attrs in results:
+ dn = normalizeDNstr(dn)
unrestricted = True
if self.restrictedGUIDs is not None:
@@ -370,6 +371,7 @@
ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=attrlist)
for dn, attrs in results:
+ dn = normalizeDNstr(dn)
guid = self._getUniqueLdapAttribute(attrs, guidAttr)
if guid:
readDelegate = self._getUniqueLdapAttribute(attrs, readAttr)
@@ -508,12 +510,13 @@
if len(result) == 1:
dn, attrs = result[0]
+ dn = normalizeDNstr(dn)
if self.groupSchema["membersAttr"]:
- members = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["membersAttr"])
+ members = set(self._getMultipleLdapAttributes(attrs,
+ self.groupSchema["membersAttr"]))
if self.groupSchema["nestedGroupsAttr"]:
- nestedGroups = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["nestedGroupsAttr"])
+ nestedGroups = set(self._getMultipleLdapAttributes(attrs,
+ self.groupSchema["nestedGroupsAttr"]))
else:
members = []
@@ -563,15 +566,16 @@
if len(result) == 1:
dn, attrs = result[0]
+ dn = normalizeDNstr(dn)
if self.groupSchema["membersAttr"]:
- subMembers = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["membersAttr"])
+ subMembers = set(self._getMultipleLdapAttributes(attrs,
+ self.groupSchema["membersAttr"]))
else:
subMembers = []
if self.groupSchema["nestedGroupsAttr"]:
- subNestedGroups = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["nestedGroupsAttr"])
+ subNestedGroups = set(self._getMultipleLdapAttributes(attrs,
+ self.groupSchema["nestedGroupsAttr"]))
else:
subNestedGroups = []
@@ -605,7 +609,7 @@
values = attrs.get(key)
if values is not None:
results += values
- return set(results)
+ return results
def _ldapResultToRecord(self, dn, attrs, recordType):
@@ -640,7 +644,7 @@
raise MissingGuidException()
# Find or build email
- emailAddresses = self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["emailAddresses"])
+ emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["emailAddresses"]))
emailSuffix = self.rdnSchema[recordType]["emailSuffix"]
if len(emailAddresses) == 0 and emailSuffix:
@@ -651,7 +655,7 @@
proxyGUIDs = ()
readOnlyProxyGUIDs = ()
autoSchedule = False
- memberGUIDs = set()
+ memberGUIDs = []
# LDAP attribute -> principal matchings
if recordType == self.recordType_users:
@@ -669,18 +673,16 @@
if self.groupSchema["membersAttr"]:
members = self._getMultipleLdapAttributes(attrs, self.groupSchema["membersAttr"])
- if members:
- if type(members) is str:
- members = set([members])
- memberGUIDs.update(members)
+ memberGUIDs.extend(members)
if self.groupSchema["nestedGroupsAttr"]:
members = self._getMultipleLdapAttributes(attrs, self.groupSchema["nestedGroupsAttr"])
- if members:
- if type(members) is str:
- members = set([members])
- memberGUIDs.update(members)
+ memberGUIDs.extend(members)
+ # Normalize members if they're in DN form
+ if not self.groupSchema["memberIdAttr"]: # empty = dn
+ memberGUIDs = [normalizeDNstr(dnStr) for dnStr in list(memberGUIDs)]
+
elif recordType in (self.recordType_resources,
self.recordType_locations):
fullName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["fullName"])
@@ -715,11 +717,11 @@
autoSchedule = (autoScheduleValue ==
self.resourceSchema["autoScheduleEnabledValue"])
if self.resourceSchema["proxyAttr"]:
- proxyGUIDs = self._getMultipleLdapAttributes(attrs,
- self.resourceSchema["proxyAttr"])
+ proxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
+ self.resourceSchema["proxyAttr"]))
if self.resourceSchema["readOnlyProxyAttr"]:
- readOnlyProxyGUIDs = self._getMultipleLdapAttributes(attrs,
- self.resourceSchema["readOnlyProxyAttr"])
+ readOnlyProxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
+ self.resourceSchema["readOnlyProxyAttr"]))
serverID = partitionID = None
if self.partitionSchema["serverIdAttr"]:
@@ -854,6 +856,7 @@
if result:
dn, attrs = result.pop()
+ dn = normalizeDNstr(dn)
unrestricted = True
if self.restrictedGUIDs is not None:
@@ -934,6 +937,7 @@
self.log_debug("LDAP search returned %d results" % (len(results),))
numMissingGuids = 0
for dn, attrs in results:
+ dn = normalizeDNstr(dn)
# Skip if group restriction is in place and guid is not
# a member
if (recordType != self.recordType_groups and
@@ -985,6 +989,7 @@
attributeToSearch = "guid"
valuesToFetch = guids
+
while valuesToFetch:
results = []
@@ -1013,10 +1018,10 @@
if alias not in recordsByAlias:
recordsByAlias[alias] = record
- # record._memberIds contains the members of this group,
+ # record.memberGUIDs() contains the members of this group,
# but it might not be in guid form; it will be data from
# self.groupSchema["memberIdAttr"]
- for memberAlias in record._memberIds:
+ for memberAlias in record.memberGUIDs():
if not memberIdAttr:
# Members are identified by dn so we can take a short
# cut: we know we only need to examine groups, and
@@ -1056,6 +1061,16 @@
return child[-len(parent):] == parent
+def normalizeDNstr(dnStr):
+ """
+ Convert to lowercase and remove extra whitespace
+ @param dnStr: dn
+ @type dnStr: C{str}
+ @return: normalized dn C{str}
+ """
+ return ldap.dn.dn2str(ldap.dn.str2dn(dnStr.lower()))
+
+
def buildFilter(mapping, fields, operand="or"):
"""
Create an LDAP filter string from a list of tuples representing directory
@@ -1138,22 +1153,13 @@
# Store copy of member guids
self._memberGUIDs = memberGUIDs
- # Identifiers of the members of this record if it is a group
- membersAttrs = []
- if self.service.groupSchema["membersAttr"]:
- membersAttrs.append(self.service.groupSchema["membersAttr"])
- if self.service.groupSchema["nestedGroupsAttr"]:
- membersAttrs.append(self.service.groupSchema["nestedGroupsAttr"])
- self._memberIds = self.service._getMultipleLdapAttributes(attrs,
- *membersAttrs)
-
# Identifier of this record as a group member
memberIdAttr = self.service.groupSchema["memberIdAttr"]
if memberIdAttr:
self._memberId = self.service._getUniqueLdapAttribute(attrs,
memberIdAttr)
else:
- self._memberId = self.dn
+ self._memberId = normalizeDNstr(self.dn)
def members(self):
@@ -1171,7 +1177,7 @@
memberIdAttr = self.service.groupSchema["memberIdAttr"]
results = []
- for memberId in self._memberIds:
+ for memberId in self._memberGUIDs:
if memberIdAttr:
@@ -1194,6 +1200,7 @@
if result:
dn, attrs = result.pop()
+ dn = normalizeDNstr(dn)
self.log_debug("Retrieved: %s %s" % (dn,attrs))
recordType = self.service.recordTypeForDN(dn)
if recordType is None:
@@ -1245,6 +1252,7 @@
ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.service.attrlist)
for dn, attrs in results:
+ dn = normalizeDNstr(dn)
shortName = self.service._getUniqueLdapAttribute(attrs, "cn")
self.log_debug("%s is a member of %s" % (self._memberId, shortName))
groups.append(self.service.recordWithShortName(recordType,
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py 2011-11-10 20:47:08 UTC (rev 8273)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py 2011-11-11 00:44:52 UTC (rev 8274)
@@ -17,13 +17,14 @@
try:
from twistedcaldav.directory.ldapdirectory import (
buildFilter, LdapDirectoryService, MissingGuidException,
- splitIntoBatches
+ splitIntoBatches, normalizeDNstr, dnContainedIn
)
from twistedcaldav.test.util import proxiesFile
from twistedcaldav.directory.calendaruserproxyloader import XMLCalendarUserProxyLoader
from twistedcaldav.directory import calendaruserproxy
from twistedcaldav.directory.directory import GroupMembershipCache, GroupMembershipCacheUpdater
from twisted.internet.defer import inlineCallbacks
+ from string import maketrans
import ldap
except ImportError:
print "Skipping because ldap module not installed"
@@ -113,16 +114,150 @@
def __init__(self, actual):
self.actual = actual
- self.testResults = []
- def addTestResults(self, results):
- self.testResults.insert(0, results)
+ # Test data returned from search_s.
+ # Note that some DNs have various extra whitespace added and mixed
+ # up case since LDAP is pretty loose about these.
+ self.records = (
+ (
+ "cn=Recursive1_coasts, cn=gROUps,dc=example, dc=com",
+ {
+ 'cn': ['recursive1_coasts'],
+ 'apple-generateduid': ['recursive1_coasts'],
+ 'uniqueMember': [
+ 'cn=recursive2_coasts,cn=groups,dc=example,dc=com',
+ 'uid=wsanchez ,cn=users, dc=eXAMple,dc=com',
+ ],
+ }
+ ),
+ (
+ "cn=recursive2_coasts,cn=groups,dc=example,dc=com",
+ {
+ 'cn': ['recursive2_coasts'],
+ 'apple-generateduid': ['recursive2_coasts'],
+ 'uniqueMember': [
+ 'cn=recursive1_coasts,cn=groups,dc=example,dc=com',
+ 'uid=cdaboo,cn=users,dc=example,dc=com',
+ ],
+ }
+ ),
+ (
+ 'cn=both_coasts,cn=groups,dc=example,dc=com',
+ {
+ 'cn': ['both_coasts'],
+ 'apple-generateduid': ['both_coasts'],
+ 'uniqueMember': [
+ 'cn=right_coast,cn=groups,dc=example,dc=com',
+ 'cn=left_coast,cn=groups,dc=example,dc=com',
+ ],
+ }
+ ),
+ (
+ 'cn=right_coast,cn=groups,dc=example,dc=com',
+ {
+ 'cn': ['right_coast'],
+ 'apple-generateduid': ['right_coast'],
+ 'uniqueMember': [
+ 'uid=cdaboo,cn=users,dc=example,dc=com',
+ ],
+ }
+ ),
+ (
+ 'cn=left_coast,cn=groups,dc=example,dc=com',
+ {
+ 'cn': ['left_coast'],
+ 'apple-generateduid': ['left_coast'],
+ 'uniqueMember': [
+ 'uid=wsanchez, cn=users,dc=example,dc=com',
+ 'uid=lecroy,cn=users,dc=example,dc=com',
+ 'uid=dreid,cn=users,dc=example,dc=com',
+ ],
+ }
+ ),
+ (
+ "uid=odtestamanda,cn=users,dc=example,dc=com",
+ {
+ 'uid': ['odtestamanda'],
+ 'apple-generateduid': ['9DC04A70-E6DD-11DF-9492-0800200C9A66'],
+ 'sn': ['Test'],
+ 'mail': ['odtestamanda at example.com', 'alternate at example.com'],
+ 'givenName': ['Amanda'],
+ 'cn': ['Amanda Test']
+ }
+ ),
+ (
+ "uid=odtestbetty,cn=users,dc=example,dc=com",
+ {
+ 'uid': ['odtestbetty'],
+ 'apple-generateduid': ['93A8F5C5-49D8-4641-840F-CD1903B0394C'],
+ 'sn': ['Test'],
+ 'mail': ['odtestbetty at example.com'],
+ 'givenName': ['Betty'],
+ 'cn': ['Betty Test']
+ }
+ ),
+ (
+ "uid=odtestcarlene,cn=users,dc=example,dc=com",
+ {
+ 'uid': ['odtestcarlene'],
+ # Note: no guid here, to test this record is skipped
+ 'sn': ['Test'],
+ 'mail': ['odtestcarlene at example.com'],
+ 'givenName': ['Carlene'],
+ 'cn': ['Carlene Test']
+ }
+ ),
+ (
+ "uid=cdaboo,cn=users,dc=example,dc=com",
+ {
+ 'uid': ['cdaboo'],
+ 'apple-generateduid': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
+ 'sn': ['Daboo'],
+ 'mail': ['daboo at example.com'],
+ 'givenName': ['Cyrus'],
+ 'cn': ['Cyrus Daboo']
+ }
+ ),
+ (
+ "uid=wsanchez , cn=users , dc=example,dc=com",
+ {
+ 'uid': ['wsanchez'],
+ 'apple-generateduid': ['6423F94A-6B76-4A3A-815B-D52CFD77935D'],
+ 'sn': ['Sanchez'],
+ 'mail': ['wsanchez at example.com'],
+ 'givenName': ['Wilfredo'],
+ 'cn': ['Wilfredo Sanchez']
+ }
+ ),
+ )
def search_s(self, base, scope, filterstr="(objectClass=*)",
attrlist=None):
- return self.testResults.pop()
+ """ A simple implementation of LDAP search filter processing """
+ base = normalizeDNstr(base)
+ results = []
+ for dn, attrs in self.records:
+ dn = normalizeDNstr(dn)
+ if dn == base:
+ results.append((dn, attrs))
+ elif dnContainedIn(ldap.dn.str2dn(dn), ldap.dn.str2dn(base)):
+ if filterstr in ("(objectClass=*)", "(!(objectClass=organizationalUnit))"):
+ results.append((dn, attrs))
+ else:
+ trans = maketrans("&(|)", " |")
+ fragments = filterstr.encode("utf-8").translate(trans).split("|")
+ for fragment in fragments:
+ if not fragment:
+ continue
+ fragment = fragment.strip()
+ key, value = fragment.split("=")
+ if value in attrs.get(key, []):
+ results.append((dn, attrs))
+ return results
+
+
class LdapDirectoryServiceTestCase(TestCase):
def setUp(self):
@@ -156,7 +291,7 @@
"rdn": "cn=Users",
"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
+ "filter": "", # additional filter for this type
"loginEnabledAttr" : "", # attribute controlling login
"loginEnabledValue" : "yes", # "True" value of above attribute
"calendarEnabledAttr" : "enable-calendar", # attribute controlling calendaring
@@ -173,7 +308,7 @@
"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
+ "filter": "", # additional filter for this type
"mapping": { # maps internal record names to LDAP
"recordName": "cn",
"fullName" : "cn",
@@ -234,6 +369,20 @@
self.service.ldap = LdapDirectoryTestWrapper(self.service.ldap)
+ def test_ldapWrapper(self):
+ """
+ Exercise the fake search_s implementation
+ """
+ # Get all groups
+ self.assertEquals(
+ len(self.service.ldap.search_s("cn=groups,dc=example,dc=com", 0, "(objectClass=*)", [])), 5)
+
+ self.assertEquals(
+ len(self.service.ldap.search_s("cn=recursive1_coasts,cn=groups,dc=example,dc=com", 2, "(objectClass=*)", [])), 1)
+
+ self.assertEquals(
+ len(self.service.ldap.search_s("cn=groups,dc=example,dc=com", 0, "(|(apple-generateduid=right_coast)(apple-generateduid=left_coast))", [])), 2)
+
def test_ldapRecordCreation(self):
"""
Exercise _ldapResultToRecord(), which converts a dictionary
@@ -321,9 +470,9 @@
'apple-generateduid': [guid],
'uniqueMember':
[
- '9DC04A70-E6DD-11DF-9492-0800200C9A66',
- '9DC04A71-E6DD-11DF-9492-0800200C9A66',
- '6C6CD282-E6E3-11DF-9492-0800200C9A66'
+ 'uid=odtestamanda,cn=users,dc=example,dc=com',
+ 'uid=odtestbetty,cn=users,dc=example,dc=com',
+ 'cn=odtestgroupb,cn=groups,dc=example,dc=com',
],
'cn': ['odtestgrouptop']
}
@@ -331,9 +480,11 @@
self.service.recordType_groups)
self.assertEquals(record.guid, guid)
self.assertEquals(record.memberGUIDs(),
- set(['6C6CD282-E6E3-11DF-9492-0800200C9A66',
- '9DC04A70-E6DD-11DF-9492-0800200C9A66',
- '9DC04A71-E6DD-11DF-9492-0800200C9A66'])
+ set([
+ 'cn=odtestgroupb,cn=groups,dc=example,dc=com',
+ 'uid=odtestamanda,cn=users,dc=example,dc=com',
+ 'uid=odtestbetty,cn=users,dc=example,dc=com',
+ ])
)
# Resource with delegates and autoSchedule = True
@@ -433,46 +584,11 @@
and turns the results into records
"""
- self.service.ldap.addTestResults([
- (
- "uid=odtestamanda,cn=users,dc=example,dc=com",
- {
- 'uid': ['odtestamanda'],
- 'apple-generateduid': ['9DC04A70-E6DD-11DF-9492-0800200C9A66'],
- 'sn': ['Test'],
- 'mail': ['odtestamanda at example.com', 'alternate at example.com'],
- 'givenName': ['Amanda'],
- 'cn': ['Amanda Test']
- }
- ),
- (
- "uid=odtestbetty,cn=users,dc=example,dc=com",
- {
- 'uid': ['odtestbetty'],
- 'apple-generateduid': ['93A8F5C5-49D8-4641-840F-CD1903B0394C'],
- 'sn': ['Test'],
- 'mail': ['odtestbetty at example.com'],
- 'givenName': ['Betty'],
- 'cn': ['Betty Test']
- }
- ),
- (
- "uid=odtestcarlene,cn=users,dc=example,dc=com",
- {
- 'uid': ['odtestcarlene'],
- # Note: no guid here, to test this record is skipped
- 'sn': ['Test'],
- 'mail': ['odtestcarlene at example.com'],
- 'givenName': ['Carlene'],
- 'cn': ['Carlene Test']
- }
- ),
- ])
records = self.service.listRecords(self.service.recordType_users)
- self.assertEquals(len(records), 2)
+ self.assertEquals(len(records), 4)
self.assertEquals(
set([r.firstName for r in records]),
- set(["Amanda", "Betty"]) # Carlene is skipped because no guid in LDAP
+ set(["Amanda", "Betty", "Cyrus", "Wilfredo"]) # Carlene is skipped because no guid in LDAP
)
@inlineCallbacks
@@ -496,106 +612,6 @@
updater = GroupMembershipCacheUpdater(calendaruserproxy.ProxyDBService,
self.service, 30, 15, cache=cache, useExternalProxies=False)
- # Fake LDAP results for the getGroups() call performed within
- # updateCache(). Also include recursive groups to make sure we
- # handle that situation.
- self.service.ldap.addTestResults([
- (
- "cn=recursive1_coasts,cn=groups,dc=example,dc=com",
- {
- 'cn': ['recursive1_coasts'],
- 'apple-generateduid': ['recursive1_coasts'],
- 'uniqueMember': [
- 'cn=recursive2_coasts,cn=groups,dc=example,dc=com',
- 'uid=wsanchez,cn=users,dc=example,dc=com',
- ],
- }
- ),
- (
- "cn=recursive2_coasts,cn=groups,dc=example,dc=com",
- {
- 'cn': ['recursive2_coasts'],
- 'apple-generateduid': ['recursive2_coasts'],
- 'uniqueMember': [
- 'cn=recursive1_coasts,cn=groups,dc=example,dc=com',
- 'uid=cdaboo,cn=users,dc=example,dc=com',
- ],
- }
- ),
- (
- 'cn=both_coasts,cn=groups,dc=example,dc=com',
- {
- 'cn': ['both_coasts'],
- 'apple-generateduid': ['both_coasts'],
- 'uniqueMember': [
- 'cn=right_coast,cn=groups,dc=example,dc=com',
- 'cn=left_coast,cn=groups,dc=example,dc=com',
- ],
- }
- ),
- (
- 'cn=right_coast,cn=groups,dc=example,dc=com',
- {
- 'cn': ['right_coast'],
- 'apple-generateduid': ['right_coast'],
- 'uniqueMember': [
- 'uid=cdaboo,cn=users,dc=example,dc=com',
- ],
- }
- ),
- (
- 'cn=left_coast,cn=groups,dc=example,dc=com',
- {
- 'cn': ['left_coast'],
- 'apple-generateduid': ['left_coast'],
- 'uniqueMember': [
- 'uid=wsanchez,cn=users,dc=example,dc=com',
- 'uid=lecroy,cn=users,dc=example,dc=com',
- 'uid=dreid,cn=users,dc=example,dc=com',
- ],
- }
- ),
- ])
- self.service.ldap.addTestResults([
- (
- "cn=recursive2_coasts,cn=groups,dc=example,dc=com",
- {
- 'cn': ['recursive2_coasts'],
- 'apple-generateduid': ['recursive2_coasts'],
- 'uniqueMember': [
- 'cn=recursive1_coasts,cn=groups,dc=example,dc=com',
- 'uid=cdaboo,cn=users,dc=example,dc=com',
- ],
- }
- ),
- ])
- self.service.ldap.addTestResults([
- (
- 'cn=left_coast,cn=groups,dc=example,dc=com',
- {
- 'cn': ['left_coast'],
- 'apple-generateduid': ['left_coast'],
- 'uniqueMember': [
- 'uid=wsanchez,cn=users,dc=example,dc=com',
- 'uid=lecroy,cn=users,dc=example,dc=com',
- 'uid=dreid,cn=users,dc=example,dc=com',
- ],
- }
- ),
- ])
- self.service.ldap.addTestResults([
- (
- 'cn=right_coast,cn=groups,dc=example,dc=com',
- {
- 'cn': ['right_coast'],
- 'apple-generateduid': ['right_coast'],
- 'uniqueMember': [
- 'uid=cdaboo,cn=users,dc=example,dc=com',
- ],
- }
- ),
- ])
-
self.assertEquals((False, 8), (yield updater.updateCache()))
users = self.service.recordType_users
@@ -605,18 +621,6 @@
("wsanchez", set(["both_coasts", "left_coast", "recursive1_coasts", "recursive2_coasts"])),
]:
- # Fake LDAP results for the record lookup
- self.service.ldap.addTestResults([
- (
- "uid=%s,cn=users,dc=example,dc=com" % (shortName,),
- {
- 'uid': [shortName],
- 'cn': [shortName],
- 'apple-generateduid': [shortName],
- }
- ),
- ])
-
record = self.service.recordWithShortName(users, shortName)
self.assertEquals(groups, (yield record.cachedGroups()))
@@ -658,3 +662,14 @@
# No Match
dnStr = "uid=foo,cn=US ers ,dc=EXAMple,dc=com"
self.assertEquals(self.service.recordTypeForDN(dnStr), None)
+
+ def test_normalizeDN(self):
+ for input, expected in (
+ ("uid=foo,cn=users,dc=example,dc=com",
+ "uid=foo,cn=users,dc=example,dc=com"),
+ ("uid=FoO,cn=uSeRs,dc=ExAmPlE,dc=CoM",
+ "uid=foo,cn=users,dc=example,dc=com"),
+ ("uid=FoO , cn=uS eRs , dc=ExA mPlE , dc=CoM",
+ "uid=foo,cn=us ers,dc=exa mple,dc=com"),
+ ):
+ self.assertEquals(expected, normalizeDNstr(input))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20111110/7c66c926/attachment-0001.html>
More information about the calendarserver-changes
mailing list