[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