[CalendarServer-changes] [13753] CalendarServer/branches/users/gaya/groupsharee2/txdav
source_changes at macosforge.org
source_changes at macosforge.org
Fri Jul 11 13:46:58 PDT 2014
Revision: 13753
http://trac.calendarserver.org//changeset/13753
Author: gaya at apple.com
Date: 2014-07-11 13:46:58 -0700 (Fri, 11 Jul 2014)
Log Message:
-----------
first group sharee tests
Modified Paths:
--------------
CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py
CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/test_sql_sharing.py
CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py
Added Paths:
-----------
CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/accounts/
CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/accounts/groupShareeAccounts.xml
Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py 2014-07-11 20:03:42 UTC (rev 13752)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py 2014-07-11 20:46:58 UTC (rev 13753)
@@ -1820,7 +1820,7 @@
rows = yield Select(
[Count(gs.GROUP_ID)],
From=gs,
- Where=(gs.CALENDAR_HOME_ID == self.ownerHome()._resourceID).And(
+ Where=(gs.CALENDAR_HOME_ID == self.viewerHome()._resourceID).And(
gs.CALENDAR_ID == self._resourceID)
).on(self._txn)
if rows[0][0] > 1:
@@ -1855,9 +1855,9 @@
gs = schema.GROUP_SHAREE
rows = yield Select(
- [gs.MEMBERSHIP_HASH, gs.MODE],
+ [gs.MEMBERSHIP_HASH, gs.GROUP_BIND_MODE],
From=gs,
- Where=(gs.CALENDAR_HOME_ID == self.ownerHome()._resourceID).And(
+ Where=(gs.CALENDAR_HOME_ID == self.viewerHome()._resourceID).And(
gs.CALENDAR_ID == self._resourceID).And(
gs.GROUP_ID == groupID)
).on(self._txn)
@@ -1871,7 +1871,7 @@
if updateMap:
yield Update(
updateMap,
- Where=(gs.CALENDAR_HOME_ID == self.ownerHome()._resourceID).And(
+ Where=(gs.CALENDAR_HOME_ID == self.viewerHome()._resourceID).And(
gs.CALENDAR_ID == self._resourceID).And(
gs.GROUP_ID == groupID
)
@@ -1881,7 +1881,7 @@
yield Insert({
gs.MEMBERSHIP_HASH: membershipHash,
gs.GROUP_BIND_MODE: mode,
- gs.CALENDAR_HOME_ID: self.ownerHome()._resourceID,
+ gs.CALENDAR_HOME_ID: self.viewerHome()._resourceID,
gs.CALENDAR_ID: self._resourceID,
gs.GROUP_ID: groupID,
}).on(self._txn)
@@ -1899,7 +1899,7 @@
rows = yield Select(
[Max(gs.GROUP_BIND_MODE)], # _BIND_MODE_WRITE > _BIND_MODE_READ
From=gs,
- Where=(gs.CALENDAR_HOME_ID == self.ownerHome()._resourceID).And(
+ Where=(gs.CALENDAR_HOME_ID == self.viewerHome()._resourceID).And(
gs.CALENDAR_ID == self._resourceID
)
).on(self._txn)
@@ -1929,7 +1929,7 @@
record = yield self._txn.directoryService().recordWithUID(shareeUID.decode("utf-8"))
if (
record is None or
- record.recordType != RecordType.group or not (False and
+ record.recordType != RecordType.group or not (
config.Sharing.Enabled and
config.Sharing.Calendars.Enabled and
config.Sharing.Calendars.Groups.Enabled
@@ -1940,15 +1940,19 @@
)
# invite every member of group
- groupID = (yield self._txn.groupByUID(record.uid))[0]
+ shareeViews = set()
+ groupID = (yield self._txn.groupByUID(shareeUID))[0]
memberUIDs = yield self._txn.groupMemberUIDs(groupID)
for memberUID in memberUIDs:
- shareeView = yield self.shareeView(shareeUID)
+ shareeView = yield self.shareeView(memberUID)
newMode = _BIND_MODE_GROUP if shareeView is None else shareeView.groupModeAfterAddingOneGroupSharee()
if newMode is not None:
- yield super(Calendar, self).inviteUIDToShare(memberUID, newMode)
+ # everything but direct share
+ shareeView = yield super(Calendar, self).inviteUIDToShare(memberUID, newMode, summary)
+ yield shareeView.updateShareeGroupLink(shareeUID, mode=mode)
+ shareeViews.add(shareeView)
- returnValue(None)
+ returnValue(shareeViews)
@inlineCallbacks
@@ -1987,16 +1991,45 @@
"""
# Cancel invites - we'll just use whatever userid we are given
- shareeView = yield self.shareeView(shareeUID)
- if shareeView is not None:
- newMode = yield shareeView.groupModeAfterRemovingOneGroupSharee()
- if newMode is None:
- yield super(Calendar, self).uninviteUIDFromShare(shareeUID)
- else:
- yield super(Calendar, self).inviteUIDToShare(shareeUID, newMode)
+ record = yield self._txn.directoryService().recordWithUID(shareeUID.decode("utf-8"))
+ if (
+ record is None or
+ record.recordType != RecordType.group or not (
+ config.Sharing.Enabled and
+ config.Sharing.Calendars.Enabled and
+ config.Sharing.Calendars.Groups.Enabled
+ )
+ ):
+ returnValue(
+ (yield super(Calendar, self).uninviteUIDFromShare(shareeUID))
+ )
+ # uninvite every member of group
+ groupID = (yield self._txn.groupByUID(shareeUID))[0]
+ memberUIDs = yield self._txn.groupMemberUIDs(groupID)
+ for memberUID in memberUIDs:
+ shareeView = yield self.shareeView(memberUID)
+ if shareeView is not None:
+ newMode = yield shareeView.groupModeAfterRemovingOneGroupSharee()
+ gs = schema.GROUP_SHAREE
+ yield Delete(
+ From=gs,
+ Where=(gs.CALENDAR_HOME_ID == shareeView.viewerHome()._resourceID).And(
+ gs.CALENDAR_ID == self._resourceID).And(
+ gs.GROUP_ID == groupID
+ )
+ )
+ if newMode is None:
+ # only group was shared, do delete share
+ yield super(Calendar, self).uninviteUIDFromShare(memberUID)
+ else:
+ # multiple groups or group and individual was shared, update to new mode
+ yield super(Calendar, self).inviteUIDToShare(memberUID, newMode)
+
+
+
icalfbtype_to_indexfbtype = {
"UNKNOWN" : 0,
"FREE" : 1,
Added: CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/accounts/groupShareeAccounts.xml
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/accounts/groupShareeAccounts.xml (rev 0)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/accounts/groupShareeAccounts.xml 2014-07-11 20:46:58 UTC (rev 13753)
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<!DOCTYPE accounts SYSTEM "accounts.dtd">
+
+<directory realm="Test Realm">
+ <record type="user">
+ <short-name>user01</short-name>
+ <uid>user01</uid>
+ <guid>10000000-0000-0000-0000-000000000001</guid>
+ <password>user01</password>
+ <full-name>User 01</full-name>
+ <email>user01 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user02</short-name>
+ <uid>user02</uid>
+ <guid>10000000-0000-0000-0000-000000000002</guid>
+ <password>user02</password>
+ <full-name>User 02</full-name>
+ <email>user02 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user03</short-name>
+ <uid>user03</uid>
+ <guid>10000000-0000-0000-0000-000000000003</guid>
+ <password>user03</password>
+ <full-name>User 03</full-name>
+ <email>user03 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user04</short-name>
+ <uid>user04</uid>
+ <guid>10000000-0000-0000-0000-000000000004</guid>
+ <password>user04</password>
+ <full-name>User 04</full-name>
+ <email>user04 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user05</short-name>
+ <uid>user05</uid>
+ <guid>10000000-0000-0000-0000-000000000005</guid>
+ <password>user05</password>
+ <full-name>User 05</full-name>
+ <email>user05 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user06</short-name>
+ <uid>user06</uid>
+ <guid>10000000-0000-0000-0000-000000000006</guid>
+ <password>user06</password>
+ <full-name>User 06</full-name>
+ <email>user06 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user07</short-name>
+ <uid>user07</uid>
+ <guid>10000000-0000-0000-0000-000000000007</guid>
+ <password>user07</password>
+ <full-name>User 07</full-name>
+ <email>user07 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user08</short-name>
+ <uid>user08</uid>
+ <guid>10000000-0000-0000-0000-000000000008</guid>
+ <password>user08</password>
+ <full-name>User 08</full-name>
+ <email>user08 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user09</short-name>
+ <uid>user09</uid>
+ <guid>10000000-0000-0000-0000-000000000009</guid>
+ <password>user09</password>
+ <full-name>User 09</full-name>
+ <email>user09 at example.com</email>
+ </record>
+ <record type="user">
+ <short-name>user10</short-name>
+ <uid>user10</uid>
+ <guid>10000000-0000-0000-0000-000000000010</guid>
+ <password>user10</password>
+ <full-name>User 10</full-name>
+ <email>user10 at example.com</email>
+ </record>
+ <record type="group">
+ <short-name>group01</short-name>
+ <uid>group01</uid>
+ <guid>20000000-0000-0000-0000-000000000001</guid>
+ <full-name>Group 01</full-name>
+ <email>group01 at example.com</email>
+ <member-uid>user01</member-uid>
+ </record>
+ <record type="group">
+ <short-name>group02</short-name>
+ <uid>group02</uid>
+ <guid>20000000-0000-0000-0000-000000000002</guid>
+ <full-name>Group 02</full-name>
+ <email>group02 at example.com</email>
+ <member-uid>user06</member-uid>
+ <member-uid>user07</member-uid>
+ <member-uid>user08</member-uid>
+ </record>
+ <record type="group">
+ <short-name>group03</short-name>
+ <uid>group03</uid>
+ <guid>20000000-0000-0000-0000-000000000003</guid>
+ <full-name>Group 03</full-name>
+ <email>group03 at example.com</email>
+ <member-uid>user07</member-uid>
+ <member-uid>user08</member-uid>
+ <member-uid>user09</member-uid>
+ </record>
+ <record type="group">
+ <short-name>group04</short-name>
+ <uid>group04</uid>
+ <guid>20000000-0000-0000-0000-000000000004</guid>
+ <full-name>Group 04</full-name>
+ <member-uid>group02</member-uid>
+ <member-uid>group03</member-uid>
+ <member-uid>user10</member-uid>
+ </record>
+</directory>
Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/test_sql_sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/test_sql_sharing.py 2014-07-11 20:03:42 UTC (rev 13752)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/test_sql_sharing.py 2014-07-11 20:46:58 UTC (rev 13753)
@@ -15,20 +15,25 @@
##
+from twext.python.clsprop import classproperty
+from twext.python.filepath import CachingFilePath as FilePath
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.trial.unittest import TestCase
-
-from twext.python.clsprop import classproperty
-from txdav.common.datastore.test.util import CommonCommonTests, \
- populateCalendarsFrom
-from txdav.common.datastore.sql_tables import _BIND_MODE_READ, \
- _BIND_STATUS_INVITED, _BIND_MODE_DIRECT, _BIND_STATUS_ACCEPTED
+from twistedcaldav import customxml
+from twistedcaldav.stdconfig import config
from txdav.base.propertystore.base import PropertyName
+from txdav.common.datastore.sql_tables import _BIND_MODE_DIRECT
+from txdav.common.datastore.sql_tables import _BIND_MODE_GROUP
+from txdav.common.datastore.sql_tables import _BIND_MODE_READ
+from txdav.common.datastore.sql_tables import _BIND_MODE_WRITE
+from txdav.common.datastore.sql_tables import _BIND_STATUS_ACCEPTED
+from txdav.common.datastore.sql_tables import _BIND_STATUS_INVITED
+from txdav.common.datastore.test.util import CommonCommonTests
+from txdav.common.datastore.test.util import populateCalendarsFrom
from txdav.xml.base import WebDAVTextElement
-from twistedcaldav import customxml
from txdav.xml.element import registerElement, registerElementClass
+import os
-
class BaseSharingTests(CommonCommonTests, TestCase):
"""
Test store-based calendar sharing.
@@ -581,6 +586,518 @@
+class GroupSharing(BaseSharingTests):
+ """
+ Test store-based group book sharing.
+ """
+
+ @inlineCallbacks
+ def setUp(self):
+ yield super(BaseSharingTests, self).setUp()
+
+ accountsFilePath = FilePath(
+ os.path.join(os.path.dirname(__file__), "accounts")
+ )
+ yield self.buildStoreAndDirectory(
+ accounts=accountsFilePath.child("groupShareeAccounts.xml"),
+ #resources=accountsFilePath.child("resources.xml"),
+ )
+ yield self.populate()
+
+ self.paths = {}
+
+
+ def configure(self):
+ super(GroupSharing, self).configure()
+ config.Sharing.Enabled = True
+ config.Sharing.Calendars.Enabled = True
+ config.Sharing.Calendars.Groups.Enabled = True
+ config.Sharing.Calendars.Groups.ReconciliationDelaySeconds = 0
+
+
+ @inlineCallbacks
+ def _check_notifications(self, home, items):
+ notifyHome = yield self.transactionUnderTest().notificationsWithUID(home)
+ notifications = yield notifyHome.listNotificationObjects()
+ self.assertEqual(set(notifications), set(items))
+
+
+ @inlineCallbacks
+ def test_no_shares(self):
+ """
+ Test that initially there are no shares.
+ """
+
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 0)
+
+
+ @inlineCallbacks
+ def test_invite_sharee(self):
+ """
+ Test invite/uninvite creates/removes shares and notifications.
+ """
+
+ # Invite
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 0)
+ self.assertFalse(calendar.isShared())
+
+ shareeViews = yield calendar.inviteUIDToShare("group02", _BIND_MODE_READ, "summary")
+ self.assertEqual(len(shareeViews), 3)
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 3)
+ shareeViews = sorted(shareeViews, key=lambda shareeView: shareeView.viewerHome().uid())
+ invites = sorted(invites, key=lambda invitee: invitee.shareeUID)
+ for i in range(3):
+ self.assertEqual(invites[i].uid, shareeViews[i].shareUID())
+ self.assertEqual(invites[i].ownerUID, "user01")
+ self.assertEqual(invites[i].shareeUID, shareeViews[i].viewerHome().uid())
+ self.assertEqual(invites[i].mode, _BIND_MODE_GROUP)
+ self.assertEqual((yield shareeViews[i].effectiveShareMode()), _BIND_MODE_READ)
+ self.assertEqual(invites[i].status, _BIND_STATUS_INVITED)
+ self.assertEqual(invites[i].summary, "summary")
+ #inviteUID = shareeView.shareUID()
+
+ self.assertTrue(calendar.isShared())
+
+ yield self.commit()
+
+ '''
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+ #yield self._check_notifications("user02", [inviteUID, ])
+
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ self.assertTrue(group.isShared())
+
+ yield self.commit()
+ '''
+
+ # Uninvite
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 3)
+ self.assertTrue(calendar.isShared())
+
+ yield calendar.uninviteUIDFromShare("group02")
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 0)
+ self.assertTrue(calendar.isShared())
+
+ yield self._check_notifications("user06", [])
+ yield self._check_notifications("user07", [])
+ yield self._check_notifications("user08", [])
+
+ yield self.commit()
+
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ self.assertTrue(calendar.isShared())
+ yield calendar.setShared(False)
+ self.assertFalse(calendar.isShared())
+
+
+ @inlineCallbacks
+ def test_accept_share(self):
+ """
+ Test that invite+accept creates shares and notifications.
+ """
+
+ # Invite
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 0)
+ self.assertFalse(group.isShared())
+
+ shareeView = yield group.inviteUIDToShare("user02", _BIND_MODE_READ, "summary")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 1)
+ inviteUID = shareeView.shareUID()
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+ yield self._check_notifications("user02", [inviteUID, ])
+
+ self.assertTrue(group.isShared())
+
+ yield self.commit()
+
+ # Accept
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.acceptShare(inviteUID)
+
+ yield self._check_calendar("user02", "user01", self.group1_children)
+ yield self._check_notifications("user01", [inviteUID + "-reply", ])
+
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ self.assertTrue(group.isShared())
+
+ yield self.commit()
+
+ # Re-accept
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.acceptShare(inviteUID)
+
+ yield self._check_calendar("user02", "user01", self.group1_children)
+ yield self._check_notifications("user01", [inviteUID + "-reply", ])
+
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ self.assertTrue(group.isShared())
+
+
+ @inlineCallbacks
+ def test_decline_share(self):
+ """
+ Test that invite+decline does not create shares but does create notifications.
+ """
+
+ # Invite
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 0)
+ self.assertFalse(group.isShared())
+
+ shareeView = yield group.inviteUIDToShare("user02", _BIND_MODE_READ, "summary")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 1)
+ inviteUID = shareeView.shareUID()
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+ yield self._check_notifications("user02", [inviteUID, ])
+
+ self.assertTrue(group.isShared())
+
+ yield self.commit()
+
+ # Decline
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.declineShare(inviteUID)
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+ yield self._check_notifications("user01", [inviteUID + "-reply", ])
+
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ self.assertTrue(group.isShared())
+
+ yield self.commit()
+
+ # Re-decline
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.declineShare(inviteUID)
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+ yield self._check_notifications("user01", [inviteUID + "-reply", ])
+
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ self.assertTrue(group.isShared())
+
+
+ @inlineCallbacks
+ def test_accept_decline_share(self):
+ """
+ Test that invite+accept/decline creates/removes shares and notifications.
+ Decline via the home.
+ """
+
+ # Invite
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 0)
+ self.assertFalse(group.isShared())
+
+ shareeView = yield group.inviteUIDToShare("user02", _BIND_MODE_READ, "summary")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 1)
+ inviteUID = shareeView.shareUID()
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+ yield self._check_notifications("user02", [inviteUID, ])
+
+ self.assertTrue(group.isShared())
+
+ yield self.commit()
+
+ # Accept
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.acceptShare(inviteUID)
+
+ yield self._check_calendar("user02", "user01", self.group1_children)
+ yield self._check_notifications("user01", [inviteUID + "-reply", ])
+
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ self.assertTrue(group.isShared())
+
+ yield self.commit()
+
+ # Decline
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.declineShare(inviteUID)
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+ yield self._check_notifications("user01", [inviteUID + "-reply", ])
+
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ self.assertTrue(group.isShared())
+
+
+ @inlineCallbacks
+ def test_accept_remove_share(self):
+ """
+ Test that invite+accept/decline creates/removes shares and notifications.
+ Decline via the shared collection (removal).
+ """
+
+ # Invite
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 0)
+
+ shareeView = yield group.inviteUIDToShare("user02", _BIND_MODE_READ, "summary")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 1)
+ inviteUID = shareeView.shareUID()
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+ yield self._check_notifications("user02", [inviteUID, ])
+
+ yield self.commit()
+
+ # Accept
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.acceptShare(inviteUID)
+
+ yield self._check_calendar("user02", "user01", self.group1_children)
+ yield self._check_notifications("user01", [inviteUID + "-reply", ])
+
+ yield self.commit()
+
+ # Delete
+ group = yield self.calendarObjectUnderTest(home="user02", calendar_name="user01", name="group1.vcf")
+ yield group.deleteShare()
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+ yield self._check_notifications("user01", [inviteUID + "-reply", ])
+
+
+ @inlineCallbacks
+ def test_accept_two_groups(self):
+ """
+ Test that accept of two groups works.
+ """
+
+ # Two shares
+ inviteUID1 = yield self._createGroupShare(groupname="group1.vcf")
+ inviteUID2 = yield self._createGroupShare(groupname="group2.vcf")
+
+ yield self._check_calendar("user02", "user01", self.all_children)
+ yield self._check_notifications("user01", [inviteUID1 + "-reply", inviteUID2 + "-reply", ])
+
+
+ @inlineCallbacks
+ def test_accept_uninvite_two_groups(self):
+ """
+ Test that accept of two groups works, then uninvite each one.
+ """
+
+ # Two shares
+ inviteUID1 = yield self._createGroupShare(groupname="group1.vcf")
+ inviteUID2 = yield self._createGroupShare(groupname="group2.vcf")
+
+ yield self._check_calendar("user02", "user01", self.all_children)
+ yield self._check_notifications("user01", [inviteUID1 + "-reply", inviteUID2 + "-reply", ])
+
+ yield self.commit()
+
+ # Uninvite one
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ yield group.uninviteUIDFromShare("user02")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 0)
+
+ yield self._check_calendar("user02", "user01", self.group2_children)
+
+ shared = yield self.calendarObjectUnderTest(home="user02", calendar_name="user01", name="group1.vcf")
+ self.assertTrue(shared is None)
+ shared = yield self.calendarObjectUnderTest(home="user02", calendar_name="user01", name="card2.vcf")
+ self.assertTrue(shared is None)
+
+ yield self.commit()
+
+ # Uninvite other
+ group = yield self.calendarObjectUnderTest(home="user02", calendar_name="user01", name="group2.vcf")
+ yield group.uninviteUIDFromShare("user02")
+ invites = yield group.sharingInvites()
+ self.assertEqual(len(invites), 0)
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+
+ @inlineCallbacks
+ def test_accept_decline_two_groups(self):
+ """
+ Test that accept of two groups works, then decline each one.
+ """
+
+ # Two shares
+ inviteUID1 = yield self._createGroupShare(groupname="group1.vcf")
+ inviteUID2 = yield self._createGroupShare(groupname="group2.vcf")
+
+ yield self._check_calendar("user02", "user01", self.all_children)
+ yield self._check_notifications("user01", [inviteUID1 + "-reply", inviteUID2 + "-reply", ])
+
+ yield self.commit()
+
+ # Decline one
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.declineShare(inviteUID1)
+
+ yield self._check_calendar("user02", "user01", self.group2_children)
+
+ shared = yield self.calendarObjectUnderTest(home="user02", calendar_name="user01", name="group1.vcf")
+ self.assertTrue(shared is None)
+ shared = yield self.calendarObjectUnderTest(home="user02", calendar_name="user01", name="card2.vcf")
+ self.assertTrue(shared is None)
+
+ yield self.commit()
+
+ # Decline other
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.declineShare(inviteUID2)
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+
+ @inlineCallbacks
+ def test_accept_two_groups_different_access(self):
+ """
+ Test that accept of two groups works, then uninvite each one.
+ """
+
+ # Two shares
+ inviteUID1 = yield self._createGroupShare(groupname="group1.vcf")
+ inviteUID2 = yield self._createGroupShare(groupname="group2.vcf", mode=_BIND_MODE_WRITE)
+
+ yield self._check_calendar("user02", "user01", self.all_children)
+ yield self._check_notifications("user01", [inviteUID1 + "-reply", inviteUID2 + "-reply", ])
+
+ # Read only for all, write for group2's items
+ yield self._check_read_only("user02", "user01", ["group1.vcf", "card2.vcf", ])
+ yield self._check_read_write("user02", "user01", ["group2.vcf", "card1.vcf", "card3.vcf", ])
+
+ yield self.commit()
+
+ # Decline one
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.declineShare(inviteUID2)
+
+ yield self._check_calendar("user02", "user01", self.group1_children)
+
+ yield self._check_read_only("user02", "user01", ["group1.vcf", "card1.vcf", "card2.vcf", ])
+
+ shared = yield self.calendarObjectUnderTest(home="user02", calendar_name="user01", name="group2.vcf")
+ self.assertTrue(shared is None)
+ shared = yield self.calendarObjectUnderTest(home="user02", calendar_name="user01", name="card3.vcf")
+ self.assertTrue(shared is None)
+
+ yield self.commit()
+
+ # Decline other
+ shareeHome = yield self.calendarHomeUnderTest(name="user02")
+ yield shareeHome.declineShare(inviteUID1)
+
+ sharedParent = yield self.calendarUnderTest(home="user02", name="user01")
+ self.assertTrue(sharedParent is None)
+
+
+
+class MixedSharing(BaseSharingTests):
+ """
+ Test store-based combined address book and group book sharing.
+ """
+
+ @inlineCallbacks
+ def test_calendar_ro_then_groups(self):
+
+ # Share address book read-only
+ shareeName = yield self._createShare()
+ yield self._check_calendar("user02", "user01", self.fully_shared_children)
+ yield self._check_read_only("user02", "user01", self.all_children)
+ yield self._check_read_write("user02", "user01", [])
+ yield self._check_notifications("user02", [shareeName, ])
+
+ # Add group1 read-write
+ inviteUID1 = yield self._createGroupShare(groupname="group1.vcf", mode=_BIND_MODE_WRITE)
+
+ yield self._check_calendar("user02", "user01", self.fully_shared_children)
+ yield self._check_read_only("user02", "user01", ["group2.vcf", "card3.vcf", ])
+ yield self._check_read_write("user02", "user01", ["group1.vcf", "card1.vcf", "card2.vcf", ])
+ yield self._check_notifications("user02", [shareeName, inviteUID1, ])
+
+ # Add group2 read-write
+ inviteUID2 = yield self._createGroupShare(groupname="group2.vcf", mode=_BIND_MODE_WRITE)
+
+ yield self._check_calendar("user02", "user01", self.fully_shared_children)
+ yield self._check_read_only("user02", "user01", [])
+ yield self._check_read_write("user02", "user01", self.all_children)
+ yield self._check_notifications("user02", [shareeName, inviteUID1, inviteUID2])
+
+ # Uninvite group1
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ yield group.uninviteUIDFromShare("user02")
+
+ yield self._check_calendar("user02", "user01", self.fully_shared_children)
+ yield self._check_read_only("user02", "user01", ["group1.vcf", "card2.vcf", ])
+ yield self._check_read_write("user02", "user01", ["group2.vcf", "card1.vcf", "card3.vcf", ])
+
+ # Uninvite group2
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group2.vcf")
+ yield group.uninviteUIDFromShare("user02")
+
+ yield self._check_calendar("user02", "user01", self.fully_shared_children)
+ yield self._check_read_only("user02", "user01", self.all_children)
+ yield self._check_read_write("user02", "user01", [])
+
+
+ @inlineCallbacks
+ def test_calendar_ro_then_group_no_accept(self):
+
+ # Share address book read-only
+ shareeName = yield self._createShare()
+ yield self._check_calendar("user02", "user01", self.fully_shared_children)
+ yield self._check_read_only("user02", "user01", self.all_children)
+ yield self._check_read_write("user02", "user01", [])
+ yield self._check_notifications("user02", [shareeName, ])
+
+ # Add group1 read-write - but do not accept
+ group = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar", name="group1.vcf")
+ invited = yield group.inviteUIDToShare("user02", _BIND_MODE_WRITE, "summary")
+ yield self._check_notifications("user02", [shareeName, invited.shareUID(), ])
+
+ yield self._check_calendar("user02", "user01", self.fully_shared_children)
+ yield self._check_read_only("user02", "user01", self.all_children)
+ yield self._check_read_write("user02", "user01", [])
+
+
+
class SharingRevisions(BaseSharingTests):
"""
Test store-based sharing and interaction with revision table.
Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py 2014-07-11 20:03:42 UTC (rev 13752)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py 2014-07-11 20:46:58 UTC (rev 13753)
@@ -453,7 +453,7 @@
for [calendarID] in rows:
wp = yield GroupShareeReconciliationWork.reschedule(
txn,
- seconds=float(config.Sharing.Calendar.Groups.ReconciliationDelaySeconds),
+ seconds=float(config.Sharing.Calendars.Groups.ReconciliationDelaySeconds),
calendarID=calendarID,
groupID=groupID,
)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140711/bd90cd9d/attachment-0001.html>
More information about the calendarserver-changes
mailing list