[CalendarServer-changes] [2190] CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav /directory

source_changes at macosforge.org source_changes at macosforge.org
Tue Mar 4 14:42:35 PST 2008


Revision: 2190
          http://trac.macosforge.org/projects/calendarserver/changeset/2190
Author:   wsanchez at apple.com
Date:     2008-03-04 14:42:34 -0800 (Tue, 04 Mar 2008)

Log Message:
-----------
Pull up support for non-calendaring principals.

Modified Paths:
--------------
    CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/test/test_opendirectoryrecords.py

Modified: CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/appleopendirectory.py	2008-03-04 22:22:01 UTC (rev 2189)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/appleopendirectory.py	2008-03-04 22:42:34 UTC (rev 2190)
@@ -12,8 +12,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# DRI: Wilfredo Sanchez, wsanchez at apple.com
 ##
 
 """
@@ -148,7 +146,8 @@
             for GUID in self._expandGroupMembership(
                 group.get(dsattributes.kDSNAttrGroupMembers, []),
                 group.get(dsattributes.kDSNAttrNestedGroups, []),
-                processedGUIDs):
+                processedGUIDs
+            ):
                 yield GUID
 
     def __cmp__(self, other):
@@ -186,13 +185,13 @@
             dsattributes.kDS1AttrGeneratedUID,
             dsattributes.kDSNAttrRecordName,
             dsattributes.kDSNAttrMetaNodeLocation,
-            'dsAttrTypeNative:apple-serviceinfo',
+            "dsAttrTypeNative:apple-serviceinfo",
         ]
 
         records = opendirectory.queryRecordsWithAttributes_list(
             self.directory,
             dsquery.match(
-                'dsAttrTypeNative:apple-serviceinfo',
+                "dsAttrTypeNative:apple-serviceinfo",
                 vhostname,
                 dsattributes.eDSContains,
             ).generate(),
@@ -241,7 +240,7 @@
         recordlocation = "%s/Computers/%s" % (record[dsattributes.kDSNAttrMetaNodeLocation], recordname)
 
         # First check for apple-serviceinfo attribute
-        plist = record.get('dsAttrTypeNative:apple-serviceinfo', None)
+        plist = record.get("dsAttrTypeNative:apple-serviceinfo", None)
         if not plist:
             return False
 
@@ -456,18 +455,47 @@
             enabledForCalendaring = True
 
             if self.requireComputerRecord:
-                if not value.get(dsattributes.kDSNAttrServicesLocator):
-                    if recordType == DirectoryService.recordType_groups:
+                servicesLocators = value.get(dsattributes.kDSNAttrServicesLocator)
+
+                def allowForACLs():
+                    return recordType in (
+                        DirectoryService.recordType_users,
+                        DirectoryService.recordType_groups,
+                    )
+
+                def disableForCalendaring():
+                    logging.debug(
+                        "Record (%s) %s is not enabled for calendaring but may be used in ACLs"
+                        % (recordType, recordShortName), system="OpenDirectoryService"
+                    )
+
+                def invalidRecord():
+                    logging.err(
+                        "Directory (incorrectly) returned a record with no applicable "
+                        "ServicesLocator attribute: (%s) %s"
+                        % (recordType, recordShortName), system="OpenDirectoryService"
+                    )
+
+                if servicesLocators:
+                    if type(servicesLocators) is str:
+                        servicesLocators = (servicesLocators,)
+
+                    for locator in servicesLocators:
+                        if locator in self.servicetags:
+                            break
+                    else:
+                        if allowForACLs():
+                            disableForCalendaring()
+                            enabledForCalendaring = False
+                        else:
+                            invalidRecord()
+                            continue
+                else:
+                    if allowForACLs():
+                        disableForCalendaring()
                         enabledForCalendaring = False
-                        logging.debug(
-                            "Group %s is not enabled for calendaring but may be used in ACLs"
-                            % (recordShortName,), system="OpenDirectoryService"
-                        )
                     else:
-                        logging.err(
-                            "Directory (incorrectly) returned a record with no ServicesLocator attribute: %s"
-                            % (recordShortName,), system="OpenDirectoryService"
-                        )
+                        invalidRecord()
                         continue
 
             # Now get useful record info.
@@ -486,7 +514,7 @@
             else:
                 calendarUserAddresses = ()
 
-            # Special case for groups.
+            # Special case for groups, which have members.
             if recordType == DirectoryService.recordType_groups:
                 memberGUIDs = value.get(dsattributes.kDSNAttrGroupMembers)
                 if memberGUIDs is None:
@@ -525,9 +553,6 @@
                 proxyGUIDs            = proxyGUIDs,
             )
 
-            del recordShortName
-            del recordGUID
-
             def disableRecord(record):
                 logging.warn("Record disabled due to conflict: %s" % (record,), system="OpenDirectoryService")
 
@@ -653,10 +678,13 @@
                     query = dsquery.expression(dsquery.expression.OR, guidQueries)
 
             #
-            # For groups, we'll load all entries, even if they don't
-            # have a services locator for this server.
+            # For users and groups, we'll load all entries, even if
+            # they don't have a services locator for this server.
             #
-            elif recordType != DirectoryService.recordType_groups:
+            elif (
+                recordType != DirectoryService.recordType_users and
+                recordType != DirectoryService.recordType_groups
+            ):
                 tag_queries = []
 
                 for tag in self.servicetags:
@@ -807,31 +835,34 @@
             except opendirectory.ODError, e:
                 logging.err("Open Directory (node=%s) error while performing basic authentication for user %s: %s"
                             % (self.service.realmName, self.shortName, e), system="OpenDirectoryService")
-                return False
+
+            return False
+
         elif isinstance(credentials, DigestedCredentials):
+            #
+            # We need a special format for the "challenge" and "response" strings passed into open directory, as it is
+            # picky about exactly what it receives.
+            #
             try:
-                # We need a special format for the "challenge" and "response" strings passed into open directory, as it is
-                # picky about exactly what it receives.
-                
-                try:
-                    challenge = 'Digest realm="%(realm)s", nonce="%(nonce)s", algorithm=%(algorithm)s' % credentials.fields
-                    response = (
-                        'Digest username="%(username)s", '
-                        'realm="%(realm)s", '
-                        'nonce="%(nonce)s", '
-                        'uri="%(uri)s", '
-                        'response="%(response)s",'
-                        'algorithm=%(algorithm)s'
-                    ) % credentials.fields
-                except KeyError, e:
-                    logging.err(
-                        "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),
-                        system="OpenDirectoryService"
-                    )
-                    return False
+                challenge = 'Digest realm="%(realm)s", nonce="%(nonce)s", algorithm=%(algorithm)s' % credentials.fields
+                response = (
+                    'Digest username="%(username)s", '
+                    'realm="%(realm)s", '
+                    'nonce="%(nonce)s", '
+                    'uri="%(uri)s", '
+                    'response="%(response)s",'
+                    'algorithm=%(algorithm)s'
+                ) % credentials.fields
+            except KeyError, e:
+                logging.err(
+                    "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),
+                    system="OpenDirectoryService"
+                )
+                return False
 
+            try:
                 if self.digestcache[credentials.fields["uri"]] == response:
                     return True
             except (AttributeError, KeyError):
@@ -861,6 +892,8 @@
                 )
                 return False
 
+            return False
+
         return super(OpenDirectoryRecord, self).verifyCredentials(credentials)
 
 class OpenDirectoryInitError(DirectoryError):

Modified: CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/test/test_opendirectoryrecords.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/test/test_opendirectoryrecords.py	2008-03-04 22:22:01 UTC (rev 2189)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/test/test_opendirectoryrecords.py	2008-03-04 22:42:34 UTC (rev 2190)
@@ -12,8 +12,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# DRI: Wilfredo Sanchez, wsanchez at apple.com
 ##
 
 import twisted.trial.unittest
@@ -48,6 +46,7 @@
         def setUp(self):
             super(ReloadCache, self).setUp()
             self._service = OpenDirectoryService(node="/Search", dosetup=False)
+            self._service.servicetags.add("FE588D50-0514-4DF9-BCB5-8ECA5F3DA274:030572AE-ABEC-4E0F-83C9-FCA304769E5F:calendar")
             
         def tearDown(self):
             for call in self._service._delayedCalls:
@@ -63,6 +62,17 @@
             self.assertTrue(len(missing) == 0, msg="Directory records not found: %s" % (missing,))
             self.assertTrue(len(extras) == 0, msg="Directory records not expected: %s" % (extras,))
                 
+        def _verifyRecordsCheckEnabled(self, recordType, expected, enabled):
+            expected = set(expected)
+            found = set([item for item in self._service._records[recordType]["records"].iterkeys()
+                         if self._service._records[recordType]["records"][item].enabledForCalendaring == enabled])
+            
+            missing = expected.difference(found)
+            extras = found.difference(expected)
+
+            self.assertTrue(len(missing) == 0, msg="Directory records not found: %s" % (missing,))
+            self.assertTrue(len(extras) == 0, msg="Directory records not expected: %s" % (extras,))
+                
         def _verifyDisabledRecords(self, recordType, expectedNames, expectedGUIDs):
             def check(disabledType, expected):
                 expected = set(expected)
@@ -114,6 +124,51 @@
             self._verifyRecords(DirectoryService.recordType_locations, ("location01", "location02"))
             self._verifyDisabledRecords(DirectoryService.recordType_locations, (), ())
 
+        def test_normal_disabledusers(self):
+            self._service.fakerecords = {
+                DirectoryService.recordType_users: [
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02"),
+                    fakeODRecord("User 03", addLocator=False),
+                    fakeODRecord("User 04", addLocator=False),
+                ],
+                DirectoryService.recordType_groups: [
+                    fakeODRecord("Group 01"),
+                    fakeODRecord("Group 02"),
+                    fakeODRecord("Group 03", addLocator=False),
+                    fakeODRecord("Group 04", addLocator=False),
+                ],
+                DirectoryService.recordType_resources: [
+                    fakeODRecord("Resource 01"),
+                    fakeODRecord("Resource 02"),
+                    fakeODRecord("Resource 03", addLocator=False),
+                    fakeODRecord("Resource 04", addLocator=False),
+                ],
+                DirectoryService.recordType_locations: [
+                    fakeODRecord("Location 01"),
+                    fakeODRecord("Location 02"),
+                    fakeODRecord("Location 03", addLocator=False),
+                    fakeODRecord("Location 04", addLocator=False),
+                ],
+            }
+
+            self._service.reloadCache(DirectoryService.recordType_users)
+            self._service.reloadCache(DirectoryService.recordType_groups)
+            self._service.reloadCache(DirectoryService.recordType_resources)
+            self._service.reloadCache(DirectoryService.recordType_locations)
+
+            self._verifyRecordsCheckEnabled(DirectoryService.recordType_users, ("user01", "user02"), True)
+            self._verifyRecordsCheckEnabled(DirectoryService.recordType_users, ("user03", "user04"), False)
+
+            self._verifyRecordsCheckEnabled(DirectoryService.recordType_groups, ("group01", "group02"), True)
+            self._verifyRecordsCheckEnabled(DirectoryService.recordType_groups, ("group03", "group04"), False)
+
+            self._verifyRecordsCheckEnabled(DirectoryService.recordType_resources, ("resource01", "resource02"), True)
+            self._verifyRecordsCheckEnabled(DirectoryService.recordType_resources, (), False)
+
+            self._verifyRecordsCheckEnabled(DirectoryService.recordType_locations, ("location01", "location02"), True)
+            self._verifyRecordsCheckEnabled(DirectoryService.recordType_locations, (), False)
+
         def test_normalCacheMiss(self):
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
@@ -245,7 +300,7 @@
                 ("EDB9EE55-31F2-4EA9-B5FB-D8AE2A8BA35E", "62368DDF-0C62-4C97-9A58-DE9FD46131A0", "D10F3EE0-5014-41D3-8488-3819D3EF3B2A"),
             )
 
-def fakeODRecord(fullName, shortName=None, guid=None, email=None):
+def fakeODRecord(fullName, shortName=None, guid=None, email=None, addLocator=True):
     if shortName is None:
         shortName = shortNameForFullName(fullName)
 
@@ -257,16 +312,18 @@
     if email is None:
         email = "%s at example.com" % (shortName,)
 
-    return [
-        shortName, {
-            dsattributes.kDS1AttrDistinguishedName: fullName,
-            dsattributes.kDS1AttrGeneratedUID: guid,
-            dsattributes.kDSNAttrEMailAddress: email,
-            dsattributes.kDSNAttrServicesLocator: "FE588D50-0514-4DF9-BCB5-8ECA5F3DA274:030572AE-ABEC-4E0F-83C9-FCA304769E5F:calendar",
-            dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-        }
-    ]
+    attrs = {
+        dsattributes.kDS1AttrDistinguishedName: fullName,
+        dsattributes.kDS1AttrGeneratedUID: guid,
+        dsattributes.kDSNAttrEMailAddress: email,
+        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
+    }
 
+    if addLocator:
+        attrs[dsattributes.kDSNAttrServicesLocator] = "FE588D50-0514-4DF9-BCB5-8ECA5F3DA274:030572AE-ABEC-4E0F-83C9-FCA304769E5F:calendar"
+
+    return [ shortName, attrs ]
+
 def shortNameForFullName(fullName):
     return fullName.lower().replace(" ", "")
 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080304/0a3e4f3a/attachment-0001.html 


More information about the calendarserver-changes mailing list