[CalendarServer-changes] [9219] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed May 2 08:47:10 PDT 2012


Revision: 9219
          http://trac.macosforge.org/projects/calendarserver/changeset/9219
Author:   glyph at apple.com
Date:     2012-05-02 08:47:09 -0700 (Wed, 02 May 2012)
Log Message:
-----------
if the calendar is already shared, change the sharing mode when shareWith is called again.

Modified Paths:
--------------
    CalendarServer/trunk/txdav/caldav/datastore/test/common.py
    CalendarServer/trunk/txdav/common/datastore/sql.py

Property Changed:
----------------
    CalendarServer/trunk/

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2012-05-01 21:05:31 UTC (rev 9218)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2012-05-02 15:47:09 UTC (rev 9219)
@@ -43,7 +43,7 @@
 from txdav.common.icommondatastore import ObjectResourceNameAlreadyExistsError
 from txdav.common.inotifications import INotificationObject
 from txdav.common.datastore.test.util import CommonCommonTests
-from txdav.common.datastore.sql_tables import _BIND_MODE_WRITE
+from txdav.common.datastore.sql_tables import _BIND_MODE_WRITE, _BIND_MODE_READ
 
 from txdav.caldav.icalendarstore import (
     ICalendarObject, ICalendarHome,
@@ -1014,6 +1014,28 @@
 
 
     @inlineCallbacks
+    def test_shareAgainChangesMode(self):
+        """
+        If a calendar is already shared with a given calendar home,
+        L{ICalendar.shareWith} will change the sharing mode.
+        """
+        yield self.test_shareWith()
+        # yield self.commit() # txn is none? why?
+        OTHER_HOME_UID = "home_splits"
+        cal = yield self.calendarUnderTest()
+        other = yield self.homeUnderTest(name=OTHER_HOME_UID)
+        newName = yield cal.shareWith(other, _BIND_MODE_READ)
+        otherCal = yield other.sharedChildWithName(newName)
+        self.assertNotIdentical(otherCal, None)
+
+        # FIXME: permission information should be visible on the retrieved
+        # calendar object, we shoudln't need to go via the legacy API.
+        invites = yield cal.retrieveOldInvites().allRecords()
+        self.assertEqual(len(invites), 1)
+        self.assertEqual(invites[0].access, "read-only")
+
+
+    @inlineCallbacks
     def test_hasCalendarResourceUIDSomewhereElse(self):
         """
         L{ICalendarHome.hasCalendarResourceUIDSomewhereElse} will determine if

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2012-05-01 21:05:31 UTC (rev 9218)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2012-05-02 15:47:09 UTC (rev 9219)
@@ -552,16 +552,22 @@
         object to execute SQL on.
 
         @param thunk: a 1-argument callable which returns a Deferred when it is
-            done.  If this Deferred fails, 
+            done.  If this Deferred fails, the sub-transaction will be rolled
+            back.
+        @type thunk: L{callable}
 
         @param retries: the number of times to re-try C{thunk} before deciding
             that it's legitimately failed.
+        @type retries: L{int}
 
         @param failureOK: it is OK if this subtransaction fails so do not log.
+        @type failureOK: L{bool}
 
         @return: a L{Deferred} which fires or fails according to the logic in
             C{thunk}.  If it succeeds, it will return the value that C{thunk}
-            returned.
+            returned.  If C{thunk} fails or raises an exception more than
+            C{retries} times, then the L{Deferred} resulting from
+            C{subtransaction} will fail with L{AllRetriesFailed}.
         """
         # Right now this code is covered mostly by the automated property store
         # tests.  It should have more direct test coverage.
@@ -1958,6 +1964,18 @@
         )
 
 
+    @classproperty
+    def _updateBindQuery(cls): #@NoSelf
+        bind = cls._bindSchema
+        return Update({bind.BIND_MODE: Parameter("mode"),
+                       bind.BIND_STATUS: Parameter("status"),
+                       bind.MESSAGE: Parameter("message")},
+                      Where=
+                      (bind.RESOURCE_ID == Parameter("resourceID"))
+                      .And(bind.HOME_RESOURCE_ID == Parameter("homeID")),
+                      Return=bind.RESOURCE_NAME)
+
+
     @inlineCallbacks
     def shareWith(self, shareeHome, mode):
         """
@@ -1977,22 +1995,37 @@
         dnprop = (self.properties().get(dn) or
                   DisplayName.fromString(self.name()))
         # FIXME: honor current home type
-        newName = str(uuid4())
-        yield self._bindInsertQuery.on(
-            self._txn, homeID=shareeHome._resourceID,
-            resourceID=self._resourceID, name=newName, mode=mode,
-            seenByOwner=True, seenBySharee=True,
-            bindStatus=_BIND_STATUS_ACCEPTED,
-        )
-        yield self._insertInviteQuery.on(
-            self._txn, uid=newName, name=str(dnprop),
-            homeID=shareeHome._resourceID, resourceID=self._resourceID,
-            recipient=shareeHome.uid()
-        )
+        @inlineCallbacks
+        def doInsert(subt):
+            newName = str(uuid4())
+            yield self._bindInsertQuery.on(
+                subt, homeID=shareeHome._resourceID,
+                resourceID=self._resourceID, name=newName, mode=mode,
+                seenByOwner=True, seenBySharee=True,
+                bindStatus=_BIND_STATUS_ACCEPTED,
+            )
+            yield self._insertInviteQuery.on(
+                subt, uid=newName, name=str(dnprop),
+                homeID=shareeHome._resourceID, resourceID=self._resourceID,
+                recipient=shareeHome.uid()
+            )
+            returnValue(newName)
+        try:
+            sharedName = yield self._txn.subtransaction(doInsert)
+        except AllRetriesFailed:
+            # FIXME: catch more specific exception
+            sharedName = (yield self._updateBindQuery.on(
+                self._txn,
+                mode=mode, status=_BIND_STATUS_ACCEPTED, message=None,
+                resourceID=self._resourceID, homeID=shareeHome._resourceID
+            ))[0][0]
+            # Invite already exists; no need to update it, since the name will
+            # remain the same.
+
         shareeProps = yield PropertyStore.load(shareeHome.uid(), self._txn,
                                                self._resourceID)
         shareeProps[dn] = dnprop
-        returnValue(newName)
+        returnValue(sharedName)
 
 
     @classmethod
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120502/2c05e2e6/attachment.html>


More information about the calendarserver-changes mailing list