[CalendarServer-changes] [3645] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Thu Feb 5 18:44:01 PST 2009
Revision: 3645
http://trac.macosforge.org/projects/calendarserver/changeset/3645
Author: cdaboo at apple.com
Date: 2009-02-05 18:44:00 -0800 (Thu, 05 Feb 2009)
Log Message:
-----------
Merge support for multiple short names in directory records.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/provision/root.py
CalendarServer/trunk/conf/auth/accounts-test.xml
CalendarServer/trunk/conf/auth/accounts.dtd
CalendarServer/trunk/twistedcaldav/accesslog.py
CalendarServer/trunk/twistedcaldav/directory/apache.py
CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
CalendarServer/trunk/twistedcaldav/directory/calendar.py
CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py
CalendarServer/trunk/twistedcaldav/directory/directory.py
CalendarServer/trunk/twistedcaldav/directory/idirectory.py
CalendarServer/trunk/twistedcaldav/directory/principal.py
CalendarServer/trunk/twistedcaldav/directory/sqldb.py
CalendarServer/trunk/twistedcaldav/directory/sudo.py
CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py
CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py
CalendarServer/trunk/twistedcaldav/directory/test/test_principal.py
CalendarServer/trunk/twistedcaldav/directory/test/test_sudo.py
CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py
CalendarServer/trunk/twistedcaldav/directory/test/util.py
CalendarServer/trunk/twistedcaldav/directory/wiki.py
CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py
CalendarServer/trunk/twistedcaldav/directory/xmlfile.py
CalendarServer/trunk/twistedcaldav/static.py
Modified: CalendarServer/trunk/calendarserver/provision/root.py
===================================================================
--- CalendarServer/trunk/calendarserver/provision/root.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/calendarserver/provision/root.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -127,7 +127,7 @@
request.checkingSACL = True
principal = (yield request.locateResource(authzUser.children[0].children[0].data))
delattr(request, "checkingSACL")
- username = principal.record.shortName
+ username = principal.record.shortNames[0]
if RootResource.CheckSACL(username, self.saclService) != 0:
log.msg("User %r is not enabled with the %r SACL" % (username, self.saclService,))
Modified: CalendarServer/trunk/conf/auth/accounts-test.xml
===================================================================
--- CalendarServer/trunk/conf/auth/accounts-test.xml 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/conf/auth/accounts-test.xml 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -37,21 +37,22 @@
</user>
<user repeat="99">
<uid>user%02d</uid>
+ <uid>User %02d</uid>
<guid>user%02d</guid>
<password>user%02d</password>
<name>User %02d</name>
- <cuaddr>mailto:user%02d at example.com</cuaddr>
<first-name>User</first-name>
<last-name>%02d</last-name>
+ <cuaddr>mailto:user%02d at example.com</cuaddr>
</user>
<user repeat="10">
<uid>public%02d</uid>
<guid>public%02d</guid>
<password>public%02d</password>
<name>Public %02d</name>
- <cuaddr>mailto:public%02d at example.com</cuaddr>
<first-name>Public</first-name>
<last-name>%02d</last-name>
+ <cuaddr>mailto:public%02d at example.com</cuaddr>
</user>
<location repeat="10">
<uid>location%02d</uid>
Modified: CalendarServer/trunk/conf/auth/accounts.dtd
===================================================================
--- CalendarServer/trunk/conf/auth/accounts.dtd 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/conf/auth/accounts.dtd 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
<!--
-Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,16 +17,16 @@
<!ELEMENT accounts (user*, group*, resource*, location*) >
<!ATTLIST accounts realm CDATA "">
- <!ELEMENT user (uid, guid, password, name, cuaddr*, disable-calendar?)>
+ <!ELEMENT user (uid+, guid, password, name, first-name?, last-name?, email-address*, cuaddr*, disable-calendar?)>
<!ATTLIST user repeat CDATA "1">
- <!ELEMENT group (uid, guid, password, name, members, cuaddr*, disable-calendar?)>
+ <!ELEMENT group (uid+, guid, password, name, members, cuaddr*, disable-calendar?)>
<!ATTLIST group repeat CDATA "1">
- <!ELEMENT resource (uid, guid, password, name, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
+ <!ELEMENT resource (uid+, guid, password, name, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
<!ATTLIST resource repeat CDATA "1">
- <!ELEMENT location (uid, guid, password, name, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
+ <!ELEMENT location (uid+, guid, password, name, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
<!ATTLIST location repeat CDATA "1">
<!ELEMENT member (#PCDATA)>
Modified: CalendarServer/trunk/twistedcaldav/accesslog.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/accesslog.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/accesslog.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2008 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -84,9 +84,9 @@
record = request.site.resource.getDirectory().recordWithUID(uid)
if record:
if record.recordType == DirectoryService.recordType_users:
- return record.shortName
+ return record.shortNames[0]
else:
- return "(%s)%s" % (record.recordType, record.shortName,)
+ return "(%s)%s" % (record.recordType, record.shortNames[0],)
else:
return uid
Modified: CalendarServer/trunk/twistedcaldav/directory/apache.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/apache.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/apache.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -143,7 +143,7 @@
service = service,
recordType = recordType,
guid = None,
- shortName = shortName,
+ shortNames = (shortName,),
fullName = None,
firstName = None,
lastName = None,
Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -170,11 +170,10 @@
):
yield GUID
- def _calendarUserAddresses(self, recordType, recordName, recordData):
+ def _calendarUserAddresses(self, recordType, recordData):
"""
Extract specific attributes from the directory record for use as calendar user address.
- @param recordName: a C{str} containing the record name being operated on.
@param recordData: a C{dict} containing the attributes retrieved from the directory.
@return: a C{set} of C{str} for each expanded calendar user address.
"""
@@ -475,12 +474,17 @@
for (recordShortName, value) in results:
# Now get useful record info.
- recordGUID = value.get(dsattributes.kDS1AttrGeneratedUID)
- recordFullName = value.get(dsattributes.kDS1AttrDistinguishedName)
- recordFirstName = value.get(dsattributes.kDS1AttrFirstName)
- recordLastName = value.get(dsattributes.kDS1AttrLastName)
+ recordGUID = value.get(dsattributes.kDS1AttrGeneratedUID)
+ recordShortNames = value.get(dsattributes.kDSNAttrRecordName)
+ if isinstance(recordShortNames, str):
+ recordShortNames = (recordShortNames,)
+ else:
+ recordShortNames = tuple(recordShortNames) if recordShortNames else ()
+ recordFullName = value.get(dsattributes.kDS1AttrDistinguishedName)
+ recordFirstName = value.get(dsattributes.kDS1AttrFirstName)
+ recordLastName = value.get(dsattributes.kDS1AttrLastName)
recordEmailAddress = value.get(dsattributes.kDSNAttrEMailAddress)
- recordNodeName = value.get(dsattributes.kDSNAttrMetaNodeLocation)
+ recordNodeName = value.get(dsattributes.kDSNAttrMetaNodeLocation)
if not recordGUID:
self.log_debug("Record (%s)%s in node %s has no GUID; ignoring."
@@ -520,7 +524,7 @@
# Get calendar user addresses from directory record.
if enabledForCalendaring:
- calendarUserAddresses = self._calendarUserAddresses(recordType, recordShortName, value)
+ calendarUserAddresses = self._calendarUserAddresses(recordType, value)
else:
calendarUserAddresses = ()
@@ -568,7 +572,7 @@
recordType = recordType,
guid = recordGUID,
nodeName = recordNodeName,
- shortName = recordShortName,
+ shortNames = recordShortNames,
fullName = recordFullName,
firstName = recordFirstName,
lastName = recordLastName,
@@ -584,39 +588,48 @@
def disableRecord(record):
self.log_warn("Record disabled due to conflict (record name and GUID must match): %s" % (record,))
- shortName = record.shortName
- guid = record.guid
+ shortNames = record.shortNames
+ guid = record.guid
- disabledNames.add(shortName)
+ disabledNames.update(shortNames)
disabledGUIDs.add(guid)
- if shortName in records:
- del records[shortName]
+ for shortName in shortNames:
+ if shortName in records:
+ del records[shortName]
if guid in guids:
del guids[guid]
# Check for disabled items
- if record.shortName in disabledNames or record.guid in disabledGUIDs:
+ if disabledNames.intersection(record.shortNames) or record.guid in disabledGUIDs:
disableRecord(record)
else:
# Check for duplicate items and disable all names/guids for mismatched duplicates.
- if record.shortName in records:
- existing_record = records[record.shortName]
- elif record.guid in guids:
- existing_record = guids[record.guid]
- else:
- existing_record = None
+ existing_records = set()
+ for shortName in record.shortNames:
+ if shortName in records:
+ existing_records.add(records[shortName])
+ if record.guid in guids:
+ existing_records.add(guids[record.guid])
- if existing_record is not None:
- if record.guid != existing_record.guid or record.shortName != existing_record.shortName:
- disableRecord(existing_record)
+ if existing_records:
+ disable = False
+ for existing_record in existing_records:
+ if record.guid != existing_record.guid or record.shortNames != existing_record.shortNames:
+ disable = True
+ break
+
+ if disable:
+ for existing_record in existing_records:
+ disableRecord(existing_record)
+ if existing_record.enabledForCalendaring:
+ enabled_count -= 1
disableRecord(record)
-
- if existing_record.enabledForCalendaring:
- enabled_count -= 1
- if record.shortName not in disabledNames:
- records[record.shortName] = guids[record.guid] = record
+ if len(disabledNames.intersection(record.shortNames)) == 0:
+ guids[record.guid] = record
+ for shortName in record.shortNames:
+ records[shortName] = record
self.log_debug("Added record %s to OD record cache" % (record,))
# Do group indexing if needed
@@ -701,6 +714,7 @@
def _queryDirectory(self, recordType, lookup=None):
attrs = [
dsattributes.kDS1AttrGeneratedUID,
+ dsattributes.kDSNAttrRecordName,
dsattributes.kDS1AttrDistinguishedName,
dsattributes.kDS1AttrFirstName,
dsattributes.kDS1AttrLastName,
@@ -817,7 +831,7 @@
Open Directory implementation of L{IDirectoryRecord}.
"""
def __init__(
- self, service, recordType, guid, nodeName, shortName, fullName,
+ self, service, recordType, guid, nodeName, shortNames, fullName,
firstName, lastName, emailAddresses,
calendarUserAddresses, autoSchedule, enabledForCalendaring,
memberGUIDs, proxyGUIDs, readOnlyProxyGUIDs,
@@ -826,7 +840,7 @@
service = service,
recordType = recordType,
guid = guid,
- shortName = shortName,
+ shortNames = shortNames,
fullName = fullName,
firstName = firstName,
lastName = lastName,
@@ -852,7 +866,7 @@
self.service.guid,
location,
self.guid,
- self.shortName,
+ ",".join(self.shortNames),
self.fullName
)
@@ -875,7 +889,11 @@
for guid in self._proxyGUIDs:
proxyRecord = self.service.recordWithGUID(guid)
if proxyRecord is None:
- self.log_error("No record for proxy in %s with GUID %s" % (self.shortName, guid))
+ self.log_error("No record for proxy in (%s)%s with GUID %s" % (
+ self.recordType,
+ self.shortNames[0],
+ guid,
+ ))
else:
yield proxyRecord
@@ -892,7 +910,11 @@
for guid in self._readOnlyProxyGUIDs:
proxyRecord = self.service.recordWithGUID(guid)
if proxyRecord is None:
- self.log_error("No record for proxy in %s with GUID %s" % (self.shortName, guid))
+ self.log_error("No record for proxy in (%s)%s with GUID %s" % (
+ self.recordType,
+ self.shortNames[0],
+ guid,
+ ))
else:
yield proxyRecord
@@ -913,13 +935,13 @@
# Check with directory services
try:
- if opendirectory.authenticateUserBasic(self.service.directory, self.nodeName, self.shortName, credentials.password):
+ if opendirectory.authenticateUserBasic(self.service.directory, self.nodeName, self.shortNames[0], credentials.password):
# Cache the password to avoid future DS queries
self.password = credentials.password
return True
except opendirectory.ODError, e:
self.log_error("Open Directory (node=%s) error while performing basic authentication for user %s: %s"
- % (self.service.realmName, self.shortName, e))
+ % (self.service.realmName, self.shortNames[0], e))
return False
@@ -942,7 +964,7 @@
self.log_error(
"Open Directory (node=%s) error while performing digest authentication for user %s: "
"missing digest response field: %s in: %s"
- % (self.service.realmName, self.shortName, e, credentials.fields)
+ % (self.service.realmName, self.shortNames[0], e, credentials.fields)
)
return False
@@ -956,7 +978,7 @@
if opendirectory.authenticateUserDigest(
self.service.directory,
self.nodeName,
- self.shortName,
+ self.shortNames[0],
challenge,
response,
credentials.method
@@ -977,12 +999,12 @@
Challenge: %s
Response: %s
Method: %s
-""" % (self.nodeName, self.shortName, challenge, response, credentials.method))
+""" % (self.nodeName, self.shortNames[0], challenge, response, credentials.method))
except opendirectory.ODError, e:
self.log_error(
"Open Directory (node=%s) error while performing digest authentication for user %s: %s"
- % (self.service.realmName, self.shortName, e)
+ % (self.service.realmName, self.shortNames[0], e)
)
return False
Modified: CalendarServer/trunk/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendar.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/calendar.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -165,11 +165,14 @@
def listChildren(self):
if config.EnablePrincipalListings:
- return (
- record.shortName
- for record in self.directory.listRecords(self.recordType)
- if record.enabledForCalendaring
- )
+
+ def _recordShortnameExpand():
+ for record in self.directory.listRecords(self.recordType):
+ if record.enabledForCalendaring:
+ for shortName in record.shortNames:
+ yield shortName
+
+ return _recordShortnameExpand()
else:
# Not a listable collection
raise HTTPError(responsecode.FORBIDDEN)
Modified: CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -239,7 +239,7 @@
"""---------------------\n"""
"""GUID: %s\n""" % (self.parent.record.guid,),
"""Record type: %s\n""" % (self.parent.record.recordType,),
- """Short name: %s\n""" % (self.parent.record.shortName,),
+ """Short names: %s\n""" % (",".join(self.parent.record.shortNames,)),
"""Full name: %s\n""" % (self.parent.record.fullName,),
"""Principal UID: %s\n""" % (self.parent.principalUID(),),
"""Principal URL: %s\n""" % (format_link(self.parent.principalURL()),),
Modified: CalendarServer/trunk/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/directory.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/directory.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2008 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -251,22 +251,22 @@
self.service.guid,
self.service.realmName,
self.guid,
- self.shortName,
+ ",".join(self.shortNames),
self.fullName
)
def __init__(
- self, service, recordType, guid, shortName, fullName,
+ self, service, recordType, guid, shortNames, fullName,
firstName, lastName, emailAddresses,
calendarUserAddresses, autoSchedule, enabledForCalendaring=True,
uid=None,
):
assert service.realmName is not None
assert recordType
- assert shortName
+ assert shortNames and isinstance(shortNames, tuple)
if not guid:
- guid = uuidFromName(service.guid, "%s:%s" % (recordType, shortName))
+ guid = uuidFromName(service.guid, "%s:%s" % (recordType, ",".join(shortNames)))
if uid is None:
uid = guid
@@ -281,7 +281,7 @@
self.recordType = recordType
self.guid = guid
self.uid = uid
- self.shortName = shortName
+ self.shortNames = shortNames
self.fullName = fullName
self.firstName = firstName
self.lastName = lastName
@@ -294,7 +294,7 @@
if not isinstance(other, DirectoryRecord):
return NotImplemented
- for attr in ("service", "recordType", "shortName", "guid"):
+ for attr in ("service", "recordType", "shortNames", "guid"):
diff = cmp(getattr(self, attr), getattr(other, attr))
if diff != 0:
return diff
@@ -302,7 +302,7 @@
def __hash__(self):
h = hash(self.__class__)
- for attr in ("service", "recordType", "shortName", "guid",
+ for attr in ("service", "recordType", "shortNames", "guid",
"enabledForCalendaring"):
h = (h + hash(getattr(self, attr))) & sys.maxint
Modified: CalendarServer/trunk/twistedcaldav/directory/idirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/idirectory.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/idirectory.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -94,7 +94,7 @@
recordType = Attribute("The type of this record.")
guid = Attribute("The GUID of this record.")
uid = Attribute("The UID of this record.")
- shortName = Attribute("The name of this record.")
+ shortNames = Attribute("The names for this record.")
fullName = Attribute("The full name of this record.")
firstName = Attribute("The first name of this record.")
lastName = Attribute("The last name of this record.")
Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/principal.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -33,6 +33,7 @@
from cgi import escape
from urllib import unquote
from urlparse import urlparse
+import itertools
from twisted.python.failure import Failure
from twisted.internet.defer import inlineCallbacks, returnValue
@@ -380,7 +381,13 @@
def listChildren(self):
if config.EnablePrincipalListings:
- return (record.shortName for record in self.directory.listRecords(self.recordType))
+
+ def _recordShortnameExpand():
+ for record in self.directory.listRecords(self.recordType):
+ for shortName in record.shortNames:
+ yield shortName
+
+ return _recordShortnameExpand()
else:
# Not a listable collection
raise HTTPError(responsecode.FORBIDDEN)
@@ -491,12 +498,12 @@
self.parent = parent
self._url = url
- self._alternate_urls = (
- joinURL(parent.parent.principalCollectionURL(), record.recordType, record.shortName) + slash,
- )
+ self._alternate_urls = tuple([
+ joinURL(parent.parent.principalCollectionURL(), record.recordType, shortName) + slash for shortName in record.shortNames
+ ])
def __str__(self):
- return "(%s) %s" % (self.record.recordType, self.record.shortName)
+ return "(%s) %s" % (self.record.recordType, self.record.shortNames[0])
def deadProperties(self):
if not hasattr(self, "_dead_properties"):
@@ -536,7 +543,7 @@
"""---------------------\n"""
"""GUID: %s\n""" % (self.record.guid,),
"""Record type: %s\n""" % (self.record.recordType,),
- """Short name: %s\n""" % (self.record.shortName,),
+ """Short names: %s\n""" % (",".join(self.record.shortNames),),
"""Full name: %s\n""" % (self.record.fullName,),
"""First name: %s\n""" % (self.record.firstName,),
"""Last name: %s\n""" % (self.record.lastName,),
@@ -563,7 +570,7 @@
if self.record.fullName:
return self.record.fullName
else:
- return self.record.shortName
+ return self.record.shortNames[0]
##
# ACL
@@ -749,7 +756,7 @@
"""---------------------\n"""
"""GUID: %s\n""" % (self.record.guid,),
"""Record type: %s\n""" % (self.record.recordType,),
- """Short name: %s\n""" % (self.record.shortName,),
+ """Short names: %s\n""" % (",".join(self.record.shortNames),),
"""Full name: %s\n""" % (self.record.fullName,),
"""First name: %s\n""" % (self.record.firstName,),
"""Last name: %s\n""" % (self.record.lastName,),
@@ -905,20 +912,17 @@
return "".join(genlist())
def format_principals(principals):
- def sort(a, b):
- def sortkey(principal):
+ def recordKey(principal):
+ try:
+ record = principal.record
+ except AttributeError:
try:
- record = principal.record
- except AttributeError:
- try:
- record = principal.parent.record
- except:
- return None
+ record = principal.parent.record
+ except:
+ return None
- return [record.recordType, record.shortName]
+ return (record.recordType, record.shortNames[0])
- return cmp(sortkey(a), sortkey(b))
-
def describe(principal):
if hasattr(principal, "record"):
return " - %s" % (principal.record.fullName,)
@@ -928,7 +932,7 @@
return format_list(
"""<a href="%s">%s%s</a>"""
% (principal.principalURL(), escape(str(principal)), describe(principal))
- for principal in sorted(principals, sort)
+ for principal in sorted(principals, key=recordKey)
)
def format_link(url):
Modified: CalendarServer/trunk/twistedcaldav/directory/sqldb.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/sqldb.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/sqldb.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -173,7 +173,7 @@
def _add_to_db(self, record):
# Do regular account entry
recordType = record.recordType
- shortName = record.shortName
+ shortName = record.shortNames[0]
guid = record.guid
password = record.password
name = record.name
@@ -348,7 +348,7 @@
service = service,
recordType = recordType,
guid = guid,
- shortName = shortName,
+ shortNames = (shortName,),
fullName = name,
firstName = None,
lastName = None,
Modified: CalendarServer/trunk/twistedcaldav/directory/sudo.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/sudo.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/sudo.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -127,7 +127,7 @@
service=service,
recordType=recordType,
guid=None,
- shortName=shortName,
+ shortNames=(shortName,),
fullName=shortName,
firstName="",
lastName="",
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@
recordType = DirectoryService.recordType_users,
guid = "B1F93EB1-DA93-4772-9141-81C250DA35B3",
nodeName = "/LDAPv2/127.0.0.1",
- shortName = "user",
+ shortNames = ("user",),
fullName = "Some user",
firstName = "Some",
lastName = "User",
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2008 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -675,6 +675,7 @@
attrs = {
dsattributes.kDS1AttrDistinguishedName: fullName,
dsattributes.kDS1AttrGeneratedUID: guid,
+ dsattributes.kDSNAttrRecordName: shortName,
dsattributes.kDSNAttrEMailAddress: email,
dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
}
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_principal.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_principal.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -102,7 +102,7 @@
self.assertEquals(set((provisioningURL,)), set(pc.principalCollectionURL() for pc in principalCollections))
shortNames = set(typeResource.listChildren())
- self.assertEquals(shortNames, set(r.shortName for r in directory.listRecords(recordType)))
+ self.assertEquals(shortNames, set(r.shortNames[0] for r in directory.listRecords(recordType)))
for shortName in shortNames:
#print " -> %s" % (shortName,)
@@ -131,7 +131,7 @@
DirectoryPrincipalProvisioningResource.principalForShortName()
"""
for provisioningResource, recordType, recordResource, record in self._allRecords():
- principal = provisioningResource.principalForShortName(recordType, record.shortName)
+ principal = provisioningResource.principalForShortName(recordType, record.shortNames[0])
self.failIf(principal is None)
self.assertEquals(record, principal.record)
@@ -143,7 +143,7 @@
provisioningResource = self.principalRootResources[directory.__class__.__name__]
for user in directory.listRecords(DirectoryService.recordType_users):
- userResource = provisioningResource.principalForUser(user.shortName)
+ userResource = provisioningResource.principalForUser(user.shortNames[0])
self.failIf(userResource is None)
self.assertEquals(user, userResource.record)
@@ -193,7 +193,7 @@
self.failIf(principal is None)
if record.enabledForCalendaring:
self.assertEquals(record.autoSchedule, principal.autoSchedule())
- if record.shortName == "gemini":
+ if record.shortNames[0] == "gemini":
self.assertTrue(principal.autoSchedule())
else:
self.assertFalse(principal.autoSchedule())
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_sudo.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_sudo.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_sudo.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -53,8 +53,8 @@
def test_listRecords(self):
for record in self.service().listRecords(self.recordType):
- self.failUnless(record.shortName in self.sudoers)
- self.assertEqual(self.sudoers[record.shortName]['password'],
+ self.failUnless(record.shortNames[0] in self.sudoers)
+ self.assertEqual(self.sudoers[record.shortNames[0]]['password'],
record.password)
def test_recordWithShortName(self):
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -116,7 +116,7 @@
( DirectoryService.recordType_resources , () ),
):
self.assertEquals(
- set(r.shortName for r in service.listRecords(recordType)),
+ set(r.shortNames[0] for r in service.listRecords(recordType)),
set(expectedRecords)
)
@@ -143,7 +143,7 @@
( DirectoryService.recordType_resources , () ),
):
self.assertEquals(
- set(r.shortName for r in service.listRecords(recordType)),
+ set(r.shortNames[0] for r in service.listRecords(recordType)),
set(expectedRecords)
)
self.assertTrue(service.recordWithShortName(DirectoryService.recordType_locations, "my office").autoSchedule)
@@ -166,7 +166,7 @@
)
def _findRecords():
- set(r.shortName for r in service.listRecords(DirectoryService.recordType_users))
+ set(r.shortNames[0] for r in service.listRecords(DirectoryService.recordType_users))
self.assertRaises(ValueError, _findRecords)
@@ -198,7 +198,7 @@
( DirectoryService.recordType_resources , () ),
):
self.assertEquals(
- set(r.shortName for r in service.listRecords(recordType)),
+ set(r.shortNames[0] for r in service.listRecords(recordType)),
set(expectedRecords)
)
self.assertTrue(service.recordWithShortName(DirectoryService.recordType_groups, "enabled").enabledForCalendaring)
@@ -222,7 +222,7 @@
)
def _findRecords():
- set(r.shortName for r in service.listRecords(DirectoryService.recordType_users))
+ set(r.shortNames[0] for r in service.listRecords(DirectoryService.recordType_users))
self.assertRaises(ValueError, _findRecords)
@@ -257,7 +257,7 @@
( DirectoryService.recordType_resources , () ),
):
self.assertEquals(
- set(r.shortName for r in service.listRecords(recordType)),
+ set(r.shortNames[0] for r in service.listRecords(recordType)),
set(expectedRecords)
)
self.assertEqual(set([("users", "test",)],), service.recordWithShortName(DirectoryService.recordType_locations, "my office")._proxies)
@@ -283,6 +283,6 @@
)
def _findRecords():
- set(r.shortName for r in service.listRecords(DirectoryService.recordType_users))
+ set(r.shortNames[0] for r in service.listRecords(DirectoryService.recordType_users))
self.assertRaises(ValueError, _findRecords)
Modified: CalendarServer/trunk/twistedcaldav/directory/test/util.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/util.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/test/util.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -163,7 +163,7 @@
for group, info in self.groups.iteritems():
prefix = info.get("prefix", "")
groupRecord = service.recordWithShortName(prefix + DirectoryService.recordType_groups, group)
- result = set((m.recordType, prefix + m.shortName) for m in groupRecord.members())
+ result = set((m.recordType, prefix + m.shortNames[0]) for m in groupRecord.members())
expected = set(self.groups[group]["members"])
self.assertEquals(
result, expected,
@@ -187,7 +187,7 @@
for shortName, info in data.iteritems():
prefix = info.get("prefix", "")
record = service.recordWithShortName(prefix + recordType, shortName)
- result = set(prefix + g.shortName for g in record.groups())
+ result = set(prefix + g.shortNames[0] for g in record.groups())
expected = set(g for g in self.groups if (record.recordType, shortName) in self.groups[g]["members"])
self.assertEquals(
result, expected,
@@ -204,7 +204,7 @@
continue
assert records is not None, "%r(%r) returned None" % (service.listRecords, recordType)
for record in records:
- names.add(prefix + record.shortName)
+ names.add(prefix + record.shortNames[0])
return names
@@ -238,7 +238,7 @@
else:
prefix = ""
- self.assertEquals(prefix + record.shortName, shortName)
+ self.assertEquals(prefix + record.shortNames[0], shortName)
self.assertEquals(set(record.calendarUserAddresses), addresses)
if value("guid"):
Modified: CalendarServer/trunk/twistedcaldav/directory/wiki.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/wiki.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/wiki.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -121,7 +121,7 @@
recordType=recordType,
guid=None,
uid="%s%s" % (WikiDirectoryService.UIDPrefix, shortName),
- shortName=shortName,
+ shortNames=(shortName,),
fullName=shortName,
firstName="",
lastName="",
@@ -146,7 +146,7 @@
wikiConfig = config.Authentication.Wiki
userID = "unauthenticated"
- wikiID = resource.record.shortName
+ wikiID = resource.record.shortNames[0]
try:
url = str(request.authzUser.children[0])
Modified: CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -106,22 +106,22 @@
def updateMembership(group):
# Update group membership
for recordType, shortName in group.members:
- item = self.items[recordType].get(shortName, None)
+ item = self.items[recordType].get(shortName)
if item is not None:
- item.groups.add(group.shortName)
+ item.groups.add(group.shortNames[0])
def updateProxyFor(proxier):
# Update proxy membership
for recordType, shortName in proxier.proxies:
- item = self.items[recordType].get(shortName, None)
+ item = self.items[recordType].get(shortName)
if item is not None:
- item.proxyFor.add((proxier.recordType, proxier.shortName))
+ item.proxyFor.add((proxier.recordType, proxier.shortNames[0]))
# Update read-only proxy membership
for recordType, shortName in proxier.readOnlyProxies:
- item = self.items[recordType].get(shortName, None)
+ item = self.items[recordType].get(shortName)
if item is not None:
- item.readOnlyProxyFor.add((proxier.recordType, proxier.shortName))
+ item.readOnlyProxyFor.add((proxier.recordType, proxier.shortNames[0]))
for child in node._get_childNodes():
child_name = child._get_localName()
@@ -143,9 +143,9 @@
if repeat > 1:
for i in xrange(1, repeat+1):
newprincipal = principal.repeat(i)
- self.items[recordType][newprincipal.shortName] = newprincipal
+ self.items[recordType][newprincipal.shortNames[0]] = newprincipal
else:
- self.items[recordType][principal.shortName] = principal
+ self.items[recordType][principal.shortNames[0]] = principal
# Do reverse membership mapping only after all records have been read in
for records in self.items.itervalues():
@@ -162,7 +162,7 @@
@param recordType: record type for directory entry.
"""
self.recordType = recordType
- self.shortName = None
+ self.shortNames = []
self.guid = None
self.password = None
self.name = None
@@ -185,10 +185,12 @@
done on them with the numeric value provided.
@param ctr: an integer to substitute into text.
"""
- if self.shortName.find("%") != -1:
- shortName = self.shortName % ctr
- else:
- shortName = self.shortName
+ shortNames = []
+ for shortName in self.shortNames:
+ if shortName.find("%") != -1:
+ shortNames.append(shortName % ctr)
+ else:
+ shortNames.append(shortName)
if self.guid and self.guid.find("%") != -1:
guid = self.guid % ctr
else:
@@ -223,7 +225,7 @@
calendarUserAddresses.add(cuaddr)
result = XMLAccountRecord(self.recordType)
- result.shortName = shortName
+ result.shortNames = shortNames
result.guid = guid
result.password = password
result.name = name
@@ -245,7 +247,7 @@
continue
elif child_name == ELEMENT_SHORTNAME:
if child.firstChild is not None:
- self.shortName = child.firstChild.data.encode("utf-8")
+ self.shortNames.append(child.firstChild.data.encode("utf-8"))
elif child_name == ELEMENT_GUID:
if child.firstChild is not None:
guid = child.firstChild.data.encode("utf-8")
Modified: CalendarServer/trunk/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/xmlfile.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/directory/xmlfile.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2008 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -64,30 +64,30 @@
return recordTypes
def listRecords(self, recordType):
- for entryShortName, xmlPrincipal in self._entriesForRecordType(recordType):
+ for _ignore_entryShortName, xmlPrincipal in self._entriesForRecordType(recordType):
yield XMLDirectoryRecord(
service = self,
recordType = recordType,
- shortName = entryShortName,
+ shortNames = tuple(xmlPrincipal.shortNames),
xmlPrincipal = xmlPrincipal,
)
def recordWithShortName(self, recordType, shortName):
- for entryShortName, xmlprincipal in self._entriesForRecordType(recordType):
- if entryShortName == shortName:
+ for _ignore_entryShortName, xmlPrincipal in self._entriesForRecordType(recordType):
+ if shortName in xmlPrincipal.shortNames:
return XMLDirectoryRecord(
service = self,
recordType = recordType,
- shortName = entryShortName,
- xmlPrincipal = xmlprincipal,
+ shortNames = tuple(xmlPrincipal.shortNames),
+ xmlPrincipal = xmlPrincipal,
)
return None
def _entriesForRecordType(self, recordType):
try:
- for entry in sorted(self._accounts()[recordType].itervalues(), key=lambda x: x.shortName):
- yield entry.shortName, entry
+ for shortName, entry in sorted(self._accounts()[recordType].iteritems(), key=lambda x: x[0]):
+ yield shortName, entry
except KeyError:
return
@@ -108,12 +108,12 @@
"""
XML based implementation implementation of L{IDirectoryRecord}.
"""
- def __init__(self, service, recordType, shortName, xmlPrincipal):
+ def __init__(self, service, recordType, shortNames, xmlPrincipal):
super(XMLDirectoryRecord, self).__init__(
service = service,
recordType = recordType,
guid = xmlPrincipal.guid,
- shortName = shortName,
+ shortNames = shortNames,
fullName = xmlPrincipal.name,
firstName = xmlPrincipal.firstName,
lastName = xmlPrincipal.lastName,
Modified: CalendarServer/trunk/twistedcaldav/static.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/static.py 2009-02-06 01:22:24 UTC (rev 3644)
+++ CalendarServer/trunk/twistedcaldav/static.py 2009-02-06 02:44:00 UTC (rev 3645)
@@ -611,7 +611,7 @@
# Pre 2.0: All in one directory
self.fp.child(name),
# Pre 1.2: In types hierarchy instead of the GUID hierarchy
- self.parent.getChild(record.recordType).fp.child(record.shortName),
+ self.parent.getChild(record.recordType).fp.child(record.shortNames[0]),
):
if oldPath.exists():
# The child exists at an old location. Move to new location.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090205/b4d361df/attachment-0001.html>
More information about the calendarserver-changes
mailing list