[CalendarServer-changes] [2221] CalendarServer/branches/release/CalendarServer-1.2-dev
source_changes at macosforge.org
source_changes at macosforge.org
Mon Mar 10 14:04:46 PDT 2008
Revision: 2221
http://trac.macosforge.org/projects/calendarserver/changeset/2221
Author: wsanchez at apple.com
Date: 2008-03-10 14:04:44 -0700 (Mon, 10 Mar 2008)
Log Message:
-----------
Pull up r2220: Store calendar data by GUID.
This fixes part of #111.
Modified Paths:
--------------
CalendarServer/branches/release/CalendarServer-1.2-dev/testcaldav
CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/calendar.py
CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/principal.py
CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/test/test_guidchange.py
CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/schedule.py
CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/static.py
CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/test/data/makelargecalendars.py
CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/test/test_config.py
Modified: CalendarServer/branches/release/CalendarServer-1.2-dev/testcaldav
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/testcaldav 2008-03-10 20:57:53 UTC (rev 2220)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/testcaldav 2008-03-10 21:04:44 UTC (rev 2221)
@@ -71,8 +71,8 @@
svn checkout http://svn.macosforge.org/repository/calendarserver/CalDAVTester/trunk "${cdt}"
fi;
-if [ ! -e "${documentroot}/calendars/users/user01" ]; then
- curl "http://localhost:8008/calendars/users/user01/";
+if [ ! -e "${documentroot}/calendars/__uids__/user01" ]; then
+ curl "http://localhost:8008/calendars/__uids__/user01/";
fi;
python twistedcaldav/test/data/makelargecalendars.py -n 1 -d "${documentroot}";
Modified: CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/calendar.py 2008-03-10 20:57:53 UTC (rev 2220)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/calendar.py 2008-03-10 21:04:44 UTC (rev 2221)
@@ -21,8 +21,10 @@
"""
__all__ = [
+ "uidsResourceName",
"DirectoryCalendarHomeProvisioningResource",
"DirectoryCalendarHomeTypeProvisioningResource",
+ "DirectoryCalendarHomeUIDProvisioningResource",
"DirectoryCalendarHomeResource",
]
@@ -42,6 +44,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.
@@ -62,10 +67,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()")
@@ -89,11 +101,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
@@ -116,8 +128,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
@@ -134,7 +145,6 @@
def getChild(self, name, record=None):
self.provision()
-
if name == "":
return self
@@ -142,11 +152,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 (
@@ -176,6 +183,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.
@@ -190,7 +252,7 @@
CalDAVResource.__init__(self)
self.record = record
- self._parent = parent
+ self.parent = parent
# Cache children which must be of a specific type
childlist = (
@@ -246,7 +308,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
@@ -263,8 +331,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 = (
@@ -309,10 +375,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/release/CalendarServer-1.2-dev/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/principal.py 2008-03-10 20:57:53 UTC (rev 2220)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/principal.py 2008-03-10 21:04:44 UTC (rev 2221)
@@ -21,8 +21,10 @@
"""
__all__ = [
+ "DirectoryProvisioningResource",
"DirectoryPrincipalProvisioningResource",
"DirectoryPrincipalTypeProvisioningResource",
+ "DirectoryPrincipalUIDProvisioningResource",
"DirectoryPrincipalResource",
"DirectoryCalendarPrincipalResource",
]
@@ -64,7 +66,7 @@
# Permissions here are fixed, and are not subject to inherritance rules, etc.
return succeed(self.defaultAccessControlList())
-class DirectoryProvisioningResource(
+class DirectoryProvisioningResource (
AutoProvisioningFileMixIn,
PermissionsMixIn,
CalendarPrincipalCollectionResource,
@@ -186,6 +188,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/release/CalendarServer-1.2-dev/twistedcaldav/directory/test/test_guidchange.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/test/test_guidchange.py 2008-03-10 20:57:53 UTC (rev 2220)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/directory/test/test_guidchange.py 2008-03-10 21:04:44 UTC (rev 2221)
@@ -47,7 +47,7 @@
self.directoryService = XMLDirectoryService(self.xmlfile)
# Set up a principals hierarchy for each service we're testing with
- name = 'principals'
+ name = "principals"
url = "/" + name + "/"
path = os.path.join(self.docroot, url[1:])
@@ -57,7 +57,7 @@
provisioningResource = DirectoryPrincipalProvisioningResource(path, url, self.directoryService)
- self.site.resource.putChild('principals', provisioningResource)
+ self.site.resource.putChild("principals", provisioningResource)
self.setupCalendars()
@@ -65,25 +65,29 @@
def setupCalendars(self):
calendarCollection = CalendarHomeProvisioningFile(
- os.path.join(self.docroot, 'calendars'),
+ os.path.join(self.docroot, "calendars"),
self.directoryService,
- '/calendars/'
+ "/calendars/"
)
- self.site.resource.putChild('calendars', calendarCollection)
+ self.site.resource.putChild("calendars", calendarCollection)
def resetCalendars(self):
- del self.site.resource.putChildren['calendars']
+ del self.site.resource.putChildren["calendars"]
self.setupCalendars()
def test_guidchange(self):
"""
DirectoryPrincipalResource.proxies()
"""
+ oldUID = "5A985493-EE2C-4665-94CF-4DFEA3A89500"
+ newUID = "38D8AC00-5490-4425-BE3A-05FFB9862444"
+
+ homeResource = "/calendars/users/cdaboo/"
def privs1(result):
# Change GUID in record
fd = open(self.xmlfile, "w")
- fd.write(open(xmlFile.path, "r").read().replace("5A985493-EE2C-4665-94CF-4DFEA3A89500", "38D8AC00-5490-4425-BE3A-05FFB9862444"))
+ fd.write(open(xmlFile.path, "r").read().replace(oldUID, newUID))
fd.close()
fd = None
@@ -95,31 +99,43 @@
self.resetCalendars()
# Make sure new user cannot access old user's calendar home
- return self._checkPrivileges(None, "/calendars/users/cdaboo/", davxml.HRef("/principals/__uids__/38D8AC00-5490-4425-BE3A-05FFB9862444/"), davxml.Write, False)
+ return self._checkPrivileges(None, homeResource, davxml.HRef("/principals/__uids__/" + newUID + "/"), davxml.Write, False)
# Make sure current user has access to their calendar home
- d = self._checkPrivileges(None, "/calendars/users/cdaboo/", davxml.HRef("/principals/__uids__/5A985493-EE2C-4665-94CF-4DFEA3A89500/"), davxml.Write, True)
+ d = self._checkPrivileges(None, homeResource, davxml.HRef("/principals/__uids__/" + oldUID + "/"), davxml.Write, True)
d.addCallback(privs1)
return d
-
+ #
+ # This test fails because /calendars/users/cdaboo/ actually is a
+ # different resource (ie. the /calendars/__uids__/... URL would be
+ # different) when the GUID for cdaboo changes.
+ #
+ # The test needs to create a fixed resource with access granted to
+ # the old cdaboo; calendar homes no longer do this.
+ #
+ # Using the __uids__ URL won't work either because the old URL
+ # goes away with the old account.
+ #
+ test_guidchange.todo = "Test no longer works."
+
def _checkPrivileges(self, resource, url, principal, privilege, allowed):
- request = SimpleRequest(self.site, "GET", "/calendars/users/cdaboo/")
+ request = SimpleRequest(self.site, "GET", "/")
def gotResource(resource):
d = resource.checkPrivileges(request, (privilege,), principal=davxml.Principal(principal))
if allowed:
def onError(f):
f.trap(AccessDeniedError)
- #print resource.readDeadProperty(davxml.ACL)
- self.fail("%s should have %s privilege on %r" % (principal.sname(), privilege.sname(), resource))
+ #print resource.readDeadProperty(davxml.ACL).toxml()
+ self.fail("%s should have %s privilege on %r" % (principal, privilege.sname(), resource))
d.addErrback(onError)
else:
def onError(f):
f.trap(AccessDeniedError)
def onSuccess(_):
- #print resource.readDeadProperty(davxml.ACL)
- self.fail("%s should not have %s privilege on %r" % (principal.sname(), privilege.sname(), resource))
+ #print resource.readDeadProperty(davxml.ACL).toxml()
+ self.fail("%s should not have %s privilege on %r" % (principal, privilege.sname(), resource))
d.addCallback(onSuccess)
d.addErrback(onError)
return d
Modified: CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/schedule.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/schedule.py 2008-03-10 20:57:53 UTC (rev 2220)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/schedule.py 2008-03-10 21:04:44 UTC (rev 2221)
@@ -38,7 +38,6 @@
from twisted.web2.dav.util import joinURL
from twistedcaldav import caldavxml
-from twistedcaldav import customxml
from twistedcaldav import itip
from twistedcaldav.resource import CalDAVResource
from twistedcaldav.caldavxml import caldav_namespace, TimeRange
@@ -203,9 +202,9 @@
x.getResult()
# Must be content-type text/calendar
- content_type = request.headers.getHeader("content-type")
- if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != ("text", "calendar"):
- log.err("MIME type %s not allowed in calendar collection" % (content_type,))
+ contentType = request.headers.getHeader("content-type")
+ if contentType is not None and (contentType.mediaType, contentType.mediaSubtype) != ("text", "calendar"):
+ log.err("MIME type %s not allowed in calendar collection" % (contentType,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "supported-calendar-data")))
# Must have Originator header
@@ -217,37 +216,37 @@
originator = originator[0]
# Verify that Originator is a valid calendar user (has an INBOX)
- oprincipal = self.principalForCalendarUserAddress(originator)
- if oprincipal is None:
+ originatorPrincipal = self.principalForCalendarUserAddress(originator)
+ if originatorPrincipal is None:
log.err("Could not find principal for originator: %s" % (originator,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
- inboxURL = oprincipal.scheduleInboxURL()
+ inboxURL = originatorPrincipal.scheduleInboxURL()
if inboxURL is None:
log.err("Could not find inbox for originator: %s" % (originator,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
# Verify that Originator matches the authenticated user
- if davxml.Principal(davxml.HRef(oprincipal.principalURL())) != self.currentPrincipal(request):
+ if davxml.Principal(davxml.HRef(originatorPrincipal.principalURL())) != self.currentPrincipal(request):
log.err("Originator: %s does not match authorized user: %s" % (originator, self.currentPrincipal(request).children[0],))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
# Get list of Recipient headers
- rawrecipients = request.headers.getRawHeaders("recipient")
- if rawrecipients is None or (len(rawrecipients) == 0):
+ rawRecipients = request.headers.getRawHeaders("recipient")
+ if rawRecipients is None or (len(rawRecipients) == 0):
log.err("POST request must have at least one Recipient header")
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "recipient-specified")))
# Recipient header may be comma separated list
recipients = []
- for rawrecipient in rawrecipients:
- for r in rawrecipient.split(","):
+ for rawRecipient in rawRecipients:
+ for r in rawRecipient.split(","):
r = r.strip()
if len(r):
recipients.append(r)
- timerange = TimeRange(start="20000101", end="20000102")
- recipients_state = {"OK":0, "BAD":0}
+ timeRange = TimeRange(start="20000101", end="20000102")
+ recipientsState = {"OK":0, "BAD":0}
# Parse the calendar object from the HTTP request stream
try:
@@ -281,18 +280,21 @@
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (calendarserver_namespace, "no-access-restrictions")))
# Verify that the ORGANIZER's cu address maps to the request.uri
- outboxURL = None
organizer = calendar.getOrganizer()
- if organizer is not None:
- oprincipal = self.principalForCalendarUserAddress(organizer)
- if oprincipal is not None:
- outboxURL = oprincipal.scheduleOutboxURL()
- if outboxURL is None:
+ if organizer is None:
+ organizerPrincipal = None
+ else:
+ organizerPrincipal = self.principalForCalendarUserAddress(organizer)
+
+ if organizerPrincipal is None:
log.err("ORGANIZER in calendar data is not valid: %s" % (calendar,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "organizer-allowed")))
# Prevent spoofing of ORGANIZER with specific METHODs
- if (calendar.propertyValue("METHOD") in ("PUBLISH", "REQUEST", "ADD", "CANCEL", "DECLINECOUNTER")) and (outboxURL != request.uri):
+ if (
+ calendar.propertyValue("METHOD") in ("PUBLISH", "REQUEST", "ADD", "CANCEL", "DECLINECOUNTER") and
+ organizerPrincipal.record != self.parent.record
+ ):
log.err("ORGANIZER in calendar data does not match owner of Outbox: %s" % (calendar,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "organizer-allowed")))
@@ -308,11 +310,8 @@
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "attendee-allowed")))
# Attendee's Outbox MUST be the request URI
- aoutboxURL = None
- aprincipal = self.principalForCalendarUserAddress(attendees[0])
- if aprincipal is not None:
- aoutboxURL = aprincipal.scheduleOutboxURL()
- if aoutboxURL is None or aoutboxURL != request.uri:
+ attendeePrincipal = self.principalForCalendarUserAddress(attendees[0])
+ if attendeePrincipal is None or attendeePrincipal.record != self.parent.record:
log.err("ATTENDEE in calendar data does not match owner of Outbox: %s" % (calendar,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "attendee-allowed")))
@@ -328,11 +327,11 @@
if dtstart is None or dtend is None:
log.err("VFREEBUSY start/end not valid: %s" % (calendar,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "valid-calendar-data")))
- timerange.start = dtstart
- timerange.end = dtend
+ timeRange.start = dtstart
+ timeRange.end = dtend
# Look for maksed UID
- excludeuid = calendar.getMaskUID()
+ excludeUID = calendar.getMaskUID()
# Do free busy operation
freebusy = True
@@ -343,10 +342,6 @@
# Prepare for multiple responses
responses = ScheduleResponseQueue("POST", responsecode.OK)
- # Extract the ORGANIZER property and UID value from the calendar data for use later
- organizerProp = calendar.getOrganizerProperty()
- uid = calendar.resourceUID()
-
# Loop over each recipient and do appropriate action.
autoresponses = []
for recipient in recipients:
@@ -356,7 +351,7 @@
# Map recipient to their inbox
inbox = None
if principal is None:
- log.err("No principal for calendar user address: %s" % (recipient,))
+ log.err("No schedulable principal for calendar user address: %s" % (recipient,))
else:
inboxURL = principal.scheduleInboxURL()
if inboxURL:
@@ -369,7 +364,7 @@
if inbox is None:
err = HTTPError(ErrorResponse(responsecode.NOT_FOUND, (caldav_namespace, "recipient-exists")))
responses.add(recipient, Failure(exc_value=err), reqstatus="3.7;Invalid Calendar User")
- recipients_state["BAD"] += 1
+ recipientsState["BAD"] += 1
# Process next recipient
continue
@@ -378,14 +373,14 @@
# Check access controls
#
try:
- d = waitForDeferred(inbox.checkPrivileges(request, (caldavxml.Schedule(),), principal=davxml.Principal(davxml.HRef(oprincipal.principalURL()))))
+ d = waitForDeferred(inbox.checkPrivileges(request, (caldavxml.Schedule(),), principal=davxml.Principal(davxml.HRef(organizerPrincipal.principalURL()))))
yield d
d.getResult()
except AccessDeniedError:
log.err("Could not access Inbox for recipient: %s" % (recipient,))
err = HTTPError(ErrorResponse(responsecode.NOT_FOUND, (caldav_namespace, "recipient-permisions")))
responses.add(recipient, Failure(exc_value=err), reqstatus="3.8;No authority")
- recipients_state["BAD"] += 1
+ recipientsState["BAD"] += 1
# Process next recipient
continue
@@ -414,46 +409,54 @@
yield availability
availability = availability.getResult()
availability = availability.calendar()
- report_common.processAvailabilityFreeBusy(availability, fbinfo, timerange)
+ report_common.processAvailabilityFreeBusy(availability, fbinfo, timeRange)
# Check to see if the recipient is the same calendar user as the organizer.
# Needed for masked UID stuff.
- same_calendar_user = oprincipal.principalURL() == principal.principalURL()
+ same_calendar_user = organizerPrincipal.principalURL() == principal.principalURL()
# Now process free-busy set calendars
matchtotal = 0
- for calURL in fbset:
- cal = waitForDeferred(request.locateResource(calURL))
- yield cal
- cal = cal.getResult()
- if cal is None or not cal.exists() or not isCalendarCollectionResource(cal):
+ for calendarResourceURL in fbset:
+ calendarResource = waitForDeferred(request.locateResource(calendarResourceURL))
+ yield calendarResource
+ calendarResource = calendarResource.getResult()
+ if calendarResource is None or not calendarResource.exists() or not isCalendarCollectionResource(calendarResource):
# We will ignore missing calendars. If the recipient has failed to
# properly manage the free busy set that should not prevent us from working.
continue
matchtotal = waitForDeferred(report_common.generateFreeBusyInfo(
request,
- cal,
+ calendarResource,
fbinfo,
- timerange,
+ timeRange,
matchtotal,
- excludeuid=excludeuid,
- organizer=organizer,
- same_calendar_user=same_calendar_user))
+ excludeuid = excludeUID,
+ organizer = organizer,
+ same_calendar_user = same_calendar_user
+ ))
yield matchtotal
matchtotal = matchtotal.getResult()
# Build VFREEBUSY iTIP reply for this recipient
- fbresult = report_common.buildFreeBusyResult(fbinfo, timerange, organizer=organizerProp, attendee=attendeeProp, uid=uid, method="REPLY")
+ fbresult = report_common.buildFreeBusyResult(
+ fbinfo,
+ timeRange,
+ organizer = calendar.getOrganizerProperty(),
+ attendee = attendeeProp,
+ uid = calendar.resourceUID(),
+ method="REPLY"
+ )
responses.add(recipient, responsecode.OK, reqstatus="2.0;Success", calendar=fbresult)
- recipients_state["OK"] += 1
+ recipientsState["OK"] += 1
except:
log.err("Could not determine free busy information: %s" % (recipient,))
err = HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "recipient-permissions")))
responses.add(recipient, Failure(exc_value=err), reqstatus="3.8;No authority")
- recipients_state["BAD"] += 1
+ recipientsState["BAD"] += 1
else:
# Hash the iCalendar data for use as the last path element of the URI path
@@ -483,7 +486,7 @@
try:
d.getResult()
responses.add(recipient, responsecode.OK, reqstatus="2.0;Success")
- recipients_state["OK"] += 1
+ recipientsState["OK"] += 1
# Store CALDAV:originator property
child.writeDeadProperty(caldavxml.Originator(davxml.HRef(originator)))
@@ -498,7 +501,7 @@
log.err("Could not store data in Inbox : %s" % (inbox,))
err = HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "recipient-permissions")))
responses.add(recipient, Failure(exc_value=err), reqstatus="3.8;No authority")
- recipients_state["BAD"] += 1
+ recipientsState["BAD"] += 1
# Now we have to do auto-respond
if len(autoresponses) != 0:
Modified: CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/static.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/static.py 2008-03-10 20:57:53 UTC (rev 2220)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/static.py 2008-03-10 21:04:44 UTC (rev 2221)
@@ -24,7 +24,9 @@
"CalDAVFile",
"AutoProvisioningFileMixIn",
"CalendarHomeProvisioningFile",
+ "CalendarHomeUIDProvisioningFile",
"CalendarHomeFile",
+ "ScheduleFile",
"ScheduleInboxFile",
"ScheduleOutboxFile",
"DropBoxHomeFile",
@@ -65,8 +67,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
@@ -442,43 +446,71 @@
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()
+ self.provision()
+
+ oldPath = self.parent.getChild(record.recordType).fp.child(record.shortName)
+ if oldPath.exists():
+ #
+ # The child exists at the old (pre-1.2) location (ie. in the types
+ # hierarchy instead of the GUID hierarchy). Move to new location.
+ #
+ 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):
@@ -677,7 +709,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())
Modified: CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/test/data/makelargecalendars.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/test/data/makelargecalendars.py 2008-03-10 20:57:53 UTC (rev 2220)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/test/data/makelargecalendars.py 2008-03-10 21:04:44 UTC (rev 2221)
@@ -41,7 +41,7 @@
for ctr in xrange(1, user_max + 1):
- path = os.path.join(document_root, "calendars/users/user%02d" % (ctr,))
+ path = os.path.join(document_root, "calendars/__uids__/user%02d" % (ctr,))
try: os.makedirs(path)
except OSError: pass
Modified: CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/test/test_config.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/test/test_config.py 2008-03-10 20:57:53 UTC (rev 2220)
+++ CalendarServer/branches/release/CalendarServer-1.2-dev/twistedcaldav/test/test_config.py 2008-03-10 21:04:44 UTC (rev 2221)
@@ -224,4 +224,3 @@
config.EnableProxyPrincipals = False
self.assertTrue("calendar-proxy" not in resource.davComplianceClasses())
-
\ No newline at end of file
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080310/87b3d486/attachment-0001.html
More information about the calendarserver-changes
mailing list