[CalendarServer-changes] [9514] CalendarServer/branches/users/gaya/inviteclean/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Wed Aug 1 17:40:53 PDT 2012
Revision: 9514
http://trac.macosforge.org/projects/calendarserver/changeset/9514
Author: gaya at apple.com
Date: 2012-08-01 17:40:53 -0700 (Wed, 01 Aug 2012)
Log Message:
-----------
Use new Share class instead of SharedCollectionRecord. Populate allShares using new db APIs.
Modified Paths:
--------------
CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/directory/util.py
CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/resource.py
CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/sharedcollection.py
CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/sharing.py
Modified: CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/directory/util.py
===================================================================
--- CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/directory/util.py 2012-08-01 20:15:25 UTC (rev 9513)
+++ CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/directory/util.py 2012-08-02 00:40:53 UTC (rev 9514)
@@ -55,6 +55,8 @@
return value
+TRANSACTION_KEY = '_newStoreTransaction'
+
def transactionFromRequest(request, newStore):
"""
Return the associated transaction from the given HTTP request, creating a
@@ -76,7 +78,6 @@
@rtype: L{ITransaction} (and possibly L{ICalendarTransaction} and
L{IAddressBookTransaction} as well.
"""
- TRANSACTION_KEY = '_newStoreTransaction'
transaction = getattr(request, TRANSACTION_KEY, None)
if transaction is None:
transaction = newStore.newTransaction(repr(request))
Modified: CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/resource.py 2012-08-01 20:15:25 UTC (rev 9513)
+++ CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/resource.py 2012-08-02 00:40:53 UTC (rev 9514)
@@ -706,7 +706,7 @@
isvirt = self.isVirtualShare()
if isvirt:
- returnValue(customxml.SharedURL(element.HRef.fromString(self._share.hosturl)))
+ returnValue(customxml.SharedURL(element.HRef.fromString(self._share.sharedResourceURL())))
else:
returnValue(None)
@@ -934,7 +934,7 @@
isVirt = self.isVirtualShare()
if isVirt:
- parent = (yield self.locateParent(request, self._share.hosturl))
+ parent = (yield self.locateParent(request, self._share.sharedResourceURL()))
else:
parent = (yield self.locateParent(request, request.urlForResource(self)))
if parent and isinstance(parent, CalDAVResource):
@@ -950,7 +950,7 @@
"""
isVirt = self.isVirtualShare()
if isVirt:
- parent = (yield self.locateParent(request, self._share.hosturl))
+ parent = (yield self.locateParent(request, self._share.sharedResourceURL()))
else:
parent = (yield self.locateParent(request, request.urlForResource(self)))
if parent and isinstance(parent, CalDAVResource):
@@ -1366,14 +1366,14 @@
isvirt = self.isVirtualShare()
if isvirt:
# A virtual share's quota root is the resource owner's root
- sharedParent = (yield request.locateResource(parentForURL(self._share.hosturl)))
+ sharedParent = (yield request.locateResource(parentForURL(self._share.sharedResourceURL())))
else:
parent = (yield self.locateParent(request, request.urlForResource(self)))
if isCalendarCollectionResource(parent) or isAddressBookCollectionResource(parent):
isvirt = parent.isVirtualShare()
if isvirt:
# A virtual share's quota root is the resource owner's root
- sharedParent = (yield request.locateResource(parentForURL(parent._share.hosturl)))
+ sharedParent = (yield request.locateResource(parentForURL(parent._share.sharedResourceURL())))
if sharedParent:
result = (yield sharedParent.quotaRootResource(request))
Modified: CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/sharedcollection.py
===================================================================
--- CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/sharedcollection.py 2012-08-01 20:15:25 UTC (rev 9513)
+++ CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/sharedcollection.py 2012-08-02 00:40:53 UTC (rev 9514)
@@ -37,7 +37,7 @@
def __init__(self, parent, share):
self.share = share
- super(SharedCollectionResource, self).__init__(parent, self.share.hosturl)
+ super(SharedCollectionResource, self).__init__(parent, self.share.sharedResourceURL())
@inlineCallbacks
def linkedResource(self, request):
@@ -46,13 +46,13 @@
"""
if not hasattr(self, "_linkedResource"):
- self._linkedResource = (yield request.locateResource(self.share.hosturl))
+ self._linkedResource = (yield request.locateResource(self.share.sharedResourceURL()))
if self._linkedResource is not None:
# FIXME: this is awkward - because we are "mutating" this object into a virtual share
# we must not cache the resource at this URL, otherwise an access of the owner's resource
# will return the same virtually shared one which would be wrong.
- request._forgetResource(self._linkedResource, self.share.hosturl)
+ request._forgetResource(self._linkedResource, self.share.sharedResourceURL())
ownerPrincipal = (yield self.parent.ownerPrincipal(request))
self._linkedResource.setVirtualShare(ownerPrincipal, self.share)
Modified: CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/sharing.py 2012-08-01 20:15:25 UTC (rev 9513)
+++ CalendarServer/branches/users/gaya/inviteclean/twistedcaldav/sharing.py 2012-08-02 00:40:53 UTC (rev 9514)
@@ -52,12 +52,13 @@
import os
import types
+#FIXME: Get rid of this!
+#from txdav.common.datastore.sql import EADDRESSBOOKTYPE
+ECALENDARTYPE = 0
+EADDRESSBOOKTYPE = 1
+ENOTIFICATIONTYPE = 2
-# Types of sharing mode
-SHARETYPE_INVITE = "I" # Invite based sharing
-SHARETYPE_DIRECT = "D" # Direct linking based sharing
-
class SharedCollectionMixin(object):
@inlineCallbacks
@@ -92,7 +93,7 @@
# See if it is on the sharee calendar
if self.isVirtualShare():
- original = (yield request.locateResource(self._share.hosturl))
+ original = (yield request.locateResource(self._share.sharedResourceURL()))
yield original.validateInvites()
invitations = yield original._allInvitations()
@@ -300,8 +301,8 @@
wikiAccessMethod = kwargs.get("wikiAccessMethod", getWikiAccess)
# Direct shares use underlying privileges of shared collection
- if self._share.sharetype == SHARETYPE_DIRECT:
- original = (yield request.locateResource(self._share.hosturl))
+ if self._share.isDirect():
+ original = (yield request.locateResource(self._share.sharedResourceURL()))
owner = yield original.ownerPrincipal(request)
if owner.record.recordType == WikiDirectoryService.recordType_wikis:
# Access level comes from what the wiki has granted to the
@@ -324,7 +325,7 @@
# Get the invite for this sharee
invitation = yield self._invitationForUID(
- self._share.shareuid
+ self._share.uid()
)
if invitation is None:
returnValue(element.ACL())
@@ -502,7 +503,7 @@
acceptedHomeChildren = yield self._newStoreObject.asShared()
# remove direct shares (it might be OK not to remove these, that would be different from legacy code)
indirectAccceptedHomeChildren = [homeChild for homeChild in acceptedHomeChildren
- if homeChild.shareMode()!=_BIND_MODE_DIRECT]
+ if homeChild.shareMode() != _BIND_MODE_DIRECT]
invitedHomeChildren += indirectAccceptedHomeChildren
invitations = [Invitation(homeChild) for homeChild in invitedHomeChildren]
@@ -1088,11 +1089,69 @@
@inlineCallbacks
- def allShares(self):
- if not hasattr(self, "_allShares"):
- allShareRecords = yield self.sharesDB().allRecords()
- self._allShares = dict([(share.localname, share) for share in
- allShareRecords])
+ def allShares(self, refresh=False):
+
+ if refresh or not hasattr(self, "_allShares"):
+
+ shares = []
+ children = yield self._newStoreHome.children()
+ for shareeHomeChild in children:
+ if not shareeHomeChild.owned():
+
+ sharerHomeID = yield shareeHomeChild.sharerHomeID()
+ sharerHome = yield self._newStoreHome._txn.homeWithResourceID(self._newStoreHome._homeType, sharerHomeID)
+ sharerHomeChild = yield sharerHome.childWithID(shareeHomeChild._resourceID)
+
+ # get the shared object's URL
+ principal = self.principalForUID(sharerHomeChild._home.uid())
+
+ # FIXEME: Fake up a request that can be used to get the sharer home resource
+ class FakeRequest(object):pass
+ fakeRequest = FakeRequest()
+ from twistedcaldav.directory.util import TRANSACTION_KEY
+ setattr(fakeRequest, TRANSACTION_KEY, self._newStoreHome._txn)
+
+ if self._newStoreHome._homeType == ECALENDARTYPE:
+ sharerHomeCollection = yield principal.calendarHome(fakeRequest)
+ elif self._newStoreHome._homeType == EADDRESSBOOKTYPE:
+ sharerHomeCollection = yield principal.addressBookHome(fakeRequest)
+
+ sharedResourceURL = joinURL(sharerHomeCollection.url(), sharerHomeChild.name())
+
+
+ share = Share(shareeHomeChild=shareeHomeChild, sharerHomeChild=sharerHomeChild, sharedResourceURL=sharedResourceURL)
+ shares.append(share)
+
+ # DEBUG ONLY
+ shares.sort(key=lambda share:share.uid())
+
+ allRecords = yield self.sharesDB().allRecords()
+ allRecords.sort(key=lambda record:record.shareuid)
+
+ oTestStrings = []
+ for i in range(len(allRecords)):
+ record = allRecords[i]
+ testStr = "i=%s, shareuid=%s, sharetype=%s, hostulr=%s, locqlname=%s, summary=%s" % (i, record.shareuid, record.sharetype, record.hosturl, record.localname, record.summary, )
+ oTestStrings += [testStr,]
+
+ testStrings = []
+ for i in range(len(shares)):
+ share = shares[i]
+ testStr = "i=%s, shareuid=%s, sharetype=%s, hostulr=%s, locqlname=%s, summary=%s" % (i, share.uid(), "D" if share.isDirect() else "I", share.sharedResourceURL(), share.shareeResourceName(), share.summary(), )
+ testStrings += [testStr,]
+
+ if oTestStrings != testStrings:
+ print("MISMATCH old: %s" % oTestStrings)
+ print("MISMATCH new: %s" % testStrings)
+ assert False
+
+
+ self._allShares = dict([(share.shareeResourceName(), share) for share in shares])
+
+ print ("allShares: GENERATED %d records, refresh=%s" % (len(self._allShares), refresh))
+ else:
+ print ("allShares: RETURNING %d records" % (len(self._allShares),))
+
returnValue(self._allShares)
@@ -1100,45 +1159,73 @@
def allShareNames(self):
allShares = yield self.allShares()
returnValue(tuple(allShares.keys()))
+
+ @inlineCallbacks
+ def _shareForUID(self, shareUID, refresh=False):
+
+ allShares = yield self.allShares(refresh)
+ for share in allShares.values():
+ if share.uid() == shareUID:
+ returnValue(share)
+ returnValue(None)
+ @inlineCallbacks
+ def _removeShareForUID(self, shareUID):
+ yield self.sharesDB().removeRecordForShareUID(shareUID)
@inlineCallbacks
+ def _addOrUpdateRecord(self, shareRecord):
+ yield self.sharesDB().addOrUpdateRecord(shareRecord)
+
+
+
+ @inlineCallbacks
def acceptInviteShare(self, request, hostUrl, inviteUID, displayname=None):
# Check for old share
- oldShare = yield self.sharesDB().recordForShareUID(inviteUID)
+ oldShare = yield self._shareForUID(inviteUID)
# Send the invite reply then add the link
yield self._changeShare(request, "ACCEPTED", hostUrl, inviteUID, displayname)
- response = (yield self._acceptShare(request, oldShare, SHARETYPE_INVITE, hostUrl, inviteUID, displayname))
+ response = (yield self._acceptShare(request, oldShare, False, hostUrl, inviteUID, displayname))
returnValue(response)
@inlineCallbacks
def acceptDirectShare(self, request, hostUrl, resourceUID, displayname=None):
# Just add the link
- oldShare = yield self.sharesDB().recordForShareUID(resourceUID)
- response = (yield self._acceptShare(request, oldShare, SHARETYPE_DIRECT, hostUrl, resourceUID, displayname))
+ oldShare = yield self._shareForUID(resourceUID)
+ response = (yield self._acceptShare(request, oldShare, True, hostUrl, resourceUID, displayname))
returnValue(response)
@inlineCallbacks
- def _acceptShare(self, request, oldShare, sharetype, hostUrl, shareUID, displayname=None):
+ def _acceptShare(self, request, oldShare, isDirect, hostUrl, shareUID, displayname=None):
+ # Get shared collection in non-share mode first
+ sharedCollection = (yield request.locateResource(hostUrl))
+ ownerPrincipal = (yield self.ownerPrincipal(request))
+
# Add or update in DB
if oldShare:
share = oldShare
else:
- share = SharedCollectionRecord(shareUID, sharetype, hostUrl, str(uuid4()), displayname)
- yield self.sharesDB().addOrUpdateRecord(share)
+
+ #FIXME: add new share, then generate new from
+
+ sharedCollectionRecord = SharedCollectionRecord(shareUID, "D" if isDirect else "I", hostUrl, str(uuid4()), displayname)
+ yield self._addOrUpdateRecord(sharedCollectionRecord)
+
+ # find in allShares, which I like better because self._allShares is a cache
+ share = yield self._shareForUID(shareUID, refresh=True)
+ # or, create fresh like legacy code
+ # FIXME: Need sharee home child
+ # share = Share(shareeHomeChild=self._newStoreObject, sharerHomeChild=sharedCollection._newStoreObject, sharedResourceURL=hostUrl)
- # Get shared collection in non-share mode first
- sharedCollection = (yield request.locateResource(hostUrl))
- ownerPrincipal = (yield self.ownerPrincipal(request))
# For a direct share we will copy any calendar-color over using the owners view
color = None
- if sharetype == SHARETYPE_DIRECT and not oldShare and sharedCollection.isCalendarCollection():
+ if share.isDirect() and not oldShare and sharedCollection.isCalendarCollection():
try:
color = (yield sharedCollection.readProperty(customxml.CalendarColor, request))
except HTTPError:
@@ -1166,24 +1253,24 @@
returnValue(XMLResponse(
code = responsecode.OK,
element = customxml.SharedAs(
- element.HRef.fromString(joinURL(self.url(), share.localname))
+ element.HRef.fromString(joinURL(self.url(), share.shareeResourceName()))
)
))
def removeShare(self, request, share):
""" Remove a shared collection named in resourceName """
- # Send a decline when an invite share is removed only
- if share.sharetype == SHARETYPE_INVITE:
- return self.declineShare(request, share.hosturl, share.shareuid)
+ if share.isDirect():
+ return self.removeDirectShare(request, share)
else:
- return self.removeDirectShare(request, share)
+ # Send a decline when an invite share is removed only
+ return self.declineShare(request, share.sharedResourceURL(), share.uid())
@inlineCallbacks
def removeShareByUID(self, request, shareUID):
""" Remove a shared collection but do not send a decline back """
- share = yield self.sharesDB().recordForShareUID(shareUID)
+ share = yield self._shareForUID(shareUID)
if share:
yield self.removeDirectShare(request, share)
@@ -1193,7 +1280,7 @@
def removeDirectShare(self, request, share):
""" Remove a shared collection but do not send a decline back """
- shareURL = joinURL(self.url(), share.localname)
+ shareURL = joinURL(self.url(), share.shareeResourceName())
if self.isCalendarCollection():
# For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
@@ -1203,7 +1290,7 @@
inbox = (yield request.locateResource(inboxURL))
inbox.processFreeBusyCalendar(shareURL, False)
- yield self.sharesDB().removeRecordForShareUID(share.shareuid)
+ yield self._removeShareForUID(share.uid())
# Notify client of changes
yield self.notifyChanged()
@@ -1324,6 +1411,32 @@
self.localname = localname
self.summary = summary
+class Share(object):
+
+ def __init__(self, sharerHomeChild, shareeHomeChild, sharedResourceURL):
+ self._shareeHomeChild = shareeHomeChild
+ self._sharerHomeChild = sharerHomeChild
+ self._sharedResourceURL = sharedResourceURL
+
+ def uid(self):
+ # Move to CommonHomeChild shareUID?
+ if self._shareeHomeChild.shareMode() == _BIND_MODE_DIRECT:
+ return "Direct-%s-%s" % (self._shareeHomeChild._home._resourceID, self._sharerHomeChild._resourceID,)
+ else:
+ return self._shareeHomeChild.shareUID()
+
+ def isDirect(self):
+ return self._shareeHomeChild.shareMode() == _BIND_MODE_DIRECT
+
+ def sharedResourceURL(self):
+ return self._sharedResourceURL
+
+ def shareeResourceName(self):
+ return self._shareeHomeChild.name()
+
+ def summary(self):
+ return self._shareeHomeChild.shareMessage()
+
class SharedCollectionsDatabase(AbstractSQLDatabase, LoggingMixIn):
db_basename = db_prefix + "shares"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120801/92fc9ca0/attachment-0001.html>
More information about the calendarserver-changes
mailing list