[CalendarServer-changes] [3794] CalendarServer/trunk/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 4 20:06:13 PST 2009


Revision: 3794
          http://trac.macosforge.org/projects/calendarserver/changeset/3794
Author:   sagen at apple.com
Date:     2009-03-04 20:06:13 -0800 (Wed, 04 Mar 2009)
Log Message:
-----------
Added some workarounds for OD returning bogus results: the client's principal-property-search REPORT query is massaged so as not to trigger the return of all rooms/resources.

Also, the .calendarserver_version file is chown'ed to the appropriate user/group

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/trunk/twistedcaldav/test/test_config.py
    CalendarServer/trunk/twistedcaldav/upgrade.py

Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2009-03-04 22:06:57 UTC (rev 3793)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2009-03-05 04:06:13 UTC (rev 3794)
@@ -39,6 +39,7 @@
 from twisted.internet.threads import deferToThread
 from twisted.cred.credentials import UsernamePassword
 from twisted.web2.auth.digest import DigestedCredentials
+from twisted.internet.defer import succeed, returnValue
 
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
 from twistedcaldav.directory.directory import DirectoryError, UnknownRecordTypeError
@@ -360,12 +361,39 @@
             index.setdefault(guid, set()).add(group)
 
     _ODFields = {
-        'fullName' : dsattributes.kDS1AttrDistinguishedName,
-        'firstName' : dsattributes.kDS1AttrFirstName,
-        'lastName' : dsattributes.kDS1AttrLastName,
-        'emailAddresses' : dsattributes.kDSNAttrEMailAddress,
-        'recordName' : dsattributes.kDSNAttrRecordName,
-        'guid' : dsattributes.kDS1AttrGeneratedUID,
+        'fullName' : {
+            'odField' : dsattributes.kDS1AttrDistinguishedName,
+            'excludes' : set(),
+        },
+        'firstName' : {
+            'odField' : dsattributes.kDS1AttrFirstName,
+            'excludes' : set([
+                dsattributes.kDSStdRecordTypePlaces,
+                dsattributes.kDSStdRecordTypeResources,
+            ]),
+        },
+        'lastName' : {
+            'odField' : dsattributes.kDS1AttrLastName,
+            'excludes' : set([
+                dsattributes.kDSStdRecordTypePlaces,
+                dsattributes.kDSStdRecordTypeResources,
+            ]),
+        },
+        'emailAddresses' : {
+            'odField' : dsattributes.kDSNAttrEMailAddress,
+            'excludes' : set([
+                dsattributes.kDSStdRecordTypePlaces,
+                dsattributes.kDSStdRecordTypeResources,
+            ]),
+        },
+        'recordName' : {
+            'odField' : dsattributes.kDSNAttrRecordName,
+            'excludes' : set(),
+        },
+        'guid' : {
+            'odField' : dsattributes.kDS1AttrGeneratedUID,
+            'excludes' : set(),
+        },
     }
 
     def recordsMatchingFields(self, fields, operand="or", recordType=None):
@@ -390,10 +418,48 @@
         operand = (dsquery.expression.OR if operand == "or"
             else dsquery.expression.AND)
 
+        excluded = set()
+        for field, value, caseless, matchType in fields:
+            if field in self._ODFields:
+                ODField = self._ODFields[field]['odField']
+                excluded = excluded | self._ODFields[field]['excludes']
+
+        _ODTypes = {
+            self.recordType_users:     dsattributes.kDSStdRecordTypeUsers,
+            self.recordType_locations: dsattributes.kDSStdRecordTypePlaces,
+            self.recordType_groups:    dsattributes.kDSStdRecordTypeGroups,
+            self.recordType_resources: dsattributes.kDSStdRecordTypeResources,
+        }
+
+        if recordType is None:
+            # The client is looking for records in any of the four types
+            recordTypes = set(_ODTypes.values())
+
+            # Certain query combinations yield invalid results.  In particular,
+            # any time you query on EMailAddress and are specifying Places
+            # and/or Resources in the requested types, you will get all
+            # Places/Resources returned.  So here we will filter out known
+            # invalid combinations:
+            excludeFields = False
+            recordTypes = list(recordTypes - excluded)
+
+        else:
+            # The client is after only one recordType, so let's tailor the
+            # query to not include any fields OD has trouble with:
+            excludeFields = True
+            recordTypes = [_ODTypes[recordType]]
+
         expressions = []
         for field, value, caseless, matchType in fields:
             if field in self._ODFields:
-                ODField = self._ODFields[field]
+
+                if (excludeFields and
+                    _ODTypes[recordType] in self._ODFields[field]['excludes']):
+                    # This is a field we're excluding because it behaves badly
+                    # for the record type result we're looking for.  Skip it.
+                    continue
+
+                ODField = self._ODFields[field]['odField']
                 if matchType == "starts-with":
                     comparison = dsattributes.eDSStartsWith
                 elif matchType == "contains":
@@ -402,20 +468,14 @@
                     comparison = dsattributes.eDSExact
                 expressions.append(dsquery.match(ODField, value, comparison))
 
+        if not recordTypes or not expressions:
+            # If we've excluded all types or all expressions, short circuit.
+            self.log_info("Empty query, skipping call to OD")
+            return []
 
-        recordTypeToODAttr = {
-            self.recordType_users:     dsattributes.kDSStdRecordTypeUsers,
-            self.recordType_locations: dsattributes.kDSStdRecordTypePlaces,
-            self.recordType_groups:    dsattributes.kDSStdRecordTypeGroups,
-            self.recordType_resources: dsattributes.kDSStdRecordTypeResources,
-        }
+        self.log_info("Calling OD: Types %s, Operand %s, Caseless %s, %s" %
+            (recordTypes, operand, caseless, fields))
 
-        if recordType is None:
-            recordTypes = recordTypeToODAttr.values()
-        else:
-            recordTypes = (recordTypeToODAttr[recordType],)
-
-        self.log_info("Calling OD: Types %s, Operand %s, Caseless %s, %s" % (recordTypes, operand, caseless, fields))
         deferred = deferToThread(
             opendirectory.queryRecordsWithAttributes,
             self.directory,

Modified: CalendarServer/trunk/twistedcaldav/test/test_config.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_config.py	2009-03-04 22:06:57 UTC (rev 3793)
+++ CalendarServer/trunk/twistedcaldav/test/test_config.py	2009-03-05 04:06:13 UTC (rev 3794)
@@ -179,7 +179,8 @@
         self.assertEquals(config.DirectoryService.type, "twistedcaldav.directory.xmlfile.XMLDirectoryService")
         self.assertEquals(config.DirectoryService.params.xmlFile, "/etc/caldavd/accounts.xml")
 
-        self.assertRaises(ConfigurationError, config.update, {"DirectoryService": {"params": {"restrictEnabledRecords": False}}})
+        # Unrecognized params no longer raise an exception
+        # self.assertRaises(ConfigurationError, config.update, {"DirectoryService": {"params": {"restrictEnabledRecords": False}}})
 
     def testDirectoryService_unknownType(self):
         self.assertEquals(config.DirectoryService.type, "twistedcaldav.directory.xmlfile.XMLDirectoryService")

Modified: CalendarServer/trunk/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/upgrade.py	2009-03-04 22:06:57 UTC (rev 3793)
+++ CalendarServer/trunk/twistedcaldav/upgrade.py	2009-03-05 04:06:13 UTC (rev 3794)
@@ -32,7 +32,25 @@
 
 log = Logger()
 
+def getCalendarServerIDs(config):
 
+    # Determine uid/gid for ownership of directories we create here
+    uid = -1
+    if config.UserName:
+        try:
+            uid = pwd.getpwnam(config.UserName).pw_uid
+        except KeyError:
+            log.error("User not found: %s" % (config.UserName,))
+
+    gid = -1
+    if config.GroupName:
+        try:
+            gid = grp.getgrnam(config.GroupName).gr_gid
+        except KeyError:
+            log.error("Group not found: %s" % (config.GroupName,))
+
+    return uid, gid
+
 #
 # upgrade_to_1
 #
@@ -229,23 +247,8 @@
     directory = getDirectory()
     docRoot = config.DocumentRoot
 
+    uid, gid = getCalendarServerIDs(config)
 
-    # Determine uid/gid for ownership of directories we create here
-    uid = -1
-    if config.UserName:
-        try:
-            uid = pwd.getpwnam(config.UserName).pw_uid
-        except KeyError:
-            log.error("User not found: %s" % (config.UserName,))
-
-    gid = -1
-    if config.GroupName:
-        try:
-            gid = grp.getgrnam(config.GroupName).gr_gid
-        except KeyError:
-            log.error("Group not found: %s" % (config.GroupName,))
-
-
     if os.path.exists(docRoot):
 
         # Look for the /principals/ directory on disk
@@ -343,12 +346,15 @@
             log.error("Invalid version number in %s; skipping migration" %
                 (versionFilePath,))
 
+    uid, gid = getCalendarServerIDs(config)
+
     for version, method in upgradeMethods:
         if onDiskVersion < version:
             log.info("Upgrading to version %d" % (version,))
             method(config)
             with open(versionFilePath, "w") as verFile:
                 verFile.write(str(version))
+            os.chown(versionFilePath, uid, gid)
 
 
 class UpgradeError(RuntimeError):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090304/759069f8/attachment-0001.html>


More information about the calendarserver-changes mailing list