[CalendarServer-changes] [2209] CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Thu Mar 6 12:34:13 PST 2008


Revision: 2209
          http://trac.macosforge.org/projects/calendarserver/changeset/2209
Author:   wsanchez at apple.com
Date:     2008-03-06 12:34:12 -0800 (Thu, 06 Mar 2008)

Log Message:
-----------
Store calendar data by GUID

Modified Paths:
--------------
    CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/directory/calendar.py
    CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/extensions.py
    CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/schedule.py
    CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/static.py

Modified: CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/directory/calendar.py	2008-03-06 20:33:27 UTC (rev 2208)
+++ CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/directory/calendar.py	2008-03-06 20:34:12 UTC (rev 2209)
@@ -19,8 +19,10 @@
 """
 
 __all__ = [
+    "uidsResourceName",
     "DirectoryCalendarHomeProvisioningResource",
     "DirectoryCalendarHomeTypeProvisioningResource",
+    "DirectoryCalendarHomeUIDProvisioningResource",
     "DirectoryCalendarHomeResource",
 ]
 
@@ -39,6 +41,9 @@
 from twistedcaldav.directory.idirectory import IDirectoryService
 from twistedcaldav.directory.resource import AutoProvisioningResourceMixIn
 
+# Use __underbars__ convention to avoid conflicts with directory resource types.
+uidsResourceName = "__uids__"
+
 class DirectoryCalendarHomeProvisioningResource (AutoProvisioningResourceMixIn, ReadOnlyResourceMixIn, DAVResource):
     """
     Resource which provisions calendar home collections as needed.    
@@ -59,10 +64,17 @@
         # FIXME: Smells like a hack
         directory.calendarHomesCollection = self
 
+        #
         # Create children
+        #
+        def provisionChild(name):
+            self.putChild(name, self.provisionChild(name))
+
         for recordType in self.directory.recordTypes():
-            self.putChild(recordType, self.provisionChild(recordType))
+            provisionChild(recordType)
 
+        provisionChild(uidsResourceName)
+
     def provisionChild(self, recordType):
         raise NotImplementedError("Subclass must implement provisionChild()")
 
@@ -86,11 +98,11 @@
         return self.directory.principalCollection.principalForRecord(record)
 
     def homeForDirectoryRecord(self, record):
-        typeResource = self.getChild(record.recordType)
-        if typeResource is None:
+        uidResource = self.getChild(uidsResourceName)
+        if uidResource is None:
             return None
         else:
-            return typeResource.getChild(record.shortName)
+            return uidResource.getChild(record.guid)
 
     ##
     # DAV
@@ -113,8 +125,7 @@
     """
     def __init__(self, parent, recordType):
         """
-        @param path: the path to the file which will back the resource.
-        @param directory: an L{IDirectoryService} to provision calendars from.
+        @param parent: the parent of this resource
         @param recordType: the directory record type to provision.
         """
         assert parent is not None
@@ -131,7 +142,6 @@
 
     def getChild(self, name, record=None):
         self.provision()
-
         if name == "":
             return self
 
@@ -139,11 +149,8 @@
             record = self.directory.recordWithShortName(self.recordType, name)
             if record is None:
                 return None
-        else:
-            assert name is None
-            name = record.shortName
 
-        return self.provisionChild(name)
+        return self._parent.homeForDirectoryRecord(record)
 
     def listChildren(self):
         return (
@@ -173,6 +180,61 @@
         return self._parent.principalForRecord(record)
 
 
+class DirectoryCalendarHomeUIDProvisioningResource (AutoProvisioningResourceMixIn, ReadOnlyResourceMixIn, DAVResource):
+    def __init__(self, parent):
+        """
+        @param parent: the parent of this resource
+        """
+        assert parent is not None
+
+        DAVResource.__init__(self)
+
+        self.directory = parent.directory
+        self.parent = parent
+
+    def url(self):
+        return joinURL(self.parent.url(), uidsResourceName)
+
+    def getChild(self, name, record=None):
+        self.provision()
+        if name == "":
+            return self
+
+        if record is None:
+            record = self.directory.recordWithGUID(name)
+            if record is None:
+                return None
+
+        return self.provisionChild(name)
+
+    def listChildren(self):
+        return (
+            record.guid
+            for record in self.directory.listRecords(self.recordType)
+            if record.enabledForCalendaring
+        )
+
+    ##
+    # DAV
+    ##
+    
+    def isCollection(self):
+        return True
+
+    ##
+    # ACL
+    ##
+
+    def defaultAccessControlList(self):
+        return readOnlyACL
+
+    def principalCollections(self):
+        return self.parent.principalCollections()
+
+    def principalForRecord(self, record):
+        return self.parent.principalForRecord(record)
+
+
 class DirectoryCalendarHomeResource (AutoProvisioningResourceMixIn, CalDAVResource):
     """
     Calendar home collection resource.
@@ -187,7 +249,7 @@
         CalDAVResource.__init__(self)
 
         self.record = record
-        self._parent = parent
+        self.parent = parent
 
         # Cache children which must be of a specific type
         childlist = (
@@ -243,7 +305,13 @@
         raise NotImplementedError("Subclass must implement provisionChild()")
 
     def url(self):
-        return joinURL(self._parent.url(), self.record.shortName)
+        return joinURL(self.parent.url(), self.record.guid)
+        ##
+        ## While the underlying primary location is GUID-based, we want
+        ## the canonical user-facing location to be recordType &
+        ## shortName-based, because that's friendlier.
+        ##
+        #return joinURL(self.parent.parent.getChild(self.record.recordType).url(), self.record.shortName)
 
     ##
     # DAV
@@ -260,8 +328,6 @@
         return succeed(davxml.HRef(self.principalForRecord().principalURL()))
 
     def defaultAccessControlList(self):
-        # FIXME: directory.principalCollection smells like a hack
-        # See DirectoryPrincipalProvisioningResource.__init__()
         myPrincipal = self.principalForRecord()
 
         aces = (
@@ -306,10 +372,10 @@
         return davxml.ACL(*aces)
 
     def principalCollections(self):
-        return self._parent.principalCollections()
+        return self.parent.principalCollections()
 
     def principalForRecord(self):
-        return self._parent.principalForRecord(self.record)
+        return self.parent.principalForRecord(self.record)
 
     ##
     # Quota

Modified: CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/directory/principal.py	2008-03-06 20:33:27 UTC (rev 2208)
+++ CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/directory/principal.py	2008-03-06 20:34:12 UTC (rev 2209)
@@ -19,8 +19,10 @@
 """
 
 __all__ = [
+    "DirectoryProvisioningResource",
     "DirectoryPrincipalProvisioningResource",
     "DirectoryPrincipalTypeProvisioningResource",
+    "DirectoryPrincipalUIDProvisioningResource",
     "DirectoryPrincipalResource",
     "DirectoryCalendarPrincipalResource",
 ]
@@ -58,11 +60,7 @@
     def defaultAccessControlList(self):
         return authReadACL
 
-    def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
-        # Permissions here are fixed, and are not subject to inherritance rules, etc.
-        return succeed(self.defaultAccessControlList())
-
-class DirectoryProvisioningResource(
+class DirectoryProvisioningResource (
     AutoProvisioningFileMixIn,
     PermissionsMixIn,
     CalendarPrincipalCollectionResource,
@@ -184,6 +182,8 @@
         if record is not None:
             return self.principalForRecord(record)
 
+        log.err("No principal for calendar user address: %r" % (address,))
+
         return None
 
     ##

Modified: CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/extensions.py	2008-03-06 20:33:27 UTC (rev 2208)
+++ CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/extensions.py	2008-03-06 20:34:12 UTC (rev 2209)
@@ -620,6 +620,10 @@
     def writeProperty(self, property, request):
         raise HTTPError(self.readOnlyResponse)
 
+    def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
+        # Permissions here are fixed, and are not subject to inherritance rules, etc.
+        return succeed(self.defaultAccessControlList())
+
 class XMLResponse (Response):
     """
     XML L{Response} object.

Modified: CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/schedule.py
===================================================================
--- CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/schedule.py	2008-03-06 20:33:27 UTC (rev 2208)
+++ CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/schedule.py	2008-03-06 20:34:12 UTC (rev 2209)
@@ -35,7 +35,6 @@
 from twisted.web2.dav.util import joinURL
 
 from twistedcaldav import caldavxml
-from twistedcaldav import customxml
 from twistedcaldav import itip
 from twistedcaldav import logging
 from twistedcaldav.resource import CalDAVResource
@@ -355,7 +354,7 @@
             # Map recipient to their inbox
             inbox = None
             if principal is None:
-                logging.err("No principal for calendar user address: %s" % (recipient,), system="CalDAV Outbox POST")
+                logging.err("No schedulable principal for calendar user address: %r" % (recipient,), system="CalDAV Outbox POST")
             else:
                 inboxURL = principal.scheduleInboxURL()
                 if inboxURL:

Modified: CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/static.py
===================================================================
--- CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/static.py	2008-03-06 20:33:27 UTC (rev 2208)
+++ CalendarServer/branches/users/wsanchez/guid-calendars/twistedcaldav/static.py	2008-03-06 20:34:12 UTC (rev 2209)
@@ -22,7 +22,9 @@
     "CalDAVFile",
     "AutoProvisioningFileMixIn",
     "CalendarHomeProvisioningFile",
+    "CalendarHomeUIDProvisioningFile",
     "CalendarHomeFile",
+    "ScheduleFile",
     "ScheduleInboxFile",
     "ScheduleOutboxFile",
     "DropBoxHomeFile",
@@ -62,8 +64,10 @@
 from twistedcaldav.resource import CalDAVResource, isCalendarCollectionResource, isPseudoCalendarCollectionResource
 from twistedcaldav.schedule import ScheduleInboxResource, ScheduleOutboxResource
 from twistedcaldav.dropbox import DropBoxHomeResource, DropBoxCollectionResource, DropBoxChildResource
+from twistedcaldav.directory.calendar import uidsResourceName
 from twistedcaldav.directory.calendar import DirectoryCalendarHomeProvisioningResource
 from twistedcaldav.directory.calendar import DirectoryCalendarHomeTypeProvisioningResource
+from twistedcaldav.directory.calendar import DirectoryCalendarHomeUIDProvisioningResource
 from twistedcaldav.directory.calendar import DirectoryCalendarHomeResource
 from twistedcaldav.directory.resource import AutoProvisioningResourceMixIn
 
@@ -439,43 +443,68 @@
         DirectoryCalendarHomeProvisioningResource.__init__(self, directory, url)
 
     def provisionChild(self, name):
+        if name == uidsResourceName:
+            return CalendarHomeUIDProvisioningFile(self.fp.child(name).path, self)
+
         return CalendarHomeTypeProvisioningFile(self.fp.child(name).path, self, name)
 
     def createSimilarFile(self, path):
         raise HTTPError(responsecode.NOT_FOUND)
 
 class CalendarHomeTypeProvisioningFile (AutoProvisioningFileMixIn, DirectoryCalendarHomeTypeProvisioningResource, DAVFile):
-    """
-    Resource which provisions calendar home collections of a specific
-    record type as needed.
-    """
     def __init__(self, path, parent, recordType):
         """
         @param path: the path to the file which will back the resource.
-        @param directory: an L{IDirectoryService} to provision calendars from.
+        @param parent: the parent of this resource
         @param recordType: the directory record type to provision.
         """
         DAVFile.__init__(self, path)
         DirectoryCalendarHomeTypeProvisioningResource.__init__(self, parent, recordType)
 
+class CalendarHomeUIDProvisioningFile (AutoProvisioningFileMixIn, DirectoryCalendarHomeUIDProvisioningResource, DAVFile):
+    def __init__(self, path, parent):
+        """
+        @param path: the path to the file which will back the resource.
+        """
+        DAVFile.__init__(self, path)
+        DirectoryCalendarHomeUIDProvisioningResource.__init__(self, parent)
+
     def provisionChild(self, name):
-        record = self.directory.recordWithShortName(self.recordType, name)
+        record = self.directory.recordWithGUID(name)
 
         if record is None:
-            log.msg("No directory record %r of type %r" % (name, self.recordType))
+            log.msg("No directory record with GUID %r" % (name,))
             return None
 
         if not record.enabledForCalendaring:
-            log.msg("Directory record %r of type %r is not enabled for calendaring" % (name, self.recordType))
+            log.msg("Directory record %r is not enabled for calendaring" % (record,))
             return None
 
-        child = CalendarHomeFile(self.fp.child(name).path, self, record)
+        childPath = self.fp.child(name)
+        child = CalendarHomeFile(childPath.path, self, record)
         if not child.exists():
-            # NOTE: provisionDefaultCalendars() returns a deferred, which we are ignoring.
-            # The result being that the default calendars will be present at some point
-            # in the future, not necessarily right now, and we don't have a way to wait
-            # on that to finish.
-            child.provisionDefaultCalendars()
+            #
+            # Find out if the child exists at the old (pre-1.2)
+            # location (ie. in the types hierarchy instead of the GUID
+            # hierarchy).
+            #
+            oldPath = self.parent.getChild(record.recordType).fp.child(record.shortName)
+            if oldPath.exists():
+                log.msg("Moving calendar home from old location %r to new location %r." % (oldPath, childPath))
+                try:
+                    oldPath.moveTo(childPath)
+                except (OSError, IOError), e:
+                    log.err("Error moving calendar home %r: %s" % (oldPath, e))
+                    raise HTTPError(StatusResponse(
+                        responsecode.INTERNAL_SERVER_ERROR,
+                        "Unable to move calendar home."
+                    ))
+            else:
+                # NOTE: provisionDefaultCalendars() returns a deferred, which we are ignoring.
+                # The result being that the default calendars will be present at some point
+                # in the future, not necessarily right now, and we don't have a way to wait
+                # on that to finish.
+                child.provisionDefaultCalendars()
         return child
 
     def createSimilarFile(self, path):
@@ -674,7 +703,7 @@
     http_MKCOL =               NotificationsCollectionResource.http_MKCOL
     http_MKCALENDAR =          NotificationsCollectionResource.http_MKCALENDAR
 
-class NotificationFile(NotificationResource, DAVFile):
+class NotificationFile (NotificationResource, DAVFile):
     def __init__(self, path, parent):
         super(NotificationFile, self).__init__(path, principalCollections=parent.principalCollections())
 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080306/3caaee81/attachment-0001.html 


More information about the calendarserver-changes mailing list