[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