[CalendarServer-changes] [9266] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed May 23 17:25:40 PDT 2012
Revision: 9266
http://trac.macosforge.org/projects/calendarserver/changeset/9266
Author: sagen at apple.com
Date: 2012-05-23 17:25:40 -0700 (Wed, 23 May 2012)
Log Message:
-----------
Purge tool now handles shared collections, and removes home resource properties.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tools/purge.py
CalendarServer/trunk/calendarserver/tools/test/test_purge.py
CalendarServer/trunk/txdav/caldav/datastore/sql.py
CalendarServer/trunk/txdav/caldav/datastore/test/common.py
CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py
CalendarServer/trunk/txdav/carddav/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql.py
Modified: CalendarServer/trunk/calendarserver/tools/purge.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/purge.py 2012-05-22 21:29:28 UTC (rev 9265)
+++ CalendarServer/trunk/calendarserver/tools/purge.py 2012-05-24 00:25:40 UTC (rev 9266)
@@ -660,7 +660,42 @@
# See if calendar home is provisioned
txn = store.newTransaction()
- calHomeProvisioned = ((yield txn.calendarHomeWithUID(uid)) is not None)
+ storeCalHome = (yield txn.calendarHomeWithUID(uid))
+ calHomeProvisioned = storeCalHome is not None
+
+ # If in "completely" mode, unshare collections, remove notifications
+ if calHomeProvisioned and completely:
+
+ # Process shared-to-me calendars
+ names = list((yield storeCalHome.listSharedChildren()))
+ for name in names:
+ if verbose:
+ if dryrun:
+ print "Would unshare: %s" % (name,)
+ else:
+ print "Unsharing: %s" % (name,)
+ if not dryrun:
+ child = (yield storeCalHome.sharedChildWithName(name))
+ (yield child.unshare())
+
+ # Process shared calendars
+ children = list((yield storeCalHome.children()))
+ for child in children:
+ if verbose:
+ if dryrun:
+ print "Would unshare: %s" % (child.name(),)
+ else:
+ print "Unsharing: %s" % (child.name(),)
+ if not dryrun:
+ (yield child.unshare())
+
+ if not dryrun:
+ (yield storeCalHome.removeUnacceptedShares())
+ (yield storeCalHome.removeInvites())
+ notificationHome = (yield txn.notificationsWithUID(uid))
+ if notificationHome is not None:
+ (yield notificationHome.remove())
+
(yield txn.commit())
# Anything in the past is left alone
@@ -686,8 +721,8 @@
calendarHome = yield principal.calendarHome(request)
for collName in (yield calendarHome.listChildren()):
collection = (yield calendarHome.getChild(collName))
+
if collection.isCalendarCollection() or collName == "inbox":
-
childNames = []
if completely:
Modified: CalendarServer/trunk/calendarserver/tools/test/test_purge.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_purge.py 2012-05-22 21:29:28 UTC (rev 9265)
+++ CalendarServer/trunk/calendarserver/tools/test/test_purge.py 2012-05-24 00:25:40 UTC (rev 9266)
@@ -29,6 +29,7 @@
from twisted.trial import unittest
from twisted.internet.defer import inlineCallbacks
from txdav.common.datastore.test.util import buildStore, populateCalendarsFrom, CommonCommonTests
+from txdav.common.datastore.sql_tables import _BIND_MODE_WRITE
from twext.web2.http_headers import MimeType
@@ -783,6 +784,7 @@
Tests for purging the data belonging to a given principal
"""
uid = "6423F94A-6B76-4A3A-815B-D52CFD77935D"
+ uid2 = "37DB0C90-4DB1-4932-BC69-3DAB66F374F5"
metadata = {
"accessMode": "PUBLIC",
@@ -798,6 +800,10 @@
"attachment.ics" : (ATTACHMENT_ICS, metadata,),
}
},
+ uid2 : {
+ "calendar2" : {
+ }
+ },
}
@inlineCallbacks
@@ -819,8 +825,9 @@
self.rootResource = getRootResource(config, self._sqlCalendarStore)
self.directory = self.rootResource.getDirectory()
+ txn = self._sqlCalendarStore.newTransaction()
+
# Add attachment to attachment.ics
- txn = self._sqlCalendarStore.newTransaction()
home = (yield txn.calendarHomeWithUID(self.uid))
calendar = (yield home.calendarWithName("calendar1"))
event = (yield calendar.calendarObjectWithName("attachment.ics"))
@@ -829,9 +836,25 @@
t.write("attachment")
t.write(" text")
(yield t.loseConnection())
+
+ # Share calendars each way
+ home2 = (yield txn.calendarHomeWithUID(self.uid2))
+ calendar2 = (yield home2.calendarWithName("calendar2"))
+ self.sharedName = (yield calendar2.shareWith(home, _BIND_MODE_WRITE))
+ self.sharedName2 = (yield calendar.shareWith(home2, _BIND_MODE_WRITE))
+
(yield txn.commit())
+ txn = self._sqlCalendarStore.newTransaction()
+ home = (yield txn.calendarHomeWithUID(self.uid))
+ calendar2 = (yield home.sharedChildWithName(self.sharedName))
+ self.assertNotEquals(calendar2, None)
+ home2 = (yield txn.calendarHomeWithUID(self.uid2))
+ calendar1 = (yield home2.sharedChildWithName(self.sharedName2))
+ self.assertNotEquals(calendar1, None)
+ (yield txn.commit())
+
@inlineCallbacks
def populate(self):
yield populateCalendarsFrom(self.requirements, self.storeUnderTest())
@@ -865,6 +888,9 @@
txn = self._sqlCalendarStore.newTransaction()
home = (yield txn.calendarHomeWithUID(self.uid))
self.assertEquals(home, None)
+ # Verify calendar1 was unshared to uid2
+ home2 = (yield txn.calendarHomeWithUID(self.uid2))
+ self.assertEquals((yield home2.sharedChildWithName(self.sharedName)), None)
(yield txn.commit())
count, ignored = (yield purgeUID(self.storeUnderTest(), self.uid, self.directory,
Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py 2012-05-22 21:29:28 UTC (rev 9265)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py 2012-05-24 00:25:40 UTC (rev 9266)
@@ -60,7 +60,7 @@
_ATTACHMENTS_MODE_NONE, _ATTACHMENTS_MODE_READ, _ATTACHMENTS_MODE_WRITE,\
CALENDAR_HOME_TABLE, CALENDAR_HOME_METADATA_TABLE,\
CALENDAR_AND_CALENDAR_BIND, CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE,\
- CALENDAR_OBJECT_AND_BIND_TABLE, schema
+ CALENDAR_OBJECT_AND_BIND_TABLE, _BIND_STATUS_INVITED, schema
from twext.enterprise.dal.syntax import Select, Count, ColumnSyntax
from twext.enterprise.dal.syntax import Insert
from twext.enterprise.dal.syntax import Update
@@ -131,6 +131,7 @@
cb = schema.CALENDAR_BIND
cor = schema.CALENDAR_OBJECT_REVISIONS
at = schema.ATTACHMENT
+ rp = schema.RESOURCE_PROPERTY
# delete attachments corresponding to this home, also removing from disk
rows = (yield Select(
@@ -167,6 +168,11 @@
Where=ch.RESOURCE_ID == self._resourceID
).on(self._txn)
+ yield Delete(
+ From=rp,
+ Where=rp.RESOURCE_ID == self._resourceID
+ ).on(self._txn)
+
yield self._cacher.delete(str(self._ownerUID))
@@ -334,7 +340,52 @@
yield _requireCalendarWithType("VTODO", "tasks")
+ @classproperty
+ def _unacceptedSharesQuery(cls): #@NoSelf
+ cb = schema.CALENDAR_BIND
+ return Select([cb.CALENDAR_RESOURCE_NAME],
+ From=cb,
+ Where=(cb.CALENDAR_HOME_RESOURCE_ID == Parameter("homeResourceID")).And(cb.BIND_STATUS == _BIND_STATUS_INVITED))
+
+ @inlineCallbacks
+ def removeUnacceptedShares(self):
+ """
+ Unbinds any collections that have been shared to this home but not yet
+ accepted. Associated invite entries are also removed.
+ """
+ inv = schema.INVITE
+ cb = schema.CALENDAR_BIND
+ rows = yield self._unacceptedSharesQuery.on(self._txn, homeResourceID=self._resourceID)
+ for (resourceName,) in rows:
+ kwds = { "ResourceName" : resourceName }
+ yield Delete(
+ From=inv,
+ Where=(
+ inv.INVITE_UID == Parameter("ResourceName")
+ ),
+ ).on(self._txn, **kwds)
+
+ yield Delete(
+ From=cb,
+ Where=(
+ cb.CALENDAR_RESOURCE_NAME == Parameter("ResourceName")
+ ),
+ ).on(self._txn, **kwds)
+
+
+ @inlineCallbacks
+ def removeInvites(self):
+ """
+ Remove all remaining invite entries for this home.
+ """
+ inv = schema.INVITE
+ kwds = { "HomeResourceID" : self._resourceID }
+ yield Delete(
+ From=inv,
+ Where=(inv.HOME_RESOURCE_ID == Parameter("HomeResourceID"))
+ ).on(self._txn, **kwds)
+
CalendarHome._register(ECALENDARTYPE)
@@ -663,7 +714,14 @@
newParentID=newparent._resourceID,
resourceID=child._resourceID
)
-
+
+ def unshare(self):
+ """
+ Unshares a collection, regardless of which "direction" it was shared.
+ """
+ return super(Calendar, self).unshare(ECALENDARTYPE)
+
+
icalfbtype_to_indexfbtype = {
"UNKNOWN" : 0,
"FREE" : 1,
Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py 2012-05-22 21:29:28 UTC (rev 9265)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py 2012-05-24 00:25:40 UTC (rev 9266)
@@ -1043,8 +1043,6 @@
L{ICalendar.unshareWith} will remove a previously-shared calendar from
another user's calendar home.
"""
- # XXX: ideally this would actually be using the shared calendar object
- # from the shareee's home and just calling .unshare() on it.
yield self.test_shareWith()
if commit:
yield self.commit()
@@ -1058,8 +1056,49 @@
shares = yield other.retrieveOldShares().allRecords()
self.assertEqual(len(shares), 0)
+ @inlineCallbacks
+ def test_unshareSharerSide(self, commit=False):
+ """
+ Verify the coll.unshare( ) method works when called from the
+ sharer's copy
+ """
+ yield self.test_shareWith()
+ if commit:
+ yield self.commit()
+ cal = yield self.calendarUnderTest()
+ other = yield self.homeUnderTest(name=OTHER_HOME_UID)
+ otherCal = yield other.sharedChildWithName(self.sharedName)
+ self.assertNotEqual(otherCal, None)
+ yield cal.unshare()
+ otherCal = yield other.sharedChildWithName(self.sharedName)
+ self.assertEqual(otherCal, None)
+ invites = yield cal.retrieveOldInvites().allRecords()
+ self.assertEqual(len(invites), 0)
+ shares = yield other.retrieveOldShares().allRecords()
+ self.assertEqual(len(shares), 0)
@inlineCallbacks
+ def test_unshareShareeSide(self, commit=False):
+ """
+ Verify the coll.unshare( ) method works when called from the
+ sharee's copy
+ """
+ yield self.test_shareWith()
+ if commit:
+ yield self.commit()
+ cal = yield self.calendarUnderTest()
+ other = yield self.homeUnderTest(name=OTHER_HOME_UID)
+ otherCal = yield other.sharedChildWithName(self.sharedName)
+ self.assertNotEqual(otherCal, None)
+ yield otherCal.unshare()
+ otherCal = yield other.sharedChildWithName(self.sharedName)
+ self.assertEqual(otherCal, None)
+ invites = yield cal.retrieveOldInvites().allRecords()
+ self.assertEqual(len(invites), 0)
+ shares = yield other.retrieveOldShares().allRecords()
+ self.assertEqual(len(shares), 0)
+
+ @inlineCallbacks
def test_unshareWithInDifferentTransaction(self):
"""
L{ICalendar.unshareWith} will remove a previously-shared calendar from
Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py 2012-05-22 21:29:28 UTC (rev 9265)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py 2012-05-24 00:25:40 UTC (rev 9266)
@@ -477,6 +477,8 @@
test_unshareWith = test_shareWith
test_unshareWithInDifferentTransaction = test_shareWith
test_asShared = test_shareWith
+ test_unshareSharerSide = test_shareWith
+ test_unshareShareeSide = test_shareWith
def test_init(self):
Modified: CalendarServer/trunk/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/sql.py 2012-05-22 21:29:28 UTC (rev 9265)
+++ CalendarServer/trunk/txdav/carddav/datastore/sql.py 2012-05-24 00:25:40 UTC (rev 9266)
@@ -107,6 +107,7 @@
ah = schema.ADDRESSBOOK_HOME
ab = schema.ADDRESSBOOK_BIND
aor = schema.ADDRESSBOOK_OBJECT_REVISIONS
+ rp = schema.RESOURCE_PROPERTY
yield Delete(
From=ab,
@@ -123,6 +124,11 @@
Where=ah.RESOURCE_ID == self._resourceID
).on(self._txn)
+ yield Delete(
+ From=rp,
+ Where=rp.RESOURCE_ID == self._resourceID
+ ).on(self._txn)
+
yield self._cacher.delete(str(self._ownerUID))
@@ -201,7 +207,13 @@
return MimeType.fromString("text/vcard; charset=utf-8")
+ def unshare(self):
+ """
+ Unshares a collection, regardless of which "direction" it was shared.
+ """
+ return super(AddressBook, self).unshare(EADDRESSBOOKTYPE)
+
class AddressBookObject(CommonObjectResource):
implements(IAddressBookObject)
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2012-05-22 21:29:28 UTC (rev 9265)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2012-05-24 00:25:40 UTC (rev 9266)
@@ -437,7 +437,6 @@
"""
return NotificationCollection.notificationsWithUID(self, uid)
-
@classproperty
def _insertAPNSubscriptionQuery(cls): #@NoSelf
apn = schema.APN_SUBSCRIPTIONS
@@ -2106,6 +2105,28 @@
return self._bindMode
+ @inlineCallbacks
+ def unshare(self, homeType):
+ """
+ Unshares a collection, regardless of which "direction" it was shared.
+
+ @param homeType: a valid store type (ECALENDARTYPE or EADDRESSBOOKTYPE)
+ """
+ mode = self.shareMode()
+ if mode == _BIND_MODE_OWN:
+ # 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 _bindEntriesFor(cls):
bind = cls._bindSchema
@@ -3641,7 +3662,31 @@
self.notifyChanged()
+ @inlineCallbacks
+ def remove(self):
+ """
+ Remove DB rows corresponding to this notification home.
+ """
+ # Delete NOTIFICATION rows
+ no = schema.NOTIFICATION
+ kwds = { "ResourceID" : self._resourceID }
+ yield Delete(
+ From=no,
+ Where=(
+ no.NOTIFICATION_HOME_RESOURCE_ID == Parameter("ResourceID")
+ ),
+ ).on(self._txn, **kwds)
+ # Delete NOTIFICATION_HOME (will cascade to NOTIFICATION_OBJECT_REVISIONS)
+ nh = schema.NOTIFICATION_HOME
+ yield Delete(
+ From=nh,
+ Where=(
+ nh.RESOURCE_ID == Parameter("ResourceID")
+ ),
+ ).on(self._txn, **kwds)
+
+
class NotificationObject(LoggingMixIn, FancyEqMixin):
implements(INotificationObject)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120523/d82de579/attachment-0001.html>
More information about the calendarserver-changes
mailing list