[CalendarServer-changes] [10745] CalendarServer/branches/users/gaya/sharedgroups

source_changes at macosforge.org source_changes at macosforge.org
Fri Feb 15 14:45:11 PST 2013


Revision: 10745
          http://trac.calendarserver.org//changeset/10745
Author:   gaya at apple.com
Date:     2013-02-15 14:45:11 -0800 (Fri, 15 Feb 2013)
Log Message:
-----------
name wrangling, fix unshare(), checkpoint

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/caldav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/common.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_file.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/iaddressbookstore.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py	2013-02-15 22:01:47 UTC (rev 10744)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py	2013-02-15 22:45:11 UTC (rev 10745)
@@ -152,7 +152,7 @@
                 "Invalid invitation uid: %s" % (inviteUID,),
             ))
 
-        # Only certain states are sharer controlled
+        # Only certain states are owner controlled
         if invitation.state() in ("NEEDS-ACTION", "ACCEPTED", "DECLINED",):
             yield self._updateInvitation(invitation, state=state, summary=summary)
 
@@ -685,15 +685,11 @@
             pass
         '''
 
-
         # Generate invite XML
         userid = "urn:uuid:" + invitation.shareeUID()
         state = notificationState if notificationState else invitation.state()
         summary = invitation.summary() if displayName is None else displayName
 
-
-        assert state != "DECLINED"
-
         typeAttr = {'shared-type': self.sharedResourceType()}
         xmltype = customxml.InviteNotification(**typeAttr)
         xmldata = customxml.Notification(
@@ -1025,32 +1021,32 @@
             returnValue(None)
 
         # get the shared object's URL
-        sharer = self.principalForUID(storeObject.ownerHome().uid())
+        owner = self.principalForUID(storeObject.ownerHome().uid())
 
         if not request:
-            # FIXEME:  Fake up a request that can be used to get the sharer home resource
+            # FIXEME:  Fake up a request that can be used to get the owner home resource
             class _FakeRequest(object):pass
             fakeRequest = _FakeRequest()
             setattr(fakeRequest, TRANSACTION_KEY, self._newStoreHome._txn)
             request = fakeRequest
 
         if self._newStoreHome._homeType == ECALENDARTYPE:
-            sharerHomeCollection = yield sharer.calendarHome(request)
+            ownerHomeCollection = yield owner.calendarHome(request)
         elif self._newStoreHome._homeType == EADDRESSBOOKTYPE:
-            sharerHomeCollection = yield sharer.addressBookHome(request)
+            ownerHomeCollection = yield owner.addressBookHome(request)
 
-        sharerHomeChild = yield storeObject.ownerHome().childWithID(storeObject._resourceID)
-        if sharerHomeChild:
-            assert sharerHomeChild != storeObject
-            url = joinURL(sharerHomeCollection.url(), sharerHomeChild.name())
-            share = Share(shareeStoreObject=storeObject, sharerStoreObject=sharerHomeChild, url=url)
-        elif self._newStoreHome._homeType == EADDRESSBOOKTYPE:
-            for sharerHomeChild in (yield storeObject.ownerHome().children()):
-                if sharerHomeChild.owned():
-                    sharedGroup = yield sharerHomeChild.objectResourceWithID(storeObject._resourceID)
+        ownerHomeChild = yield storeObject.ownerHome().childWithID(storeObject._resourceID)
+        if ownerHomeChild:
+            assert ownerHomeChild != storeObject
+            url = joinURL(ownerHomeCollection.url(), ownerHomeChild.name())
+            share = Share(shareeStoreObject=storeObject, ownerStoreObject=ownerHomeChild, url=url)
+        else:
+            for ownerHomeChild in (yield storeObject.ownerHome().children()):
+                if ownerHomeChild.owned():
+                    sharedGroup = yield ownerHomeChild.objectResourceWithID(storeObject._resourceID)
                     if sharedGroup:
-                        url = joinURL(sharerHomeCollection.url(), sharerHomeChild.name(), sharedGroup.name())
-                        share = Share(shareeStoreObject=storeObject, sharerStoreObject=sharedGroup, url=url)
+                        url = joinURL(ownerHomeCollection.url(), ownerHomeChild.name(), sharedGroup.name())
+                        share = Share(shareeStoreObject=storeObject, ownerStoreObject=sharedGroup, url=url)
                         break
 
         returnValue(share)
@@ -1059,7 +1055,7 @@
     @inlineCallbacks
     def _shareForUID(self, shareUID, request):
 
-        child = yield self._newStoreHome.objectWithBindName(shareUID)
+        child = yield self._newStoreHome.objectWithShareUID(shareUID)
         if child:
             share = yield self._shareForStoreObject(child, request)
             if share and share.uid() == shareUID:
@@ -1087,9 +1083,9 @@
             share = oldShare
         else:
             sharedResource = yield request.locateResource(hostUrl)
-            shareeStoreObject = yield self._newStoreHome.objectWithBindName(inviteUID)
+            shareeStoreObject = yield self._newStoreHome.objectWithShareUID(inviteUID)
 
-            share = Share(shareeStoreObject=shareeStoreObject, sharerStoreObject=sharedResource._newStoreObject, url=hostUrl)
+            share = Share(shareeStoreObject=shareeStoreObject, ownerStoreObject=sharedResource._newStoreObject, url=hostUrl)
 
         response = yield self._acceptShare(request, not oldShare, share, displayname)
         returnValue(response)
@@ -1109,7 +1105,7 @@
                                                     status=_BIND_STATUS_ACCEPTED,
                                                     message=displayname)
 
-            share = Share(shareeStoreObject=shareeStoreObject, sharerStoreObject=sharedCollection._newStoreObject, url=hostUrl)
+            share = Share(shareeStoreObject=shareeStoreObject, ownerStoreObject=sharedCollection._newStoreObject, url=hostUrl)
 
         response = yield self._acceptShare(request, not oldShare, share, displayname)
         returnValue(response)
@@ -1151,13 +1147,13 @@
 
         elif sharedResource.isAddressBookCollection():
             shareeHomeResource = yield sharee.addressBookHome(request)
-            shareeAddressBookURL = joinURL(shareeHomeResource.url(), share.sharerUID())
+            shareeAddressBookURL = joinURL(shareeHomeResource.url(), share.ownerUID())
             shareeAddressBook = yield request.locateResource(shareeAddressBookURL)
             shareeAddressBook.setShare(share)
 
         elif sharedResource.isGroup():
             shareeHomeResource = yield sharee.addressBookHome(request)
-            shareeGroupURL = joinURL(shareeHomeResource.url(), share.sharerUID(), share.name())
+            shareeGroupURL = joinURL(shareeHomeResource.url(), share.ownerUID(), share.name())
             shareeGroup = yield request.locateResource(shareeGroupURL)
             shareeGroup.setShare(share)
 
@@ -1168,9 +1164,9 @@
         if sharedResource.isCalendarCollection():
             sharedAsURL = joinURL(self.url(), share.name())
         elif sharedResource.isAddressBookCollection():
-            sharedAsURL = joinURL(self.url(), share.sharerUID())
+            sharedAsURL = joinURL(self.url(), share.ownerUID())
         elif sharedResource.isGroup():
-            sharedAsURL = joinURL(self.url(), share.sharerUID(), share.name())
+            sharedAsURL = joinURL(self.url(), share.ownerUID(), share.name())
 
         # Return the URL of the shared collection
         returnValue(XMLResponse(
@@ -1230,9 +1226,9 @@
                 inbox.processFreeBusyCalendar(shareURL, False)
 
         if share.direct():
-            yield share._sharerStoreObject.unshareWith(share._shareeStoreObject.viewerHome())
+            yield share._ownerStoreObject.unshareWith(share._shareeStoreObject.viewerHome())
         else:
-            yield share._sharerStoreObject.updateShare(share._shareeStoreObject, status=_BIND_STATUS_DECLINED)
+            yield share._ownerStoreObject.updateShare(share._shareeStoreObject, status=_BIND_STATUS_DECLINED)
 
         returnValue(displayname)
 
@@ -1251,7 +1247,7 @@
         """
         Accept or decline an invite to a shared collection.
         """
-        # Change state in sharer invite
+        # Change state in owner invite
         ownerPrincipal = (yield self.ownerPrincipal(request))
         ownerPrincipalUID = ownerPrincipal.principalUID()
         sharedResource = (yield request.locateResource(hostUrl))
@@ -1272,9 +1268,9 @@
     @inlineCallbacks
     def sendReply(self, request, shareePrincipal, sharedResource, state, hostUrl, replytoUID, displayname=None):
 
-        # Locate notifications collection for sharer
-        sharer = (yield sharedResource.ownerPrincipal(request))
-        notificationResource = (yield request.locateResource(sharer.notificationURL()))
+        # Locate notifications collection for owner
+        owner = (yield sharedResource.ownerPrincipal(request))
+        notificationResource = (yield request.locateResource(owner.notificationURL()))
         notifications = notificationResource._newStoreNotifications
 
         # Generate invite XML
@@ -1350,21 +1346,21 @@
 
 class Share(object):
 
-    def __init__(self, sharerStoreObject, shareeStoreObject, url):
+    def __init__(self, ownerStoreObject, shareeStoreObject, url):
         self._shareeStoreObject = shareeStoreObject
-        self._sharerStoreObject = sharerStoreObject
-        self._sharerResourceURL = url
+        self._ownerStoreObject = ownerStoreObject
+        self._ownerResourceURL = url
 
 
     @classmethod
-    def directUID(cls, shareeHome, sharerHomeChild):
-        return "Direct-%s-%s" % (shareeHome._resourceID, sharerHomeChild._resourceID,)
+    def directUID(cls, shareeHome, ownerHomeChild):
+        return "Direct-%s-%s" % (shareeHome._resourceID, ownerHomeChild._resourceID,)
 
 
     def uid(self):
         # Move to CommonHomeChild shareUID?
         if self._shareeStoreObject.shareMode() == _BIND_MODE_DIRECT:
-            return self.directUID(shareeHome=self._shareeStoreObject.viewerHome(), sharerHomeChild=self._sharerStoreObject,)
+            return self.directUID(shareeHome=self._shareeStoreObject.viewerHome(), ownerHomeChild=self._ownerStoreObject,)
         else:
             return self._shareeStoreObject.shareUID()
 
@@ -1374,7 +1370,7 @@
 
 
     def url(self):
-        return self._sharerResourceURL
+        return self._ownerResourceURL
 
 
     def name(self):
@@ -1389,5 +1385,5 @@
         return self._shareeStoreObject.viewerHome().uid()
 
 
-    def sharerUID(self):
+    def ownerUID(self):
         return self._shareeStoreObject.ownerHome().uid()

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py	2013-02-15 22:01:47 UTC (rev 10744)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py	2013-02-15 22:45:11 UTC (rev 10745)
@@ -73,7 +73,7 @@
 from twext.web2.filter.location import addLocation
 
 from txdav.carddav.iaddressbookstore import GroupWithUnsharedAddressNotAllowedError, \
-    DeleteOfGroupForSharedAddressBookNotAllowedError
+    SharedGroupDeleteNotAllowedError
 
 """
 Wrappers to translate between the APIs in L{txdav.caldav.icalendarstore} and
@@ -3010,7 +3010,7 @@
         try:
             returnValue((yield super(AddressBookObjectResource, self).http_DELETE(request)))
 
-        except DeleteOfGroupForSharedAddressBookNotAllowedError:
+        except SharedGroupDeleteNotAllowedError:
             raise HTTPError(StatusResponse(
                 FORBIDDEN,
                 "Sharee cannot delete group vcard shadowing shared address book",)

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/caldav/datastore/sql.py	2013-02-15 22:01:47 UTC (rev 10744)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/caldav/datastore/sql.py	2013-02-15 22:45:11 UTC (rev 10745)
@@ -908,13 +908,6 @@
         )
 
 
-    def unshare(self):
-        """
-        Unshares a collection, regardless of which "direction" it was shared.
-        """
-        return super(Calendar, self).unshare(ECALENDARTYPE)
-
-
     def creatingResourceCheckAttachments(self, component):
         """
         When component data is created or changed we need to look for changes related to managed attachments.

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2013-02-15 22:01:47 UTC (rev 10744)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2013-02-15 22:45:11 UTC (rev 10745)
@@ -44,7 +44,7 @@
 from txdav.carddav.datastore.util import validateAddressBookComponent
 from txdav.carddav.iaddressbookstore import IAddressBookHome, IAddressBook, \
     IAddressBookObject, GroupWithUnsharedAddressNotAllowedError, \
-    DeleteOfGroupForSharedAddressBookNotAllowedError
+    SharedGroupDeleteNotAllowedError
 from txdav.common.datastore.sql import CommonHome, CommonHomeChild, \
     CommonObjectResource, EADDRESSBOOKTYPE, SharingMixIn
 from txdav.common.datastore.sql_legacy import PostgresLegacyABIndexEmulator
@@ -103,7 +103,7 @@
     removeAddressBookWithName = CommonHome.removeChildWithName
 
 
-    def objectWithBindName(self, name):
+    def objectWithShareUID(self, shareUID):
         """
         Retrieve the child with the given C{name} contained in this
         home.
@@ -111,7 +111,7 @@
         @param name: a string.
         @return: an L{ICalendar} or C{None} if no such child exists.
         """
-        return self._childClass.objectWithBindName(self, name)
+        return self._childClass.objectWithShareUID(self, shareUID)
 
 
     @inlineCallbacks
@@ -259,18 +259,12 @@
     def create(cls, home, name):
 
         if name != home.addressbookName():
+            assert False, "create(cls=%s home=%s, name=%s): should not be here." % (cls, home, name,)
             raise NotImplementedError()
 
         returnValue((yield super(AddressBook, cls).create(home, name)))
 
 
-    def unshare(self):
-        """
-        Unshares a collection, regardless of which "direction" it was shared.
-        """
-        return super(AddressBook, self).unshare(EADDRESSBOOKTYPE)
-
-
     @inlineCallbacks
     def listObjectResources(self):
 
@@ -466,8 +460,8 @@
         groupBindRows = yield AddressBookObject._childrenAndMetadataForHomeID.on(home._txn, homeID=home._resourceID)
         for groupBindRow in groupBindRows:
             bindMode, homeID, resourceID, bindName, bindStatus, bindMessage = groupBindRow[:6] #@UnusedVariable        
-            ownerAddressBookIDRows = yield AddressBookObject._parentIDForObjectID.on(home._txn, objectID=resourceID)
-            ownerHomeID = yield cls.ownerHomeID(home._txn, ownerAddressBookIDRows[0][0])
+            ownerAddressBookID = yield AddressBookObject.ownerAddressBookID(home._txn, resourceID)
+            ownerHomeID = yield cls.ownerHomeID(home._txn, ownerAddressBookID)
             if ownerHomeID not in ownerHomeIDToDataRowMap:
                 groupBindRow[0] = _BIND_MODE_WRITE
                 groupBindRow[3] = None # bindName
@@ -607,7 +601,7 @@
 
     @classmethod
     @inlineCallbacks
-    def objectWithBindName(cls, home, bindName):
+    def objectWithShareUID(cls, home, shareUID):
         """
         Retrieve the child with the given C{name} contained in the given
         C{home}.
@@ -619,7 +613,7 @@
         @return: an L{CommonHomeChild} or C{None} if no such child
             exists.
         """
-        bindRows = yield cls._acceptedBindForNameAndHomeID.on(home._txn, name=bindName, homeID=home._resourceID)
+        bindRows = yield cls._acceptedBindForNameAndHomeID.on(home._txn, name=shareUID, homeID=home._resourceID)
         if bindRows:
             bindMode, homeID, resourceID, bindName, bindStatus, bindMessage = bindRows[0] #@UnusedVariable
             # use childWithName, since it is cached by querycacher
@@ -630,13 +624,13 @@
             returnValue((yield home.childWithName(ownerAddressBook.shareeABName())))
 
 
-        groupBindRows = yield AddressBookObject._acceptedBindForNameAndHomeID.on(home._txn, name=bindName, homeID=home._resourceID)
+        groupBindRows = yield AddressBookObject._acceptedBindForNameAndHomeID.on(home._txn, name=shareUID, homeID=home._resourceID)
         if groupBindRows:
             bindMode, homeID, resourceID, bindName, bindStatus, bindMessage = groupBindRows[0] #@UnusedVariable
-            ownerAddressBookIDRows = yield AddressBookObject._parentIDForObjectID.on(home._txn, objectID=resourceID)
+            ownerAddressBookID = yield AddressBookObject.ownerAddressBookID(home._txn, resourceID)
             # use childWithName, since it is cached by querycacher
             # addressbook = yield cls.objectWithID(home, ownerAddressBookIDRows[0][0])
-            ownerHomeID = yield cls.ownerHomeID(home._txn, ownerAddressBookIDRows[0][0])
+            ownerHomeID = yield cls.ownerHomeID(home._txn, ownerAddressBookID)
             ownerHome = yield home._txn.homeWithResourceID(home._homeType, ownerHomeID)
             ownerAddressBook = yield ownerHome.addressbook()
             addressbook = yield home.childWithName(ownerAddressBook.shareeABName())
@@ -849,7 +843,7 @@
 
             if readonlyGroupIDs and readwriteGroupIDs:
                 # expand read-write groups and remove any subgroups from read-only group list
-                allWriteableIDs = yield self._addressbook._objectIDsInExpandedGroupIDs(self._txn, readwriteGroupIDs)
+                allWriteableIDs = yield self._objectIDsInExpandedGroupIDs(self._txn, readwriteGroupIDs)
                 adjustedReadOnlyGroupIDs = set(readonlyGroupIDs) - set(allWriteableIDs)
                 adjustedReadWriteGroupIDs = set(readwriteGroupIDs) | (set(readonlyGroupIDs) - adjustedReadOnlyGroupIDs)
             else:
@@ -1064,28 +1058,29 @@
         sharedAddressBook = yield shareeHome.addressbookWithName(self.shareeABName())
         if sharedAddressBook:
 
-            sharedRemoval = False
-            if sharedAddressBook.fullyShared():
-                acceptedGroupBinds = len((yield AddressBookObject._acceptedBindWithHomeIDAndAddressBookID.on(
-                        self._txn, homeID=sharedAddressBook._home._resourceID, addressbookID=sharedAddressBook._resourceID
-                )))
-                sharedRemoval = acceptedGroupBinds == 0
-                if sharedRemoval:
-                    sharedAddressBook._deletedSyncToken(sharedRemoval=True)
-                    shareeHome._children.pop(resourceName, None)
+            acceptedBinds = 1 if sharedAddressBook.fullyShared() else 0
+            acceptedBinds += len((yield AddressBookObject._acceptedBindWithHomeIDAndAddressBookID.on(
+                    self._txn, homeID=sharedAddressBook._home._resourceID, addressbookID=sharedAddressBook._resourceID
+            )))
+            if acceptedBinds == 1:
+                resourceName = self.shareeABName()
+                sharedAddressBook._deletedSyncToken(sharedRemoval=True)
+                shareeHome._children.pop(self.shareeABName(), None)
 
+            queryCacher = self._txn._queryCacher
+            if queryCacher:
+                cacheKey = queryCacher.keyForObjectWithName(shareeHome._resourceID, self.shareeABName())
+                queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+
+            deleted = yield self._deleteBindWithResourceIDAndHomeID.on(self._txn, resourceID=self._resourceID,
+                 homeID=shareeHome._resourceID)
+
             # Must send notification to ensure cache invalidation occurs
             yield self.notifyChanged()
 
-        queryCacher = self._txn._queryCacher
-        if queryCacher:
-            cacheKey = queryCacher.keyForObjectWithName(shareeHome._resourceID, self.shareeABName())
-            queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+        returnValue(resourceName)
 
-        yield self._deleteBindWithResourceIDAndHomeID.on(self._txn, resourceID=self._resourceID,
-             homeID=shareeHome._resourceID)
 
-        returnValue(resourceName)
 
 
 class AddressBookObject(CommonObjectResource, SharingMixIn):
@@ -1146,11 +1141,12 @@
                         cacheKey = queryCacher.keyForObjectWithName(shareeAddressBook._home._resourceID, shareeAddressBook._name)
                         yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
         else:
-            # sharee cannot delete group representing shared address book
+            # cannot delete share for now
+            # TODO: convert to unshare
             if self._resourceID == self._addressbook._resourceID:
-                raise DeleteOfGroupForSharedAddressBookNotAllowedError
+                raise SharedGroupDeleteNotAllowedError
             elif self._bindName:
-                raise DeleteOfGroupForSharedAddressBookNotAllowedError
+                raise SharedGroupDeleteNotAllowedError
 
         aboMembers = schema.ABO_MEMBERS
         aboForeignMembers = schema.ABO_FOREIGN_MEMBERS
@@ -1893,16 +1889,42 @@
 
 
     @classproperty
-    def _parentIDForObjectID(cls): #@NoSelf
+    def _addressbookIDForResourceID(cls): #@NoSelf
         #TODO: This query could be part of previously called query using object schema join
         obj = cls._objectSchema
         return Select([obj.PARENT_RESOURCE_ID],
                       From=obj,
-                      Where=obj.RESOURCE_ID == Parameter("objectID")
+                      Where=obj.RESOURCE_ID == Parameter("resourceID")
                     )
 
 
+    @classmethod
     @inlineCallbacks
+    def ownerAddressBookID(cls, txn, resourceID):
+        ownerAddressBookIDRows = yield cls._addressbookIDForResourceID.on(txn, resourceID=resourceID)
+        returnValue(ownerAddressBookIDRows[0][0])
+
+
+    @inlineCallbacks
+    def unshare(self):
+        """
+        Unshares a group, regardless of which "direction" it was shared.
+        """
+        if self.owned():
+            # This collection may be shared to others
+            for sharedToHome in [x.viewerHome() for x in (yield self.asShared())]:
+                yield self.unshareWith(sharedToHome)
+        else:
+            # This collection is shared to me
+            ownerHomeID = yield self.ownerHomeID(self._txn, self._resourceID)
+            ownerHome = yield self._txn.homeWithResourceID(self._home._homeType,
+                ownerHomeID)
+            ownerAddressBook = yield ownerHome.addressbook()
+            ownerGroup = yield ownerAddressBook.objectResourceWithID(self._resourceID)
+            yield ownerGroup.unshareWith(self._home)
+
+
+    @inlineCallbacks
     def unshareWith(self, shareeHome):
         """
         Remove the shared version of this (owned) L{CommonHomeChild} from the
@@ -1919,29 +1941,27 @@
         resourceName = None
         sharedAddressBook = yield shareeHome.addressbookWithName(self._addressbook.shareeABName())
         if sharedAddressBook:
-            returnValue(None)
 
-            sharedRemoval = False
-            if not sharedAddressBook.fullyShared():
-                acceptedGroupBinds = len((yield AddressBookObject._acceptedBindWithHomeIDAndAddressBookID.on(
-                        self._txn, homeID=sharedAddressBook._home._resourceID, addressbookID=sharedAddressBook._resourceID
-                )))
-                sharedRemoval = acceptedGroupBinds == 1
-                if sharedRemoval:
-                    sharedAddressBook._deletedSyncToken(sharedRemoval=True)
-                    shareeHome._children.pop(resourceName, None)
+            acceptedBinds = 1 if sharedAddressBook.fullyShared() else 0
+            acceptedBinds += len((yield AddressBookObject._acceptedBindWithHomeIDAndAddressBookID.on(
+                    self._txn, homeID=sharedAddressBook._home._resourceID, addressbookID=sharedAddressBook._resourceID
+            )))
 
-                # Must send notification to ensure cache invalidation occurs
-                yield self._addressbook.notifyChanged()
+            if acceptedBinds == 1:
+                resourceName = self._addressbook.shareeABName()
+                sharedAddressBook._deletedSyncToken(sharedRemoval=True)
+                shareeHome._children.pop(resourceName, None)
 
-        queryCacher = self._txn._queryCacher
-        if queryCacher:
-            cacheKey = queryCacher.keyForObjectWithName(shareeHome._resourceID, self._addressbook.shareeABName())
-            queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+            queryCacher = self._txn._queryCacher
+            if queryCacher:
+                cacheKey = queryCacher.keyForObjectWithName(shareeHome._resourceID, self._addressbook.shareeABName())
+                queryCacher.invalidateAfterCommit(self._txn, cacheKey)
 
-        yield self._deleteBindWithResourceIDAndHomeID.on(self._txn, resourceID=self._resourceID,
-             homeID=shareeHome._resourceID)
+            deleted = yield self._deleteBindWithResourceIDAndHomeID.on(self._txn, resourceID=self._resourceID,
+                 homeID=shareeHome._resourceID)
 
+            # Must send notification to ensure cache invalidation occurs
+            yield self._addressbook.notifyChanged()
 
         returnValue(resourceName)
 
@@ -2037,7 +2057,7 @@
         bind = cls._bindSchema
         abo = cls._objectSchema
         return Select(
-                  cls._bindColumns,
+                  cls._bindColumns(),
                   From=bind.join(abo),
                   Where=(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
                         .And(bind.RESOURCE_ID == abo.RESOURCE_ID)
@@ -2049,7 +2069,7 @@
         bind = cls._bindSchema
         abo = cls._objectSchema
         return Select(
-                  cls._bindColumns,
+                  cls._bindColumns(),
                   From=bind.join(abo),
                   Where=(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
                         .And(bind.RESOURCE_ID == abo.RESOURCE_ID)
@@ -2062,7 +2082,7 @@
         bind = cls._bindSchema
         abo = cls._objectSchema
         return Select(
-                  cls._bindColumns,
+                  cls._bindColumns(),
                   From=bind.join(abo),
                   Where=(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
                         .And(bind.RESOURCE_ID == abo.RESOURCE_ID)
@@ -2076,7 +2096,7 @@
         bind = cls._bindSchema
         abo = cls._objectSchema
         return Select(
-                  cls._bindColumns,
+                  cls._bindColumns(),
                   From=bind.join(abo),
                   Where=(bind.BIND_STATUS == _BIND_STATUS_INVITED)
                         .And(bind.RESOURCE_ID == abo.RESOURCE_ID)
@@ -2090,11 +2110,12 @@
         bind = cls._bindSchema
         abo = cls._objectSchema
         return Select(
-                  cls._bindColumns,
+                  cls._bindColumns(),
                   From=bind.join(abo),
                   Where=(bind.RESOURCE_ID == abo.RESOURCE_ID)
                         .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
                         .And(abo.ADDRESSBOOK_RESOURCE_ID == Parameter("addressbookID"))
         )
 
+
 AddressBook._objectResourceClass = AddressBookObject

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/common.py	2013-02-15 22:01:47 UTC (rev 10744)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/common.py	2013-02-15 22:45:11 UTC (rev 10745)
@@ -48,7 +48,7 @@
 
 homeRoot = storePath.child("ho").child("me").child("home1")
 
-adbk1Root = homeRoot.child("addressbook_1")
+adbk1Root = homeRoot.child("addressbook")
 
 addressbook1_objectNames = [
     "1.vcf",
@@ -58,9 +58,7 @@
 
 
 home1_addressbookNames = [
-    "addressbook_1",
-    "addressbook_2",
-    "addressbook_empty",
+    "addressbook",
 ]
 
 
@@ -114,26 +112,22 @@
     )
     requirements = {
         "home1": {
-            "addressbook_1": {
+            "addressbook": {
                 "1.vcf": adbk1Root.child("1.vcf").getContent(),
                 "2.vcf": adbk1Root.child("2.vcf").getContent(),
                 "3.vcf": adbk1Root.child("3.vcf").getContent()
             },
-            "addressbook_2": {},
-            "addressbook_empty": {},
             "not_a_addressbook": None
         },
         "not_a_home": None
     }
     md5s = {
         "home1": {
-            "addressbook_1": {
+            "addressbook": {
                 "1.vcf": md5Values[0],
                 "2.vcf": md5Values[1],
                 "3.vcf": md5Values[2],
             },
-            "addressbook_2": {},
-            "addressbook_empty": {},
             "not_a_addressbook": None
         },
         "not_a_home": None
@@ -161,17 +155,17 @@
     @inlineCallbacks
     def addressbookUnderTest(self):
         """
-        Get the addressbook detailed by C{requirements['home1']['addressbook_1']}.
+        Get the addressbook detailed by C{requirements['home1']['addressbook']}.
         """
         returnValue((yield (yield self.homeUnderTest())
-            .addressbookWithName("addressbook_1")))
+            .addressbookWithName("addressbook")))
 
 
     @inlineCallbacks
     def addressbookObjectUnderTest(self):
         """
         Get the addressbook detailed by
-        C{requirements['home1']['addressbook_1']['1.vcf']}.
+        C{requirements['home1']['addressbook']['1.vcf']}.
         """
         returnValue((yield (yield self.addressbookUnderTest())
                     .addressbookObjectWithName("1.vcf")))
@@ -228,9 +222,9 @@
     def test_notifierID(self):
         home = yield self.homeUnderTest()
         self.assertEquals(home.notifierID(), "CardDAV|home1")
-        addressbook = yield home.addressbookWithName("addressbook_1")
+        addressbook = yield home.addressbookWithName("addressbook")
         self.assertEquals(addressbook.notifierID(), "CardDAV|home1")
-        self.assertEquals(addressbook.notifierID(label="collection"), "CardDAV|home1/addressbook_1")
+        self.assertEquals(addressbook.notifierID(label="collection"), "CardDAV|home1/addressbook")
 
 
     @inlineCallbacks
@@ -277,13 +271,13 @@
         L{IAddressBook.rename} changes the name of the L{IAddressBook}.
         """
         home = yield self.homeUnderTest()
-        addressbook = yield home.addressbookWithName("addressbook_1")
+        addressbook = yield home.addressbookWithName("addressbook")
         yield addressbook.rename("some_other_name")
         @inlineCallbacks
         def positiveAssertions():
             self.assertEquals(addressbook.name(), "some_other_name")
             self.assertEquals(addressbook, (yield home.addressbookWithName("some_other_name")))
-            self.assertEquals(None, (yield home.addressbookWithName("addressbook_1")))
+            self.assertEquals(None, (yield home.addressbookWithName("addressbook")))
         yield positiveAssertions()
         yield self.commit()
         home = yield self.homeUnderTest()
@@ -380,11 +374,7 @@
             self.notifierFactory.history,
             [
                 ("update", "CardDAV|home1"),
-                ("update", "CardDAV|home1/addressbook_1"),
-                ("update", "CardDAV|home1"),
-                ("update", "CardDAV|home1/addressbook_2"),
-                ("update", "CardDAV|home1"),
-                ("update", "CardDAV|home1/addressbook_empty")
+                ("update", "CardDAV|home1/addressbook"),
             ]
         )
 
@@ -516,7 +506,7 @@
             self.notifierFactory.history,
             [
                 ("update", "CardDAV|home1"),
-                ("update", "CardDAV|home1/addressbook_1"),
+                ("update", "CardDAV|home1/addressbook"),
             ]
         )
 
@@ -538,7 +528,7 @@
         """
         L{AddressBook.name} reflects the name of the addressbook.
         """
-        self.assertEquals((yield self.addressbookUnderTest()).name(), "addressbook_1")
+        self.assertEquals((yield self.addressbookUnderTest()).name(), "addressbook")
 
 
     @inlineCallbacks
@@ -822,7 +812,7 @@
             self.notifierFactory.history,
             [
                 ("update", "CardDAV|home1"),
-                ("update", "CardDAV|home1/addressbook_1"),
+                ("update", "CardDAV|home1/addressbook"),
             ]
         )
 
@@ -929,7 +919,7 @@
         home2 = yield self.transactionUnderTest().addressbookHomeWithUID(
             "home2", create=True
         )
-        self.assertIdentical((yield home2.addressbookWithName("addressbook_1")), None)
+        self.assertIdentical((yield home2.addressbookWithName("addressbook")), None)
 
 
     @inlineCallbacks
@@ -941,11 +931,11 @@
         home1 = yield self.homeUnderTest()
         home2 = yield self.transactionUnderTest().addressbookHomeWithUID(
             "home2", create=True)
-        addressbook1 = yield home1.addressbookWithName("addressbook_1")
+        addressbook1 = yield home1.addressbookWithName("addressbook")
         addressbook2 = yield home2.addressbookWithName("addressbook")
         objects = list((yield (yield home2.addressbookWithName("addressbook")).addressbookObjects()))
         self.assertEquals(objects, [])
-        for resourceName in self.requirements['home1']['addressbook_1'].keys():
+        for resourceName in self.requirements['home1']['addressbook'].keys():
             obj = yield addressbook1.addressbookObjectWithName(resourceName)
             self.assertIdentical(
                 (yield addressbook2.addressbookObjectWithName(resourceName)), None)

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_file.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_file.py	2013-02-15 22:01:47 UTC (rev 10744)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_file.py	2013-02-15 22:45:11 UTC (rev 10745)
@@ -79,7 +79,7 @@
 @inlineCallbacks
 def setUpAddressBook1(test):
     yield setUpHome1(test)
-    test.addressbook1 = yield test.home1.addressbookWithName("addressbook_1")
+    test.addressbook1 = yield test.home1.addressbookWithName("addressbook")
     assert test.addressbook1 is not None, "No addressbook?"
 
 
@@ -305,7 +305,7 @@
         """
         self.txn = self.addressbookStore.newTransaction(self.id())
         self.home1 = yield self.txn.addressbookHomeWithUID("home1")
-        self.addressbook1 = yield self.home1.addressbookWithName("addressbook_1")
+        self.addressbook1 = yield self.home1.addressbookWithName("addressbook")
 
 
     @inlineCallbacks

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/iaddressbookstore.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/iaddressbookstore.py	2013-02-15 22:01:47 UTC (rev 10744)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/iaddressbookstore.py	2013-02-15 22:45:11 UTC (rev 10745)
@@ -27,7 +27,7 @@
 __all__ = [
     # Classes
     "GroupWithUnsharedAddressNotAllowedError",
-    "DeleteOfGroupForSharedAddressBookNotAllowedError",
+    "SharedGroupDeleteNotAllowedError",
     "IAddressBookTransaction",
     "IAddressBookHome",
     "IAddressBook",
@@ -38,11 +38,14 @@
     """
     Sharee cannot add or modify group vcard such that result contains addresses of unshared vcards.
     """
-class DeleteOfGroupForSharedAddressBookNotAllowedError(CommonStoreError):
+
+
+class SharedGroupDeleteNotAllowedError(CommonStoreError):
     """
     Sharee cannot delete group vcard shadowing shared address book
     """
 
+
 class IAddressBookTransaction(ICommonTransaction):
     """
     Transaction interface that addressbook stores must provide.
@@ -60,11 +63,11 @@
         """
 
 
-
 #
 # Interfaces
 #
 
+
 class IAddressBookHome(INotifier, IDataStoreObject):
     """
     AddressBook home

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py	2013-02-15 22:01:47 UTC (rev 10744)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py	2013-02-15 22:45:11 UTC (rev 10745)
@@ -1498,7 +1498,7 @@
         return self._childClass.objectWithName(self, name)
 
 
-    def objectWithBindName(self, name):
+    def objectWithShareUID(self, shareUID):
         """
         Retrieve the child with the given bind identifier contained in this
         home.
@@ -1506,7 +1506,7 @@
         @param name: a string.
         @return: an L{ICalendar} or C{None} if no such child exists.
         """
-        return self._childClass.objectWithName(self, name)
+        return self._childClass.objectWithName(self, shareUID)
 
 
     @memoizedKey("resourceID", "_children")
@@ -2303,24 +2303,22 @@
                      bind.MESSAGE: Parameter("message")})
 
 
-    @classproperty
+    @classmethod
     def _bindColumns(cls): #@NoSelf
         bind = cls._bindSchema
-        return [
-                bind.BIND_MODE,
+        return (bind.BIND_MODE,
                 bind.HOME_RESOURCE_ID,
                 bind.RESOURCE_ID,
                 bind.RESOURCE_NAME,
                 bind.BIND_STATUS,
-                bind.MESSAGE,
-                ]
+                bind.MESSAGE,)
 
 
     @classmethod
     def _bindFor(cls, condition): #@NoSelf
         bind = cls._bindSchema
         return Select(
-                  cls._bindColumns,
+                  cls._bindColumns(),
                   From=bind,
                   Where=condition
         )
@@ -2588,7 +2586,26 @@
 
         returnValue(resourceName)
 
+
     @inlineCallbacks
+    def unshare(self):
+        """
+        Unshares a collection, regardless of which "direction" it was shared.
+        """
+        if self.owned():
+            # This collection may be shared to others
+            for sharedToHome in [x.viewerHome() for x in (yield self.asShared())]:
+                yield self.unshareWith(sharedToHome)
+        else:
+            # This collection is shared to me
+            ownerHomeID = yield self.ownerHomeID(self._txn, self._resourceID)
+            ownerHome = yield self._txn.homeWithResourceID(self._home._homeType,
+                ownerHomeID)
+            ownerHomeChild = yield ownerHome.childWithID(self._resourceID)
+            yield ownerHomeChild.unshareWith(self._home)
+
+
+    @inlineCallbacks
     def asShared(self):
         """
         Retrieve all the versions of this L{CommonHomeChild} as it is shared to
@@ -2803,7 +2820,7 @@
         bind = cls._bindSchema
         child = cls._homeChildSchema
         childMetaData = cls._homeChildMetaDataSchema
-        columns = cls._bindColumns + list(cls.metadataColumns())
+        columns = cls._bindColumns() + cls.metadataColumns()
         return Select(columns,
                      From=child.join(
                          bind, child.RESOURCE_ID == bind.RESOURCE_ID,
@@ -2814,26 +2831,6 @@
                            ).And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED))
 
 
-    @inlineCallbacks
-    def unshare(self, homeType):
-        """
-        Unshares a collection, regardless of which "direction" it was shared.
-
-        @param homeType: a valid store type (ECALENDARTYPE or EADDRESSBOOKTYPE)
-        """
-        if self.owned():
-            # This collection may be shared to others
-            for sharedToHome in [x.viewerHome() for x in (yield self.asShared())]:
-                (yield self.unshareWith(sharedToHome))
-        else:
-            # This collection is shared to me
-            sharerHomeID = (yield self.sharerHomeID())
-            sharerHome = (yield self._txn.homeWithResourceID(homeType,
-                sharerHomeID))
-            sharerCollection = (yield sharerHome.childWithID(self._resourceID))
-            (yield sharerCollection.unshareWith(self._home))
-
-
     @classproperty
     def _revisionsForHomeID(cls): #@NoSelf
             bind = cls._bindSchema
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130215/3bd26a2d/attachment-0001.html>


More information about the calendarserver-changes mailing list