[CalendarServer-changes] [3010] CalendarServer/branches/users/sagen/principal-property-search-2995

source_changes at macosforge.org source_changes at macosforge.org
Wed Sep 17 14:18:57 PDT 2008


Revision: 3010
          http://trac.macosforge.org/projects/calendarserver/changeset/3010
Author:   sagen at apple.com
Date:     2008-09-17 14:18:56 -0700 (Wed, 17 Sep 2008)
Log Message:
-----------
Checkpoint of progress: recordTypes to directory-search for are determined by resource (i.e., /principals/ would search all recordTypes, whereas /principals/users/ would search for only user principals)

Modified Paths:
--------------
    CalendarServer/branches/users/sagen/principal-property-search-2995/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch
    CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/aggregate.py
    CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/directory.py
    CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/principal.py

Modified: CalendarServer/branches/users/sagen/principal-property-search-2995/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch
===================================================================
--- CalendarServer/branches/users/sagen/principal-property-search-2995/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch	2008-09-17 17:37:45 UTC (rev 3009)
+++ CalendarServer/branches/users/sagen/principal-property-search-2995/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch	2008-09-17 21:18:56 UTC (rev 3010)
@@ -22,7 +22,7 @@
      # Get a single DAV:prop element from the REPORT request body
      propertiesForResource = None
      propElement = None
-@@ -93,73 +99,147 @@
+@@ -93,73 +99,155 @@
          else:
              return False
          
@@ -102,7 +102,10 @@
 +        for props, match in propertySearches:
 +            nonDirectoryProps = []
 +            for prop in props:
-+                fieldName = self.propertyToField(prop)
++                try:
++                    fieldName = self.propertyToField(prop)
++                except AttributeError:
++                    fieldName = None
 +                if fieldName:
 +                    fields.append((fieldName, match))
 +                else:
@@ -193,8 +196,13 @@
 +
 +
 +        elif fields: # search the directory
++            try:
++                recordType = self.recordType
++            except AttributeError:
++                recordType = None
++
 +            for record in self.directory.recordsMatchingFields(fields,
-+                operand=operand):
++                operand=operand, recordType=recordType):
 +
 +                resource = self.principalForRecord(record)
 +                url = resource.url()
@@ -216,7 +224,7 @@
                      yield d
                      d = d.getResult()
                      if d:
-@@ -167,18 +247,26 @@
+@@ -167,18 +255,26 @@
                          matchcount += 1
                          if matchcount > max_number_of_matches:
                              raise NumberOfMatchesWithinLimits

Modified: CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/aggregate.py
===================================================================
--- CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/aggregate.py	2008-09-17 17:37:45 UTC (rev 3009)
+++ CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/aggregate.py	2008-09-17 21:18:56 UTC (rev 3010)
@@ -104,8 +104,13 @@
         return self._queryAll("recordWithCalendarUserAddress", address)
 
     def recordsMatchingFields(self, fields, caseInsensitive=True, operand="or",
-        recordType=DirectoryService.recordType_users):
-        for service in self._recordTypes.values():
+        recordType=None):
+        if recordType:
+            services = (self.serviceForRecordType(recordType),)
+        else:
+            services = set(self._recordTypes.values())
+
+        for service in services:
             for record in service.recordsMatchingFields(fields,
                 caseInsensitive=caseInsensitive, operand=operand,
                 recordType=recordType):

Modified: CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/appleopendirectory.py	2008-09-17 17:37:45 UTC (rev 3009)
+++ CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/appleopendirectory.py	2008-09-17 21:18:56 UTC (rev 3010)
@@ -462,13 +462,27 @@
 
 
     _ODFields = {
+        'fullName' : dsattributes.kDS1AttrDistinguishedName,
         'firstName' : dsattributes.kDS1AttrFirstName,
         'lastName' : dsattributes.kDS1AttrLastName,
         'emailAddress' : dsattributes.kDSNAttrEMailAddress,
     }
 
+    _toODRecordTypes = {
+        DirectoryService.recordType_users :
+            dsattributes.kDSStdRecordTypeUsers,
+        DirectoryService.recordType_locations :
+            dsattributes.kDSStdRecordTypeLocations,
+        DirectoryService.recordType_groups :
+            dsattributes.kDSStdRecordTypeGroups,
+        DirectoryService.recordType_resources :
+            dsattributes.kDSStdRecordTypeResources,
+    }
+
+    _fromODRecordTypes = dict([(b, a) for a, b in _toODRecordTypes.iteritems()])
+
     def recordsMatchingFields(self, fields, caseInsensitive=True, operand="or",
-        recordType=DirectoryService.recordType_users):
+        recordType=None):
 
         comparison = dsattributes.eDSStartsWith
         operand = (dsquery.expression.OR if operand == "or"
@@ -481,50 +495,65 @@
                 expressions.append(dsquery.match(ODField, value, comparison))
 
 
-        results = opendirectory.queryRecordsWithAttributes(
-            self.directory,
-            dsquery.expression(operand, expressions).generate(),
-            caseInsensitive,
-            dsattributes.kDSStdRecordTypeUsers,
-            [
-                dsattributes.kDS1AttrGeneratedUID,
-                dsattributes.kDS1AttrFirstName,
-                dsattributes.kDS1AttrLastName,
-                dsattributes.kDSNAttrEMailAddress,
-                dsattributes.kDS1AttrDistinguishedName,
-                dsattributes.kDSNAttrMetaNodeLocation,
-            ]
-        )
-        for key, val in results.iteritems():
+        if recordType is None:
+            recordTypes = self._toODRecordTypes.values()
+        else:
+            recordTypes = (self._toODRecordTypes[recordType],)
+
+        for recordType in recordTypes:
+
             try:
-                calendarUserAddresses = set()
-                enabledForCalendaring = False
-                if val.has_key(dsattributes.kDSNAttrEMailAddress):
-                    enabledForCalendaring = True
-                    calendarUserAddresses.add(val[dsattributes.kDSNAttrEMailAddress])
-                rec = OpenDirectoryRecord(
-                    service = self,
-                    recordType = DirectoryService.recordType_users,
-                    guid = val[dsattributes.kDS1AttrGeneratedUID],
-                    nodeName = val[dsattributes.kDSNAttrMetaNodeLocation],
-                    shortName = key,
-                    fullName = val[dsattributes.kDS1AttrDistinguishedName],
-                    firstName = val[dsattributes.kDS1AttrFirstName],
-                    lastName = val[dsattributes.kDS1AttrLastName],
-                    emailAddress = val.get(dsattributes.kDSNAttrEMailAddress, ""),
-                    calendarUserAddresses = calendarUserAddresses,
-                    autoSchedule = False,
-                    enabledForCalendaring = enabledForCalendaring,
-                    memberGUIDs = (),
-                    proxyGUIDs = (),
-                    readOnlyProxyGUIDs = (),
+                self.log_info("Calling OD: %s %s %s" % (recordType, operand,
+                    fields))
+                results = opendirectory.queryRecordsWithAttributes(
+                    self.directory,
+                    dsquery.expression(operand, expressions).generate(),
+                    caseInsensitive,
+                    recordType,
+                    [
+                        dsattributes.kDS1AttrGeneratedUID,
+                        dsattributes.kDS1AttrFirstName,
+                        dsattributes.kDS1AttrLastName,
+                        dsattributes.kDSNAttrEMailAddress,
+                        dsattributes.kDS1AttrDistinguishedName,
+                        dsattributes.kDSNAttrMetaNodeLocation,
+                    ]
                 )
-                yield rec
+                self.log_info("Got back %d records from OD" % (len(results),))
+                for key, val in results.iteritems():
+                    self.log_info("OD result: %s %s" % (key, val))
+                    try:
+                        calendarUserAddresses = set()
+                        enabledForCalendaring = False
+                        if val.has_key(dsattributes.kDSNAttrEMailAddress):
+                            enabledForCalendaring = True
+                            calendarUserAddresses.add(val[dsattributes.kDSNAttrEMailAddress])
+                        rec = OpenDirectoryRecord(
+                            service = self,
+                            recordType = self._fromODRecordTypes[recordType],
+                            guid = val[dsattributes.kDS1AttrGeneratedUID],
+                            nodeName = val[dsattributes.kDSNAttrMetaNodeLocation],
+                            shortName = key,
+                            fullName = val.get(dsattributes.kDS1AttrDistinguishedName, ""),
+                            firstName = val.get(dsattributes.kDS1AttrFirstName, ""),
+                            lastName = val.get(dsattributes.kDS1AttrLastName, ""),
+                            emailAddress = val.get(dsattributes.kDSNAttrEMailAddress, ""),
+                            calendarUserAddresses = calendarUserAddresses,
+                            autoSchedule = False,
+                            enabledForCalendaring = enabledForCalendaring,
+                            memberGUIDs = (),
+                            proxyGUIDs = (),
+                            readOnlyProxyGUIDs = (),
+                        )
+                        yield rec
+                    except Exception, e:
+                        self.log_error("Failed to convert OD result into record: %s %s" % (val, e))
+                        raise
+
             except Exception, e:
-                print e
-                import pdb; pdb.set_trace()
+                self.log_error("OD search failed: %s" % (e,))
+                raise
 
-
     def reloadCache(self, recordType, shortName=None, guid=None):
         if shortName:
             self.log_info("Faulting record %s into %s record cache" % (shortName, recordType))
@@ -532,7 +561,7 @@
             self.log_info("Reloading %s record cache" % (recordType,))
 
         results = self._queryDirectory(recordType, shortName=shortName, guid=guid)
-        
+
         if shortName is None and guid is None:
             records = {}
             guids   = {}

Modified: CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/directory.py	2008-09-17 17:37:45 UTC (rev 3009)
+++ CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/directory.py	2008-09-17 21:18:56 UTC (rev 3010)
@@ -139,10 +139,20 @@
                 yield record
 
     def recordsMatchingFields(self, fields, caseInsensitive=True, operand="or",
-        recordType=recordType_users):
+        recordType=None):
         # Default, bruteforce method; override with one optimized for each
         # service
 
+        if recordType is None:
+            recordTypes = (
+                DirectoryService.recordType_users,
+                DirectoryService.recordType_groups,
+                DirectoryService.recordType_locations,
+                DirectoryService.recordType_resources,
+            )
+        else:
+            recordTypes = (recordType,)
+
         def fieldMatches(fieldValue, value):
             if caseInsensitive:
                 return fieldValue.lower().startswith(value.lower())
@@ -174,9 +184,10 @@
                 return False
 
         try:
-            for record in self.listRecords(recordType):
-                if recordMatches(record):
-                    yield record
+            for recordType in recordTypes:
+                for record in self.listRecords(recordType):
+                    if recordMatches(record):
+                        yield record
         except UnknownRecordTypeError:
             # Skip this service since it doesn't understand this record type
             pass

Modified: CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/principal.py	2008-09-17 17:37:45 UTC (rev 3009)
+++ CalendarServer/branches/users/sagen/principal-property-search-2995/twistedcaldav/directory/principal.py	2008-09-17 21:18:56 UTC (rev 3010)
@@ -125,6 +125,22 @@
     def principalForCalendarUserAddress(self, address):
         raise NotImplementedError("Subclass must implement principalForCalendarUserAddress()")
 
+    ##
+    # DAV-property-to-record-field mapping
+    ##
+
+    _cs_ns = "http://calendarserver.org/ns/"
+    _fieldMap = {
+        "<{DAV:}%s>" % ("displayname",) : "fullName",
+        "<{%s}%s>" % (_cs_ns, "first-name") : "firstName",
+        "<{%s}%s>" % (_cs_ns, "last-name") : "lastName",
+        "<{%s}%s>" % (_cs_ns, "email-address") : "emailAddress",
+    }
+
+    def propertyToField(self, property):
+        return self._fieldMap.get(repr(property), None)
+
+
 class DirectoryPrincipalProvisioningResource (DirectoryProvisioningResource):
     """
     Collection resource which provisions directory principals as its children.
@@ -237,6 +253,7 @@
     def principalCollections(self):
         return (self,)
 
+
 class DirectoryPrincipalTypeProvisioningResource (DirectoryProvisioningResource):
     """
     Collection resource which provisions directory principals of a
@@ -290,21 +307,7 @@
     def principalCollections(self):
         return self.parent.principalCollections()
 
-    ##
-    # DAV-property-to-record-field mapping
-    ##
 
-    _cs_ns = "http://calendarserver.org/ns/"
-    _fieldMap = {
-        "<{%s}%s>" % (_cs_ns, "first-name") : "firstName",
-        "<{%s}%s>" % (_cs_ns, "last-name") : "lastName",
-        "<{%s}%s>" % (_cs_ns, "email-address") : "emailAddress",
-    }
-
-    def propertyToField(self, property):
-        return self._fieldMap.get(repr(property), None)
-
-
 class DirectoryPrincipalUIDProvisioningResource (DirectoryProvisioningResource):
     """
     Collection resource which provisions directory principals indexed
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080917/3c42bce3/attachment-0001.html 


More information about the calendarserver-changes mailing list