[CalendarServer-changes] [13766] CalendarServer/branches/users/gaya/groupsharee2/txdav
source_changes at macosforge.org
source_changes at macosforge.org
Wed Jul 16 16:30:52 PDT 2014
Revision: 13766
http://trac.calendarserver.org//changeset/13766
Author: gaya at apple.com
Date: 2014-07-16 16:30:52 -0700 (Wed, 16 Jul 2014)
Log Message:
-----------
fix _BIND_MODE_DIRECT _BIND_MODE_GROUP interactions
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/common/datastore/sql.py
CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py
Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py 2014-07-16 20:30:19 UTC (rev 13765)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py 2014-07-16 23:30:52 UTC (rev 13766)
@@ -84,8 +84,8 @@
from txdav.common.datastore.sql_tables import _ATTACHMENTS_MODE_NONE, \
_ATTACHMENTS_MODE_READ, _ATTACHMENTS_MODE_WRITE, _BIND_MODE_DIRECT, \
_BIND_MODE_GROUP, _BIND_MODE_GROUP_READ, _BIND_MODE_GROUP_WRITE, \
- _BIND_MODE_OWN, _BIND_MODE_READ, _BIND_MODE_WRITE, _TRANSP_OPAQUE, \
- _TRANSP_TRANSPARENT, schema
+ _BIND_MODE_OWN, _BIND_MODE_READ, _BIND_MODE_WRITE, _BIND_STATUS_ACCEPTED, \
+ _TRANSP_OPAQUE, _TRANSP_TRANSPARENT, schema
from txdav.common.icommondatastore import IndexedSearchException, \
InternalDataStoreError, HomeChildNameAlreadyExistsError, \
HomeChildNameNotAllowedError, ObjectResourceTooBigError, \
@@ -1760,31 +1760,33 @@
reconcile bind table with group members
"""
changed = False
- if (yield self.updateShareeGroupLink, groupUID):
- record = (
- yield self._txn.directoryService().recordWithUID(groupUID.decode("utf-8"))
- )
- groupID = (yield self._txn.groupByUID(record.uid))[0]
+ if (yield self.updateShareeGroupLink(groupUID)):
+ groupID = (yield self._txn.groupByUID(groupUID))[0]
memberUIDs = yield self._txn.groupMemberUIDs(groupID)
boundUIDs = set()
- bind = schema.CALENDAR_BIND
+ home = self._homeSchema
+ bind = self._bindSchema
rows = yield Select(
- [bind.HOME_RESOURCE_ID],
- From=bind,
- Where=bind.CALENDAR_RESOURCE_ID == self._resourceID.And(
- (bind.BIND_MODE == _BIND_MODE_GROUP).Or(
- bind.BIND_MODE == _BIND_MODE_GROUP_READ).Or(
- bind.BIND_MODE == _BIND_MODE_GROUP_WRITE)
+ [home.OWNER_UID],
+ From=home,
+ Where=home.RESOURCE_ID.In(
+ Select(
+ [bind.HOME_RESOURCE_ID],
+ From=bind,
+ Where=(bind.CALENDAR_RESOURCE_ID == self._resourceID).And(
+ (bind.BIND_MODE == _BIND_MODE_GROUP).Or(
+ bind.BIND_MODE == _BIND_MODE_GROUP_READ).Or(
+ bind.BIND_MODE == _BIND_MODE_GROUP_WRITE)
+ )
+ )
)
).on(self._txn)
- groupShareeHomeIDs = [row[0] for row in rows]
- for groupShareeHomeID in groupShareeHomeIDs:
- shareeHome = yield self._txn.calendarHomeWithResourceID(groupShareeHomeID, create=True)
- if shareeHome.uid() in memberUIDs:
- boundUIDs.add(shareeHome.uid())
+ for [shareeHomeUID] in rows:
+ if shareeHomeUID in memberUIDs:
+ boundUIDs.add(shareeHomeUID)
else:
- yield self.uninviteUIDFromShare(shareeHome.uid())
+ yield self.uninviteUIDFromShare(shareeHomeUID)
changed = True
for memberUID in memberUIDs - boundUIDs:
@@ -1812,16 +1814,39 @@
}.get(self._bindMode)
+ @inlineCallbacks
def _groupModeAfterRemovingOneIndividualSharee(self):
"""
return group mode after adding one group sharee or None
"""
- return {
- _BIND_MODE_GROUP_READ: _BIND_MODE_GROUP,
- _BIND_MODE_GROUP_WRITE: _BIND_MODE_GROUP,
- }.get(self._bindMode)
+ if self._bindMode == _BIND_MODE_DIRECT:
+ gs = schema.GROUP_SHAREE
+ gm = schema.GROUP_MEMBERSHIP
+ rows = yield Select(
+ [Count(gs.GROUP_ID)],
+ From=gs,
+ Where=(
+ gs.GROUP_ID.In(
+ Select(
+ [gm.GROUP_ID],
+ From=gm,
+ Where=(
+ gm.MEMBER_UID == Parameter("uid")
+ )
+ )
+ )
+ )
+ ).on(self._txn, uid=self.viewerHome().uid())
+ groupMode = _BIND_MODE_GROUP if rows[0][0] > 0 else None
+ else:
+ groupMode = {
+ _BIND_MODE_GROUP_READ: _BIND_MODE_GROUP,
+ _BIND_MODE_GROUP_WRITE: _BIND_MODE_GROUP,
+ }.get(self._bindMode)
+ returnValue(groupMode)
+
def _groupModeAfterAddingOneGroupSharee(self):
"""
return group mode after adding one group sharee or None
@@ -2017,19 +2042,14 @@
@type shareeUID: C{str}
"""
- # Ignore if it already exists
shareeView = yield self.shareeView(shareeUID)
- if shareeView is None:
- shareeView = yield self.createShare(shareeUID=shareeUID, mode=_BIND_MODE_DIRECT, shareName=shareName)
- yield shareeView.newShare()
+ if shareeView is not None and shareeView._bindMode == _BIND_MODE_GROUP:
+ yield self.updateShare(shareeView, mode=_BIND_MODE_DIRECT, status=_BIND_STATUS_ACCEPTED)
+ returnValue(shareeView)
+ else:
+ returnValue((yield super(Calendar, self).directShareWithUser(shareeUID, shareName)))
- # Check for external
- if shareeView.viewerHome().external():
- yield self._sendExternalInvite(shareeView)
- returnValue(shareeView)
-
-
@inlineCallbacks
def uninviteUIDFromShare(self, shareeUID):
"""
@@ -2061,13 +2081,14 @@
if memberUID != self._home.uid():
shareeView = yield self.shareeView(memberUID)
if shareeView is not None:
- newMode = yield shareeView._groupModeAfterRemovingOneGroupSharee()
- 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)
+ newMode = yield shareeView._groupModeAfterRemovingOneGroupSharee()
+ if newMode is None:
+ if shareeView._bindMode != _BIND_MODE_DIRECT:
+ # one group or individual share: 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)
else:
shareeView = yield self.shareeView(shareeUID)
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-16 20:30:19 UTC (rev 13765)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/test/test_sql_sharing.py 2014-07-16 23:30:52 UTC (rev 13766)
@@ -1277,6 +1277,87 @@
@inlineCallbacks
+ def test_accept_uninvite_individual_direct_and_group(self):
+ """
+ Test individual invite + group containing individual invite, accept,
+ then uninvite individual, group.
+ """
+
+ # Invite
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 0)
+ self.assertFalse(calendar.isShared())
+
+ shareeViewUser07 = yield calendar.directShareWithUser("user07")
+ self.assertNotEqual(shareeViewUser07, None)
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 1)
+ self.assertEqual(invites[0].uid, shareeViewUser07.shareUID())
+ self.assertEqual(invites[0].ownerUID, "user01")
+ self.assertEqual(invites[0].shareeUID, "user07")
+ self.assertEqual(invites[0].mode, _BIND_MODE_DIRECT)
+ self.assertEqual(invites[0].status, _BIND_STATUS_ACCEPTED)
+
+ shareeViewsGroup02 = yield calendar.inviteUIDToShare("group02", _BIND_MODE_READ)
+ self.assertEqual(len(shareeViewsGroup02), 2)
+
+ shareeViewsDict = dict([(shareeView.shareUID(), shareeView) for shareeView in shareeViewsGroup02])
+ self.assertEqual(len(shareeViewsDict), 2)
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 3)
+ for invite in invites:
+ shareeView = yield calendar.shareeView(invite.shareeUID)
+ self.assertEqual(invite.ownerUID, "user01")
+ self.assertEqual(invite.shareeUID, shareeView.viewerHome().uid())
+ self.assertEqual(invite.mode, _BIND_MODE_DIRECT if invite.shareeUID == "user07" else _BIND_MODE_GROUP)
+ self.assertEqual((yield shareeView.effectiveShareMode()), _BIND_MODE_DIRECT if invite.shareeUID == "user07" else _BIND_MODE_READ)
+ self.assertEqual(invite.status, _BIND_STATUS_ACCEPTED if invite.shareeUID == "user07" else _BIND_STATUS_INVITED)
+ self.assertEqual(invite.summary, None)
+ yield self._check_notifications(invite.shareeUID, [] if invite.shareeUID == "user07" else [invite.uid, ])
+
+ yield self.commit()
+
+ # accept
+ for invite in invites:
+ if invite.shareeUID != "user07":
+ shareeHome = yield self.homeUnderTest(name=invite.shareeUID)
+ yield shareeHome.acceptShare(invite.uid)
+
+ yield self._check_notifications("user01", [invite.uid + "-reply" for invite in invites if invite.shareeUID != "user07"])
+
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ self.assertTrue(calendar.isShared())
+
+ yield self.commit()
+
+ # Uninvite individual
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ yield calendar.uninviteUIDFromShare("user07")
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 3)
+ for invite in invites:
+ shareeView = yield calendar.shareeView(invite.shareeUID)
+ self.assertNotEqual(shareeView, None)
+ self.assertEqual(invite.uid, shareeView.shareName())
+ self.assertEqual(invite.ownerUID, "user01")
+ self.assertEqual(invite.mode, _BIND_MODE_GROUP)
+ self.assertEqual((yield shareeView.effectiveShareMode()), _BIND_MODE_READ)
+ self.assertEqual(invite.status, _BIND_STATUS_ACCEPTED)
+ self.assertEqual(invite.summary, None)
+ yield self._check_notifications(invite.shareeUID, [invite.uid, ])
+
+ # Uninvite group
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ yield calendar.uninviteUIDFromShare("group02")
+ noinvites = yield calendar.sharingInvites()
+ self.assertEqual(len(noinvites), 0)
+
+ for invite in invites:
+ self.assertEqual((yield self.calendarUnderTest(home=invite.shareeUID, name=invite.uid)), None)
+
+
+ @inlineCallbacks
def test_accept_uninvite_group_and_individual(self):
"""
Test group + individual contained in group invite, accept, then uninvite group, individual.
@@ -1329,7 +1410,6 @@
self.assertEqual(len(invites), 1)
for invite in invites:
- print("invite = %s" % (invite,))
shareeView = yield calendar.shareeView(invite.shareeUID)
self.assertNotEqual(shareeView, None)
self.assertEqual(invite.ownerUID, "user01")
@@ -1353,6 +1433,82 @@
@inlineCallbacks
+ def test_accept_uninvite_group_and_individual_direct(self):
+ """
+ Test group + individual contained in group invite, accept, then uninvite group, individual.
+ """
+
+ # Invite
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 0)
+ self.assertFalse(calendar.isShared())
+
+ shareeViewsGroup02 = yield calendar.inviteUIDToShare("group02", _BIND_MODE_READ)
+ self.assertEqual(len(shareeViewsGroup02), 3)
+ shareeViewsDict = dict([(shareeView.shareUID(), shareeView) for shareeView in shareeViewsGroup02])
+ self.assertEqual(len(shareeViewsDict), 3)
+ shareeViewUser07 = yield calendar.directShareWithUser("user07")
+ self.assertNotEqual(shareeViewUser07, None)
+
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 3)
+ for invite in invites:
+ shareeView = yield calendar.shareeView(invite.shareeUID)
+ self.assertEqual(invite.ownerUID, "user01")
+ self.assertEqual(invite.shareeUID, shareeView.viewerHome().uid())
+ self.assertEqual(invite.mode, _BIND_MODE_DIRECT if invite.shareeUID == "user07" else _BIND_MODE_GROUP)
+ self.assertEqual((yield shareeView.effectiveShareMode()), _BIND_MODE_DIRECT if invite.shareeUID == "user07" else _BIND_MODE_READ)
+ self.assertEqual(invite.status, _BIND_STATUS_ACCEPTED if invite.shareeUID == "user07" else _BIND_STATUS_INVITED)
+ self.assertEqual(invite.summary, None)
+ yield self._check_notifications(invite.shareeUID, [invite.uid, ])
+
+ yield self.commit()
+
+ # accept
+ for invite in invites:
+ if invite.shareeUID != "user07":
+ shareeHome = yield self.homeUnderTest(name=invite.shareeUID)
+ yield shareeHome.acceptShare(invite.uid)
+
+ yield self._check_notifications("user01", [invite.uid + "-reply" for invite in invites if invite.shareeUID != "user07"])
+
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ self.assertTrue(calendar.isShared())
+
+ yield self.commit()
+
+ # Uninvite group
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ yield calendar.uninviteUIDFromShare("group02")
+ invites = yield calendar.sharingInvites()
+ self.assertEqual(len(invites), 1)
+
+ for invite in invites:
+ shareeView = yield calendar.shareeView(invite.shareeUID)
+ self.assertEqual(invites[0].ownerUID, "user01")
+ self.assertNotEqual(shareeView, None)
+ self.assertEqual(invite.ownerUID, "user01")
+ self.assertEqual(invite.uid, shareeView.shareName())
+ self.assertEqual(invite.mode, _BIND_MODE_DIRECT)
+ self.assertEqual((yield shareeView.effectiveShareMode()), _BIND_MODE_DIRECT)
+ self.assertEqual(invite.status, _BIND_STATUS_ACCEPTED)
+ self.assertEqual(invite.summary, None)
+ yield self._check_notifications(invite.shareeUID, [invite.uid, ])
+
+ yield self.commit()
+
+ # Uninvite individual
+ calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+ yield calendar.uninviteUIDFromShare("user07")
+ noinvites = yield calendar.sharingInvites()
+ self.assertEqual(len(noinvites), 0)
+
+ for invite in invites:
+ self.assertEqual((yield self.calendarUnderTest(home=invite.shareeUID, name=invite.uid)), None)
+
+
+ @inlineCallbacks
def test_accept_uninvite_individual_and_groups(self):
"""
Test individual invite + 2 group containing individual invite, accept, then uninvite individual, groups.
Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql.py 2014-07-16 20:30:19 UTC (rev 13765)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql.py 2014-07-16 23:30:52 UTC (rev 13766)
@@ -62,7 +62,6 @@
from txdav.common.datastore.common import HomeChildBase
from txdav.common.datastore.podding.conduit import PoddingConduit
from txdav.common.datastore.sql_tables import _BIND_MODE_DIRECT, \
- _BIND_MODE_GROUP, _BIND_MODE_GROUP_READ, _BIND_MODE_GROUP_WRITE, \
_BIND_MODE_INDIRECT, _BIND_MODE_OWN, _BIND_STATUS_ACCEPTED, \
_BIND_STATUS_DECLINED, _BIND_STATUS_DELETED, _BIND_STATUS_INVALID, \
_BIND_STATUS_INVITED, _HOME_STATUS_EXTERNAL, _HOME_STATUS_NORMAL, \
Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py 2014-07-16 20:30:19 UTC (rev 13765)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py 2014-07-16 23:30:52 UTC (rev 13766)
@@ -31,7 +31,6 @@
from txdav.caldav.datastore.sql import CalendarStoreFeatures, ComponentUpdateState
from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
import datetime
-import hashlib
log = Logger()
@@ -244,7 +243,7 @@
rows = yield Select(
[bind.HOME_RESOURCE_ID],
From=bind,
- Where=bind.CALENDAR_RESOURCE_ID == self.calendarID.And(
+ Where=(bind.CALENDAR_RESOURCE_ID == self.calendarID).And(
bind.BIND_MODE == _BIND_MODE_OWN
),
).on(self.transaction)
@@ -252,11 +251,11 @@
homeID = rows[0][0]
home = yield self.transaction.calendarHomeWithResourceID(homeID)
calendar = yield home.childWithID(self.calendarID)
+ groupUID = ((yield self.transaction.groupByID(self.groupID)))[0]
+ yield calendar.reconcileGroupSharee(groupUID)
- yield calendar.reconcileGroupSharee(self.groupUID)
-
def diffAssignments(old, new):
"""
Compare two proxy assignment lists and return their differences in the form
@@ -384,11 +383,11 @@
groupID, membershipChanged = yield txn.refreshGroup(groupUID)
if membershipChanged:
- wps = yield self.scheduleGroupAttendeeReconciliations(txn, groupID)
- else:
- wps = ()
+ wpsAttendee = yield self.scheduleGroupAttendeeReconciliations(txn, groupID)
+ wpsShareee = yield self.scheduleGroupShareeReconciliations(txn, groupID)
+ returnValue(wpsAttendee + wpsShareee)
- returnValue(wps)
+ returnValue(tuple())
def synchronizeMembers(self, txn, groupID, newMemberUIDs):
@@ -508,4 +507,4 @@
# FIXME: is this a good place to clear out unreferenced groups?
- returnValue((delegatedUIDs | attendeeGroupUIDs | shareeGroupUIDs))
+ returnValue(frozenset(delegatedUIDs | attendeeGroupUIDs | shareeGroupUIDs))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140716/60c57a69/attachment-0001.html>
More information about the calendarserver-changes
mailing list