[CalendarServer-changes] [7601] CalendarServer/trunk/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Thu Jun 16 12:02:09 PDT 2011
Revision: 7601
http://trac.macosforge.org/projects/calendarserver/changeset/7601
Author: cdaboo at apple.com
Date: 2011-06-16 12:02:09 -0700 (Thu, 16 Jun 2011)
Log Message:
-----------
Make sure default calendar/addressbook cannot be set to a shared collection. Automatically fix this case if it happens, when the default property is read too.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/resource.py
CalendarServer/trunk/twistedcaldav/schedule.py
CalendarServer/trunk/twistedcaldav/test/test_resource.py
CalendarServer/trunk/twistedcaldav/test/test_schedule.py
Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py 2011-06-16 18:58:45 UTC (rev 7600)
+++ CalendarServer/trunk/twistedcaldav/resource.py 2011-06-16 19:02:09 UTC (rev 7601)
@@ -51,8 +51,7 @@
from twext.web2.dav.resource import AccessDeniedError, DAVPrincipalCollectionResource,\
davPrivilegeSet
from twext.web2.dav.resource import TwistedACLInheritable
-from twext.web2.dav.util import joinURL, parentForURL, normalizeURL,\
- unimplemented
+from twext.web2.dav.util import joinURL, parentForURL, normalizeURL
from twext.web2.http import HTTPError, RedirectResponse, StatusResponse, Response
from twext.web2.http_headers import MimeType
from twext.web2.stream import MemoryStream
@@ -2590,7 +2589,7 @@
if defaultAddressBookProperty and len(defaultAddressBookProperty.children) == 1:
defaultAddressBook = str(defaultAddressBookProperty.children[0])
adbk = (yield request.locateResource(str(defaultAddressBook)))
- if adbk is not None and adbk.exists() and isAddressBookCollectionResource(adbk):
+ if adbk is not None and isAddressBookCollectionResource(adbk) and adbk.exists() and not adbk.isVirtualShare():
returnValue(defaultAddressBookProperty)
# Default is not valid - we have to try to pick one
@@ -2612,7 +2611,7 @@
if len(new_adbk) == 1:
adbkURI = str(new_adbk[0])
adbk = (yield request.locateResource(str(new_adbk[0])))
- if adbk is None or not adbk.exists() or not isAddressBookCollectionResource(adbk):
+ if adbk is None or not adbk.exists() or not isAddressBookCollectionResource(adbk) or adbk.isVirtualShare():
# Validate that href's point to a valid addressbook.
raise HTTPError(ErrorResponse(
responsecode.CONFLICT,
@@ -2673,7 +2672,7 @@
defaultAddressBookURL = joinURL(self.url(), "addressbook")
defaultAddressBook = (yield self.makeRegularChild("addressbook"))
if defaultAddressBook is None or not defaultAddressBook.exists():
- getter = iter((yield self._newStoreHome.addressbooks()))
+ getter = iter((yield self._newStoreHome.addressbooks())) # These are only unshared children
# FIXME: the back-end should re-provision a default addressbook here.
# Really, the dead property shouldn't be necessary, and this should
# be entirely computed by a back-end method like 'defaultAddressBook()'
Modified: CalendarServer/trunk/twistedcaldav/schedule.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/schedule.py 2011-06-16 18:58:45 UTC (rev 7600)
+++ CalendarServer/trunk/twistedcaldav/schedule.py 2011-06-16 19:02:09 UTC (rev 7601)
@@ -168,7 +168,7 @@
if defaultCalendarProperty and len(defaultCalendarProperty.children) == 1:
defaultCalendar = str(defaultCalendarProperty.children[0])
cal = (yield request.locateResource(str(defaultCalendar)))
- if cal is not None and isCalendarCollectionResource(cal) and cal.exists():
+ if cal is not None and isCalendarCollectionResource(cal) and cal.exists() and not cal.isVirtualShare():
returnValue(defaultCalendarProperty)
# Default is not valid - we have to try to pick one
@@ -223,7 +223,7 @@
calURI = str(new_calendar[0])
cal = (yield request.locateResource(str(new_calendar[0])))
# 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):
+ if cal is None or not cal.exists() or not isCalendarCollectionResource(cal) or cal.isVirtualShare():
# Validate that href's point to a valid calendar.
raise HTTPError(ErrorResponse(
responsecode.CONFLICT,
@@ -263,16 +263,17 @@
defaultCalendarURL = joinURL(calendarHomeURL, "calendar")
defaultCalendar = (yield request.locateResource(defaultCalendarURL))
if defaultCalendar is None or not defaultCalendar.exists():
- getter = iter((yield self.parent._newStoreHome.calendars()))
# FIXME: the back-end should re-provision a default calendar here.
# Really, the dead property shouldn't be necessary, and this should
# be entirely computed by a back-end method like 'defaultCalendar()'
- try:
- aCalendar = getter.next()
- except StopIteration:
- raise RuntimeError("No calendars at all.")
+ for calendarName in (yield self.parent._newStoreHome.listCalendars()): # These are only unshared children
+ if calendarName != "inbox":
+ aCalendar = calendarName
+ break
+ else:
+ raise RuntimeError("No valid calendars to use as a default calendar.")
- defaultCalendarURL = joinURL(calendarHomeURL, aCalendar.name())
+ defaultCalendarURL = joinURL(calendarHomeURL, aCalendar)
self.writeDeadProperty(
caldavxml.ScheduleDefaultCalendarURL(
Modified: CalendarServer/trunk/twistedcaldav/test/test_resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_resource.py 2011-06-16 18:58:45 UTC (rev 7600)
+++ CalendarServer/trunk/twistedcaldav/test/test_resource.py 2011-06-16 19:02:09 UTC (rev 7601)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2008 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2011 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,22 +14,21 @@
# limitations under the License.
##
-from twisted.internet.defer import inlineCallbacks
-
-from twext.web2.test.test_server import SimpleRequest
-
+from twext.web2.dav import davxml
from twext.web2.dav.davxml import Principal
from twext.web2.dav.davxml import Unauthenticated
from twext.web2.dav.element.rfc2518 import HRef
+from twext.web2.http import HTTPError
+from twext.web2.test.test_server import SimpleRequest
-from twistedcaldav.resource import (
- CalDAVResource, CommonHomeResource, CalendarHomeResource,
- AddressBookHomeResource)
+from twisted.internet.defer import inlineCallbacks
+from twistedcaldav import carddavxml
+from twistedcaldav.config import config
+from twistedcaldav.resource import CalDAVResource, CommonHomeResource, \
+ CalendarHomeResource, AddressBookHomeResource
from twistedcaldav.test.util import InMemoryPropertyStore
from twistedcaldav.test.util import TestCase
-from twistedcaldav.config import config
-
from twistedcaldav.test.util import patchConfig
@@ -215,3 +214,130 @@
rsrc.owner = lambda igreq: HRef("/some-other-user/")
self.assertEquals((yield rsrc.isOwner(request)), True)
+
+class DefaultAddressBook (TestCase):
+
+ def setUp(self):
+ super(DefaultAddressBook, self).setUp()
+ self.createStockDirectoryService()
+ self.setupCalendars()
+
+ @inlineCallbacks
+ def test_pick_default_addressbook(self):
+ """
+ Make calendar
+ """
+
+
+ request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ home = yield request.locateResource("/addressbooks/users/wsanchez")
+
+ # default property initially not present
+ try:
+ home.readDeadProperty(carddavxml.DefaultAddressBookURL)
+ except HTTPError:
+ pass
+ else:
+ self.fail("carddavxml.DefaultAddressBookURL is not empty")
+
+ yield home.pickNewDefaultAddressBook(request)
+
+ try:
+ default = home.readDeadProperty(carddavxml.DefaultAddressBookURL)
+ except HTTPError:
+ self.fail("carddavxml.DefaultAddressBookURL is not present")
+ else:
+ self.assertEqual(str(default.children[0]), "/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/addressbook")
+
+ request._newStoreTransaction.abort()
+
+ @inlineCallbacks
+ def test_pick_default_other(self):
+ """
+ Make adbk
+ """
+
+
+ request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ home = yield request.locateResource("/addressbooks/users/wsanchez")
+
+ # default property not present
+ try:
+ home.readDeadProperty(carddavxml.DefaultAddressBookURL)
+ except HTTPError:
+ pass
+ else:
+ self.fail("carddavxml.DefaultAddressBookURL is not empty")
+
+ # Create a new default adbk
+ newadbk = yield request.locateResource("/addressbooks/users/wsanchez/newadbk")
+ yield newadbk.createAddressBookCollection()
+ home.writeDeadProperty(carddavxml.DefaultAddressBookURL(
+ davxml.HRef("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk")
+ ))
+ request._newStoreTransaction.commit()
+
+ # Delete the normal adbk
+ request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ home = yield request.locateResource("/addressbooks/users/wsanchez")
+ adbk = yield request.locateResource("/addressbooks/users/wsanchez/addressbook")
+ yield adbk.storeRemove(request, False, "/addressbooks/users/wsanchez/addressbook")
+
+ home.removeDeadProperty(carddavxml.DefaultAddressBookURL)
+
+ # default property not present
+ try:
+ home.readDeadProperty(carddavxml.DefaultAddressBookURL)
+ except HTTPError:
+ pass
+ else:
+ self.fail("carddavxml.DefaultAddressBookURL is not empty")
+ request._newStoreTransaction.commit()
+
+ request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ home = yield request.locateResource("/addressbooks/users/wsanchez")
+ yield home.pickNewDefaultAddressBook(request)
+
+ try:
+ default = home.readDeadProperty(carddavxml.DefaultAddressBookURL)
+ except HTTPError:
+ self.fail("carddavxml.DefaultAddressBookURL is not present")
+ else:
+ self.assertEqual(str(default.children[0]), "/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk")
+
+ request._newStoreTransaction.abort()
+
+ @inlineCallbacks
+ def test_fix_shared_default(self):
+ """
+ Make calendar
+ """
+
+
+ request = SimpleRequest(self.site, "GET", "/addressbooks/users/wsanchez/")
+ home = yield request.locateResource("/addressbooks/users/wsanchez")
+
+ # Create a new default adbk
+ newadbk = yield request.locateResource("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk")
+ yield newadbk.createAddressBookCollection()
+ home.writeDeadProperty(carddavxml.DefaultAddressBookURL(
+ davxml.HRef("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk")
+ ))
+ try:
+ default = yield home.readProperty(carddavxml.DefaultAddressBookURL, request)
+ except HTTPError:
+ self.fail("carddavxml.DefaultAddressBookURL is not present")
+ else:
+ self.assertEqual(str(default.children[0]), "/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk")
+
+ # Force the new calendar to think it is a virtual share
+ newadbk._isVirtualShare = True
+
+ try:
+ default = yield home.readProperty(carddavxml.DefaultAddressBookURL, request)
+ except HTTPError:
+ self.fail("carddavxml.DefaultAddressBookURL is not present")
+ else:
+ self.assertEqual(str(default.children[0]), "/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/addressbook")
+
+ request._newStoreTransaction.abort()
Modified: CalendarServer/trunk/twistedcaldav/test/test_schedule.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_schedule.py 2011-06-16 18:58:45 UTC (rev 7600)
+++ CalendarServer/trunk/twistedcaldav/test/test_schedule.py 2011-06-16 19:02:09 UTC (rev 7601)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2011 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,16 +15,18 @@
##
from twext.web2 import responsecode
-from twext.web2.iweb import IResponse
from twext.web2.dav import davxml
from twext.web2.dav.util import davXMLFromStream
+from twext.web2.http import HTTPError
+from twext.web2.iweb import IResponse
from twext.web2.stream import MemoryStream
from twext.web2.test.test_server import SimpleRequest
+from twisted.internet.defer import inlineCallbacks
+
from twistedcaldav import caldavxml
+from twistedcaldav.test.util import HomeTestCase, TestCase
-from twistedcaldav.test.util import HomeTestCase
-
class Properties (HomeTestCase):
"""
CalDAV properties
@@ -80,3 +82,127 @@
request = SimpleRequest(self.site, "PROPFIND", inbox_uri)
request.stream = MemoryStream(query.toxml())
return self.send(request, propfind_cb)
+
+class DefaultCalendar (TestCase):
+
+ def setUp(self):
+ super(DefaultCalendar, self).setUp()
+ self.createStockDirectoryService()
+ self.setupCalendars()
+
+ @inlineCallbacks
+ def test_pick_default_calendar(self):
+ """
+ Make calendar
+ """
+
+
+ request = SimpleRequest(self.site, "GET", "/calendars/users/wsanchez/")
+ inbox = yield request.locateResource("/calendars/users/wsanchez/inbox")
+
+ # default property initially not present
+ try:
+ inbox.readDeadProperty(caldavxml.ScheduleDefaultCalendarURL)
+ except HTTPError:
+ pass
+ else:
+ self.fail("caldavxml.ScheduleDefaultCalendarURL is not empty")
+
+ yield inbox.pickNewDefaultCalendar(request)
+
+ try:
+ default = inbox.readDeadProperty(caldavxml.ScheduleDefaultCalendarURL)
+ except HTTPError:
+ self.fail("caldavxml.ScheduleDefaultCalendarURL is not present")
+ else:
+ self.assertEqual(str(default.children[0]), "/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/calendar")
+
+ request._newStoreTransaction.abort()
+
+ @inlineCallbacks
+ def test_pick_default_other(self):
+ """
+ Make calendar
+ """
+
+
+ request = SimpleRequest(self.site, "GET", "/calendars/users/wsanchez/")
+ inbox = yield request.locateResource("/calendars/users/wsanchez/inbox")
+
+ # default property not present
+ try:
+ inbox.readDeadProperty(caldavxml.ScheduleDefaultCalendarURL)
+ except HTTPError:
+ pass
+ else:
+ self.fail("caldavxml.ScheduleDefaultCalendarURL is not empty")
+
+ # Create a new default calendar
+ newcalendar = yield request.locateResource("/calendars/users/wsanchez/newcalendar")
+ yield newcalendar.createCalendarCollection()
+ inbox.writeDeadProperty(caldavxml.ScheduleDefaultCalendarURL(
+ davxml.HRef("/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newcalendar")
+ ))
+
+ # Delete the normal calendar
+ calendar = yield request.locateResource("/calendars/users/wsanchez/calendar")
+ yield calendar.storeRemove(request, False, "/calendars/users/wsanchez/calendar")
+
+ inbox.removeDeadProperty(caldavxml.ScheduleDefaultCalendarURL)
+
+ # default property not present
+ try:
+ inbox.readDeadProperty(caldavxml.ScheduleDefaultCalendarURL)
+ except HTTPError:
+ pass
+ else:
+ self.fail("caldavxml.ScheduleDefaultCalendarURL is not empty")
+ request._newStoreTransaction.commit()
+
+ request = SimpleRequest(self.site, "GET", "/calendars/users/wsanchez/")
+ inbox = yield request.locateResource("/calendars/users/wsanchez/inbox")
+ yield inbox.pickNewDefaultCalendar(request)
+
+ try:
+ default = inbox.readDeadProperty(caldavxml.ScheduleDefaultCalendarURL)
+ except HTTPError:
+ self.fail("caldavxml.ScheduleDefaultCalendarURL is not present")
+ else:
+ self.assertEqual(str(default.children[0]), "/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newcalendar")
+
+ request._newStoreTransaction.abort()
+
+ @inlineCallbacks
+ def test_fix_shared_default(self):
+ """
+ Make calendar
+ """
+
+
+ request = SimpleRequest(self.site, "GET", "/calendars/users/wsanchez/")
+ inbox = yield request.locateResource("/calendars/users/wsanchez/inbox")
+
+ # Create a new default calendar
+ newcalendar = yield request.locateResource("/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newcalendar")
+ yield newcalendar.createCalendarCollection()
+ inbox.writeDeadProperty(caldavxml.ScheduleDefaultCalendarURL(
+ davxml.HRef("/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newcalendar")
+ ))
+ try:
+ default = yield inbox.readProperty(caldavxml.ScheduleDefaultCalendarURL, request)
+ except HTTPError:
+ self.fail("caldavxml.ScheduleDefaultCalendarURL is not present")
+ else:
+ self.assertEqual(str(default.children[0]), "/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newcalendar")
+
+ # Force the new calendar to think it is a virtual share
+ newcalendar._isVirtualShare = True
+
+ try:
+ default = yield inbox.readProperty(caldavxml.ScheduleDefaultCalendarURL, request)
+ except HTTPError:
+ self.fail("caldavxml.ScheduleDefaultCalendarURL is not present")
+ else:
+ self.assertEqual(str(default.children[0]), "/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/calendar")
+
+ request._newStoreTransaction.abort()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110616/23e8e10c/attachment-0001.html>
More information about the calendarserver-changes
mailing list