[CalendarServer-changes] [3760] CalendarServer/trunk/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Thu Feb 26 19:27:50 PST 2009
Revision: 3760
http://trac.macosforge.org/projects/calendarserver/changeset/3760
Author: cdaboo at apple.com
Date: 2009-02-26 19:27:49 -0800 (Thu, 26 Feb 2009)
Log Message:
-----------
Default calendar is now required.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/method/copymove.py
CalendarServer/trunk/twistedcaldav/method/delete_common.py
CalendarServer/trunk/twistedcaldav/resource.py
CalendarServer/trunk/twistedcaldav/schedule.py
CalendarServer/trunk/twistedcaldav/scheduling/processing.py
Modified: CalendarServer/trunk/twistedcaldav/method/copymove.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/copymove.py 2009-02-27 03:11:59 UTC (rev 3759)
+++ CalendarServer/trunk/twistedcaldav/method/copymove.py 2009-02-27 03:27:49 UTC (rev 3760)
@@ -119,13 +119,14 @@
result, sourcecal, sourceparent, destination_uri, destination, destinationcal, destinationparent = (yield checkForCalendarAction(self, request))
if not result:
is_calendar_collection = isPseudoCalendarCollectionResource(self)
+ defaultCalendar = (yield self.isDefaultCalendar(request)) if is_calendar_collection else False
# Do default WebDAV action
result = (yield super(CalDAVFile, self).http_MOVE(request))
if is_calendar_collection:
# Do some clean up
- yield self.movedCalendar(request, destination, destination_uri)
+ yield self.movedCalendar(request, defaultCalendar, destination, destination_uri)
returnValue(result)
Modified: CalendarServer/trunk/twistedcaldav/method/delete_common.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/delete_common.py 2009-02-27 03:11:59 UTC (rev 3759)
+++ CalendarServer/trunk/twistedcaldav/method/delete_common.py 2009-02-27 03:27:49 UTC (rev 3760)
@@ -13,7 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
-from twistedcaldav.method.report_common import applyToCalendarCollections
"""
@@ -25,12 +24,15 @@
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.web2 import responsecode
from twisted.web2.dav.fileop import delete
-from twisted.web2.dav.http import ResponseQueue, MultiStatusResponse
+from twisted.web2.dav.http import ResponseQueue, MultiStatusResponse,\
+ ErrorResponse
from twisted.web2.dav.util import joinURL
from twisted.web2.http import HTTPError, StatusResponse
+from twistedcaldav.caldavxml import caldav_namespace
from twistedcaldav.log import Logger
from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
+from twistedcaldav.method.report_common import applyToCalendarCollections
from twistedcaldav.resource import isCalendarCollectionResource,\
isPseudoCalendarCollectionResource
from twistedcaldav.scheduling.implicit import ImplicitScheduler
@@ -160,6 +162,12 @@
reported back in a multistatus response.
"""
+ # Not allowed to delete the default calendar
+ default = (yield delresource.isDefaultCalendar(self.request))
+ if default:
+ log.err("Cannot DELETE default calendar: %s" % (delresource,))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "default-calendar-delete-allowed",)))
+
if self.depth != "infinity":
msg = "Client sent illegal depth header value for DELETE: %s" % (self.depth,)
log.err(msg)
Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py 2009-02-27 03:11:59 UTC (rev 3759)
+++ CalendarServer/trunk/twistedcaldav/resource.py 2009-02-27 03:27:49 UTC (rev 3760)
@@ -549,21 +549,11 @@
if inboxURL:
inbox = (yield request.locateResource(inboxURL))
inbox.processFreeBusyCalendar(request.path, False)
-
- # Also check the default calendar setting and remove it if the default is deleted
- default = (yield inbox.readProperty((caldav_namespace, "schedule-default-calendar-URL"), request))
- if default and len(default.children) == 1:
- defaultURL = normalizeURL(str(default.children[0]))
- if normalizeURL(request.path) == defaultURL:
- yield inbox.writeProperty(caldavxml.ScheduleDefaultCalendarURL(), request)
@inlineCallbacks
- def movedCalendar(self, request, destination, destination_uri):
+ def movedCalendar(self, request, defaultCalendar, destination, destination_uri):
"""
Calendar has been moved. Need to do some extra clean-up.
-
- @param request:
- @type request:
"""
# For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
@@ -576,12 +566,9 @@
inbox.processFreeBusyCalendar(request.path, False)
inbox.processFreeBusyCalendar(destination_uri, destination.isCalendarOpaque())
- # Also check the default calendar setting and remove it if the default is deleted
- default = (yield inbox.readProperty((caldav_namespace, "schedule-default-calendar-URL"), request))
- if default and len(default.children) == 1:
- defaultURL = normalizeURL(str(default.children[0]))
- if normalizeURL(request.path) == defaultURL:
- yield inbox.writeProperty(caldavxml.ScheduleDefaultCalendarURL(davxml.HRef(destination_path)), request)
+ # Adjust the default calendar setting if necessary
+ if defaultCalendar:
+ yield inbox.writeProperty(caldavxml.ScheduleDefaultCalendarURL(davxml.HRef(destination_path)), request)
def isCalendarOpaque(self):
@@ -593,6 +580,24 @@
else:
return False
+ @inlineCallbacks
+ def isDefaultCalendar(self, request):
+
+ assert self.isCalendarCollection()
+
+ # Not allowed to delete the default calendar
+ principal = (yield self.ownerPrincipal(request))
+ inboxURL = principal.scheduleInboxURL()
+ if inboxURL:
+ inbox = (yield request.locateResource(inboxURL))
+ default = (yield inbox.readProperty((caldav_namespace, "schedule-default-calendar-URL"), request))
+ if default and len(default.children) == 1:
+ defaultURL = normalizeURL(str(default.children[0]))
+ myURL = (yield self.canonicalURL(request))
+ returnValue(defaultURL == myURL)
+
+ returnValue(False)
+
def iCalendar(self, name=None):
"""
See L{ICalDAVResource.iCalendar}.
Modified: CalendarServer/trunk/twistedcaldav/schedule.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/schedule.py 2009-02-27 03:11:59 UTC (rev 3759)
+++ CalendarServer/trunk/twistedcaldav/schedule.py 2009-02-27 03:27:49 UTC (rev 3760)
@@ -24,7 +24,7 @@
"IScheduleInboxResource",
]
-from twisted.internet.defer import succeed, inlineCallbacks, returnValue
+from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.web2 import responsecode
from twisted.web2.dav import davxml
from twisted.web2.dav.http import ErrorResponse
@@ -105,6 +105,7 @@
),
)
+ @inlineCallbacks
def readProperty(self, property, request):
if type(property) is tuple:
qname = property
@@ -114,13 +115,22 @@
if qname == (caldav_namespace, "calendar-free-busy-set"):
# Always return at least an empty list
if not self.hasDeadProperty(property):
- return succeed(caldavxml.CalendarFreeBusySet())
+ returnValue(caldavxml.CalendarFreeBusySet())
elif qname == (caldav_namespace, "schedule-default-calendar-URL"):
- # Always return at least an empty item
- if not self.hasDeadProperty(property):
- return succeed(caldavxml.ScheduleDefaultCalendarURL())
+ # Must have a valid default
+ defaultCalendarProperty = self.readDeadProperty(property)
+ if defaultCalendarProperty and len(defaultCalendarProperty.children) == 1:
+ defaultCalendar = str(defaultCalendarProperty.children[0])
+ cal = (yield request.locateResource(str(defaultCalendar)))
+ if cal is not None and cal.exists() and isCalendarCollectionResource(cal):
+ returnValue(defaultCalendarProperty)
- return super(ScheduleInboxResource, self).readProperty(property, request)
+ # Default is not valid - we have to try to pick one
+ defaultCalendarProperty = (yield self.pickNewDefaultCalendar(request))
+ returnValue(defaultCalendarProperty)
+
+ result = (yield super(ScheduleInboxResource, self).readProperty(property, request))
+ returnValue(result)
@inlineCallbacks
def writeProperty(self, property, request):
@@ -160,14 +170,21 @@
# Verify that the calendar added in the PROPPATCH is valid.
property.children = [davxml.HRef(normalizeURL(str(href))) for href in property.children]
new_calendar = [str(href) for href in property.children]
+ cal = None
if len(new_calendar) == 1:
+ calURI = str(new_calendar[0])
cal = (yield request.locateResource(str(new_calendar[0])))
- if cal is None or not cal.exists() or not isCalendarCollectionResource(cal):
- # Validate that href's point to a valid calendar.
- raise HTTPError(ErrorResponse(
- responsecode.CONFLICT,
- (caldav_namespace, "valid-calendar-url")
- ))
+ # TODO: check that owner of the new calendar is the same as owner of this inbox
+ if cal is None or not cal.exists() or not isCalendarCollectionResource(cal):
+ # Validate that href's point to a valid calendar.
+ raise HTTPError(ErrorResponse(
+ responsecode.CONFLICT,
+ (caldav_namespace, "valid-schedule-default-calendar-URL")
+ ))
+ else:
+ # Canonicalize the URL to __uids__ form
+ calURI = (yield cal.canonicalURL(request))
+ property = caldavxml.ScheduleDefaultCalendarURL(davxml.HRef(calURI))
yield super(ScheduleInboxResource, self).writeProperty(property, request)
@@ -187,6 +204,22 @@
fbset.remove(uri)
self.writeDeadProperty(caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in fbset]))
+ @inlineCallbacks
+ def pickNewDefaultCalendar(self, request):
+ """
+ First see if "calendar" exists in the calendar home and pick that. Otherwise
+ create "calendar" in the calendar home.
+ """
+
+ calendarHomeURL = self.parent.url()
+ defaultCalendarURL = (yield joinURL(calendarHomeURL, "calendar"))
+ defaultCalendar = (yield request.locateResource(defaultCalendarURL))
+ if defaultCalendar is None or not defaultCalendar.exists():
+ self.parent.provisionDefaultCalendars()
+ else:
+ self.writeDeadProperty(caldavxml.ScheduleDefaultCalendarURL(davxml.HRef(defaultCalendarURL)))
+ returnValue(caldavxml.ScheduleDefaultCalendarURL(davxml.HRef(defaultCalendarURL)))
+
class ScheduleOutboxResource (CalendarSchedulingCollectionResource):
"""
CalDAV schedule Outbox resource.
Modified: CalendarServer/trunk/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/processing.py 2009-02-27 03:11:59 UTC (rev 3759)
+++ CalendarServer/trunk/twistedcaldav/scheduling/processing.py 2009-02-27 03:27:49 UTC (rev 3760)
@@ -260,37 +260,33 @@
else:
default = None
- # Must have a calendar if auto-replying
- if default is None and self.recipient.principal.autoSchedule():
- log.error("No default calendar for auto-replying recipient: '%s'." % (self.recipient.cuaddr,))
+ # Must have a default calendar
+ if default is None:
+ log.error("No default calendar for recipient: '%s'." % (self.recipient.cuaddr,))
raise ImplicitProcessorException(iTIPRequestStatus.NO_USER_SUPPORT)
- if default:
- log.debug("ImplicitProcessing - originator '%s' to recipient '%s' ignoring METHOD:REQUEST, UID: '%s' - new processed" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
- autoprocessed = self.recipient.principal.autoSchedule()
- new_calendar = iTipProcessing.processNewRequest(self.message, self.recipient.cuaddr, autoprocessing=autoprocessed)
- name = md5(str(new_calendar) + str(time.time()) + default.fp.path).hexdigest() + ".ics"
-
- # Handle auto-reply behavior
- if autoprocessed:
- send_reply, partstat = (yield self.checkAttendeeAutoReply(new_calendar))
+ log.debug("ImplicitProcessing - originator '%s' to recipient '%s' ignoring METHOD:REQUEST, UID: '%s' - new processed" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
+ autoprocessed = self.recipient.principal.autoSchedule()
+ new_calendar = iTipProcessing.processNewRequest(self.message, self.recipient.cuaddr, autoprocessing=autoprocessed)
+ name = md5(str(new_calendar) + str(time.time()) + default.fp.path).hexdigest() + ".ics"
+
+ # Handle auto-reply behavior
+ if autoprocessed:
+ send_reply, partstat = (yield self.checkAttendeeAutoReply(new_calendar))
- new_resource = (yield self.writeCalendarResource(defaultURL, default, name, new_calendar))
-
- if autoprocessed and send_reply:
- reactor.callLater(2.0, self.sendAttendeeAutoReply, *(new_calendar, new_resource, partstat))
+ new_resource = (yield self.writeCalendarResource(defaultURL, default, name, new_calendar))
+
+ if autoprocessed and send_reply:
+ reactor.callLater(2.0, self.sendAttendeeAutoReply, *(new_calendar, new_resource, partstat))
- # Build the schedule-changes XML element
- changes = customxml.ScheduleChanges(
- customxml.DTStamp(),
- customxml.Action(
- customxml.Create(),
- ),
- )
- result = (True, autoprocessed, changes,)
- else:
- log.debug("ImplicitProcessing - originator '%s' to recipient '%s' ignoring METHOD:REQUEST, UID: '%s' - new not processed" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
- result = (False, False, None,)
+ # Build the schedule-changes XML element
+ changes = customxml.ScheduleChanges(
+ customxml.DTStamp(),
+ customxml.Action(
+ customxml.Create(),
+ ),
+ )
+ result = (True, autoprocessed, changes,)
else:
# Processing update to existing event
autoprocessed = self.recipient.principal.autoSchedule()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090226/a95c91b9/attachment-0001.html>
More information about the calendarserver-changes
mailing list