[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