[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