[CalendarServer-changes] [13684] CalendarServer/branches/users/gaya/groupsharee2

source_changes at macosforge.org source_changes at macosforge.org
Wed Jun 25 02:28:53 PDT 2014


Revision: 13684
          http://trac.calendarserver.org//changeset/13684
Author:   gaya at apple.com
Date:     2014-06-25 02:28:53 -0700 (Wed, 25 Jun 2014)
Log Message:
-----------
more schema changes.  Most logic. (Missing group sharee access control).

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/groupsharee2/.project
    CalendarServer/branches/users/gaya/groupsharee2/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py
    CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql.py
    CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
    CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/current.sql
    CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/old/oracle-dialect/v43.sql
    CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_43_to_44.sql
    CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_43_to_44.sql
    CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_tables.py
    CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py

Modified: CalendarServer/branches/users/gaya/groupsharee2/.project
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/.project	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/.project	2014-06-25 09:28:53 UTC (rev 13684)
@@ -3,19 +3,10 @@
 	<name>CalendarServer</name>
 	<comment></comment>
 	<projects>
-		<project>CalDAVClientLibrary</project>
-		<project>cffi</project>
-		<project>psutil</project>
-		<project>pyasn1</project>
+		<project>caldavclientlibrary</project>
+		<project>kerberos</project>
 		<project>pycalendar</project>
-		<project>pycparser</project>
-		<project>pycrypto</project>
-		<project>PyGreSQL</project>
-		<project>python-ldap-2.3.13</project>
-		<project>sqlparse</project>
 		<project>twextpy</project>
-		<project>Twisted</project>
-		<project>zope.interface-4.0.3</project>
 	</projects>
 	<buildSpec>
 		<buildCommand>

Modified: CalendarServer/branches/users/gaya/groupsharee2/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/twistedcaldav/stdconfig.py	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/twistedcaldav/stdconfig.py	2014-06-25 09:28:53 UTC (rev 13684)
@@ -598,7 +598,7 @@
     "MaxBytesBatchUpload"     : 10485760, # Maximum size of a batch POST (10 MB)
 
     "Sharing": {
-        "Enabled"             : False, # Overall on/off switch
+        "Enabled"             : True, # Overall on/off switch
         "AllowExternalUsers"  : False, # External (non-principal) sharees allowed
 
         "Calendars" : {
@@ -619,6 +619,10 @@
                 "Global": [
                 ],
             },
+            "Groups" : {
+                "Enabled"     : False, # Calendar Group sharing on/off switch
+                "ReconciliationDelaySeconds" : 5,
+            },
         },
         "AddressBooks" : {
             "Enabled"         : False, # Address Book sharing on/off switch
@@ -632,7 +636,7 @@
                 ],
             },
             "Groups" : {
-                "Enabled"         : False, # Address Book Group sharing on/off switch
+                "Enabled"      : False, # Address Book Group sharing on/off switch
             },
         },
     },

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/caldav/datastore/sql.py	2014-06-25 09:28:53 UTC (rev 13684)
@@ -40,6 +40,7 @@
 from twext.python.clsprop import classproperty
 from twext.python.filepath import CachingFilePath
 from twext.python.log import Logger
+from twext.who.idirectory import RecordType
 from twistedcaldav.ical import Component as VComponent
 from txweb2.http_headers import MimeType, generateContentType
 from txweb2.stream import readStream
@@ -87,7 +88,8 @@
     CommonObjectResource, ECALENDARTYPE
 from txdav.common.datastore.sql_tables import _ATTACHMENTS_MODE_NONE, \
     _ATTACHMENTS_MODE_WRITE, schema, _BIND_MODE_OWN, \
-    _ATTACHMENTS_MODE_READ, _TRANSP_OPAQUE, _TRANSP_TRANSPARENT
+    _ATTACHMENTS_MODE_READ, _TRANSP_OPAQUE, _TRANSP_TRANSPARENT, \
+    _BIND_MODE_GROUP
 from txdav.common.icommondatastore import IndexedSearchException, \
     InternalDataStoreError, HomeChildNameAlreadyExistsError, \
     HomeChildNameNotAllowedError, ObjectResourceTooBigError, \
@@ -95,7 +97,7 @@
     ObjectResourceNameNotAllowedError, TooManyObjectResourcesError, \
     InvalidUIDError, UIDExistsError, UIDExistsElsewhereError, \
     InvalidResourceMove, InvalidComponentForStoreError, \
-    NoSuchObjectResourceError, ConcurrentModification
+    NoSuchObjectResourceError, ConcurrentModification, AllRetriesFailed
 from txdav.xml import element
 from txdav.xml.parser import WebDAVDocument
 
@@ -1753,6 +1755,147 @@
         )
 
 
+    #===============================================================================
+    # Group sharing
+    #===============================================================================
+    @inlineCallbacks
+    def shareWithUID(self, shareeUID, mode, status=None, summary=None, shareName=None):
+        """
+        Share this (owned) L{CommonHomeChild} with another principal.
+
+        @param shareeUID: The UID of the sharee.
+        @type: L{str}
+
+        @param mode: The sharing mode; L{_BIND_MODE_READ} or
+            L{_BIND_MODE_WRITE} or L{_BIND_MODE_DIRECT}
+        @type mode: L{str}
+
+        @param status: The sharing status; L{_BIND_STATUS_INVITED} or
+            L{_BIND_STATUS_ACCEPTED}
+        @type: L{str}
+
+        @param summary: The proposed message to go along with the share, which
+            will be used as the default display name.
+        @type: L{str}
+
+        @return: the name of the shared calendar in the new calendar home.
+        @rtype: L{str}
+        """
+        record = (
+            yield self._txn.directoryService().recordWithUID(shareeUID.decode("utf-8"))
+        ) if True or (
+              config.Sharing.Enabled and
+              config.Sharing.Calendars.Enabled and
+              config.Sharing.Calendars.Groups.Enabled
+        ) else None
+
+        if record is None or record.recordType != RecordType.group:
+            shareeHome = yield self._txn.calendarHomeWithUID(shareeUID, create=True)
+            returnValue(
+                (yield self.shareWith(shareeHome, mode, status, summary, shareName))
+            )
+
+        # shareWith every member of group not already shared to
+        members = yield record.expandedMembers()
+        for member in members:
+            shareeHome = yield self._txn.calendarHomeWithUID(member.uid(), create=True)
+            if (yield shareeHome.childWithID(self._resourceID)) is None:
+                yield self.shareWith(shareeHome, _BIND_MODE_GROUP, status)
+
+        yield self.updateGroupLink(shareeUID, mode)
+        returnValue(None)
+
+
+    @inlineCallbacks
+    def reconcileGroupSharee(self, groupUID):
+        """
+        reconcile bind table with group members
+        """
+        changed = False
+        if (yield self.updateShareeGroupLink, groupUID):
+            record = (
+                yield self._txn.directoryService().recordWithUID(groupUID.decode("utf-8"))
+            ) if True or (
+                  config.Sharing.Enabled and
+                  config.Sharing.Calendars.Enabled and
+                  config.Sharing.Calendars.Groups.Enabled
+            ) else None
+            members = yield record.expandedMembers() if record is not None else []
+            memberUIDs = set([member.uid() for member in members])
+            boundUIDs = set()
+
+            bind = schema.CALENDAR_BIND
+            rows = yield Select(
+                [bind.HOME_RESOURCE_ID],
+                From=bind,
+                Where=bind.CALENDAR_RESOURCE_ID == self._resourceID.And(
+                    bind.BIND_MODE == _BIND_MODE_GROUP
+                ),
+            ).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())
+                else:
+                    shareeView = yield shareeHome.childWithID(self._resourceID)
+                    yield self.removeShare(shareeView)
+                    changed = True
+
+            for member in [member for member in members if member.uid() not in boundUIDs]:
+                shareeHome = yield self._txn.calendarHomeWithUID(member.uid(), create=True)
+                if (yield shareeHome.childWithID(self._resourceID)) is None:
+                    yield self.shareWith(shareeHome, _BIND_MODE_GROUP)
+                    changed = True
+
+        returnValue(changed)
+
+
+    @inlineCallbacks
+    def updateShareeGroupLink(self, groupUID, mode=None):
+        """
+        update schema.GROUP_SHAREE
+        """
+        changed = False
+        groupID, _ignore_name, membershipHash, _ignore_modDate = yield self._txn.groupByUID(groupUID)
+
+        gs = schema.GROUP_SHAREE
+        rows = yield Select(
+            [gs.MEMBERSHIP_HASH, gs.MODE],
+            From=gs,
+            Where=gs.HOME_ID == self.ownerHome()._resourceID.And(
+                gs.CALENDAR_ID == self._resourceID).And(
+                gs.GROUP_ID == groupID)
+        ).on(self._txn)
+        if rows:
+            [[gsMembershipHash, gsMode]] = rows
+            updateMap = {}
+            if gsMembershipHash != membershipHash:
+                updateMap[gs.MEMBERSHIP_HASH] = membershipHash
+            if mode is not None and gsMode != mode:
+                updateMap[gs.GROUP_BIND_MODE] = mode
+            if updateMap:
+                yield Update(
+                    updateMap,
+                    Where=gs.HOME_ID == self.ownerHome()._resourceID.And(
+                        gs.CALENDAR_ID == self._resourceID).And(
+                        gs.GROUP_ID == groupID
+                    )
+                ).on(self._txn)
+                changed = True
+        else:
+            yield Insert({
+                gs.MEMBERSHIP_HASH: membershipHash,
+                gs.GROUP_BIND_MODE: mode,
+                gs.HOME_ID: self.ownerHome()._resourceID,
+                gs.CALENDAR_ID: self._resourceID,
+                gs.GROUP_ID: groupID,
+            }).on(self._txn)
+            changed = True
+
+        returnValue(changed)
+
+
 icalfbtype_to_indexfbtype = {
     "UNKNOWN"         : 0,
     "FREE"            : 1,

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql.py	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql.py	2014-06-25 09:28:53 UTC (rev 13684)
@@ -4703,7 +4703,35 @@
         returnValue(shareeView)
 
 
+    @inlineCallbacks
+    def shareWithUID(self, shareeUID, mode, status=None, summary=None, shareName=None):
+        """
+        Share this (owned) L{CommonHomeChild} with another principal.
 
+        @param shareeUID: The UID of the sharee.
+        @type: L{str}
+
+        @param mode: The sharing mode; L{_BIND_MODE_READ} or
+            L{_BIND_MODE_WRITE} or L{_BIND_MODE_DIRECT}
+        @type mode: L{str}
+
+        @param status: The sharing status; L{_BIND_STATUS_INVITED} or
+            L{_BIND_STATUS_ACCEPTED}
+        @type: L{str}
+
+        @param summary: The proposed message to go along with the share, which
+            will be used as the default display name.
+        @type: L{str}
+
+        @return: the name of the shared calendar in the new calendar home.
+        @rtype: L{str}
+        """
+        shareeHome = yield self._txn.calendarHomeWithUID(shareeUID, create=True)
+        returnValue(
+            (yield self.shareWith(shareeHome, mode, status, summary, shareName))
+        )
+
+
     @inlineCallbacks
     def shareWith(self, shareeHome, mode, status=None, summary=None, shareName=None):
         """

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/current-oracle-dialect.sql	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/current-oracle-dialect.sql	2014-06-25 09:28:53 UTC (rev 13684)
@@ -401,13 +401,6 @@
     "GROUP_UID" nvarchar2(255)
 );
 
-create table GROUP_ATTENDEE_RECONCILE_WORK (
-    "WORK_ID" integer primary key not null,
-    "JOB_ID" integer not null references JOB,
-    "RESOURCE_ID" integer,
-    "GROUP_ID" integer
-);
-
 create table GROUPS (
     "GROUP_ID" integer primary key,
     "NAME" nvarchar2(255),
@@ -424,6 +417,13 @@
     primary key ("GROUP_ID", "MEMBER_UID")
 );
 
+create table GROUP_ATTENDEE_RECONCILE_WORK (
+    "WORK_ID" integer primary key not null,
+    "JOB_ID" integer not null references JOB,
+    "RESOURCE_ID" integer,
+    "GROUP_ID" integer
+);
+
 create table GROUP_ATTENDEE (
     "GROUP_ID" integer not null references GROUPS on delete cascade,
     "RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
@@ -431,13 +431,20 @@
     primary key ("GROUP_ID", "RESOURCE_ID")
 );
 
+create table GROUP_SHAREE_RECONCILE_WORK (
+    "WORK_ID" integer primary key not null,
+    "JOB_ID" integer not null references JOB,
+    "CALENDAR_ID" integer not null references CALENDAR on delete cascade,
+    "GROUP_ID" integer not null references GROUPS on delete cascade
+);
+
 create table GROUP_SHAREE (
     "GROUP_ID" integer not null references GROUPS on delete cascade,
-    "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME on delete cascade,
-    "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+    "CALENDAR_HOME_ID" integer not null references CALENDAR_HOME on delete cascade,
+    "CALENDAR_ID" integer not null references CALENDAR on delete cascade,
     "GROUP_BIND_MODE" integer not null,
     "MEMBERSHIP_HASH" nvarchar2(255), 
-    primary key ("GROUP_ID", "CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID")
+    primary key ("GROUP_ID", "CALENDAR_HOME_ID", "CALENDAR_ID")
 );
 
 create table DELEGATES (
@@ -579,7 +586,7 @@
     "VALUE" nvarchar2(255)
 );
 
-insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '43');
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '44');
 insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '6');
 insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
 insert into CALENDARSERVER (NAME, VALUE) values ('NOTIFICATION-DATAVERSION', '1');
@@ -737,10 +744,6 @@
     JOB_ID
 );
 
-create index GROUP_ATTENDEE_RECONC_da73d3c2 on GROUP_ATTENDEE_RECONCILE_WORK (
-    JOB_ID
-);
-
 create index GROUPS_GROUP_UID_b35cce23 on GROUPS (
     GROUP_UID
 );
@@ -749,14 +752,22 @@
     MEMBER_UID
 );
 
-create index GROUP_ATTENDEE_RESOUR_855124dc on GROUP_ATTENDEE (
+create index GROUP_ATTENDEE_RECONC_da73d3c2 on GROUP_ATTENDEE_RECONCILE_WORK (
+    JOB_ID
+);
+
+create index GROUP_ATTENDEE_ID_d497ffdb on GROUP_ATTENDEE (
     RESOURCE_ID
 );
 
-create index GROUP_SHAREE_RESOURCE_cc288b3b on CALENDAR_BIND (
-    CALENDAR_RESOURCE_ID
+create index GROUP_SHAREE_RECONCIL_9aad0858 on GROUP_SHAREE_RECONCILE_WORK (
+    JOB_ID
 );
 
+create index GROUP_SHAREE_CALENDAR_28a88850 on GROUP_SHAREE (
+    CALENDAR_ID
+);
+
 create index DELEGATE_TO_DELEGATOR_5e149b11 on DELEGATES (
     DELEGATE,
     READ_WRITE,

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/current.sql	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/current.sql	2014-06-25 09:28:53 UTC (rev 13684)
@@ -213,7 +213,7 @@
 insert into CALENDAR_BIND_MODE values (2, 'write');
 insert into CALENDAR_BIND_MODE values (3, 'direct');
 insert into CALENDAR_BIND_MODE values (4, 'indirect');
-insert into CALENDAR_BIND_MODE values (5, 'group');			-- bind mode is determined by group bind mode. TODO: May not be needed
+insert into CALENDAR_BIND_MODE values (5, 'group');
 
 -- Enumeration of statuses
 
@@ -767,17 +767,6 @@
 create index GROUP_REFRESH_WORK_JOB_ID on
   GROUP_REFRESH_WORK(JOB_ID);
 
-create table GROUP_ATTENDEE_RECONCILE_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  JOB_ID                        integer      references JOB not null,
-  RESOURCE_ID                   integer,
-  GROUP_ID                      integer
-);
-
-create index GROUP_ATTENDEE_RECONCILE_WORK_JOB_ID on
-  GROUP_ATTENDEE_RECONCILE_WORK(JOB_ID);
-
-
 create table GROUPS (
   GROUP_ID                      integer      primary key default nextval('RESOURCE_ID_SEQ'),    -- implicit index
   NAME                          varchar(255) not null,
@@ -800,6 +789,17 @@
 create index GROUP_MEMBERSHIP_MEMBER on
   GROUP_MEMBERSHIP(MEMBER_UID);
 
+create table GROUP_ATTENDEE_RECONCILE_WORK (
+  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  JOB_ID                        integer not null references JOB,
+  RESOURCE_ID                   integer,	-- FIXME add: not null references CALENDAR_OBJECT on delete cascade,
+  GROUP_ID                      integer		-- FIXME add: not null references GROUPS on delete cascade
+);
+
+create index GROUP_ATTENDEE_RECONCILE_WORK_JOB_ID on
+  GROUP_ATTENDEE_RECONCILE_WORK(JOB_ID);
+
+  
 create table GROUP_ATTENDEE (
   GROUP_ID                      integer not null references GROUPS on delete cascade,
   RESOURCE_ID                   integer not null references CALENDAR_OBJECT on delete cascade,
@@ -807,22 +807,34 @@
   
   primary key (GROUP_ID, RESOURCE_ID)
 );
-create index GROUP_ATTENDEE_RESOURCE_ID on
+
+create index GROUP_ATTENDEE_ID on
   GROUP_ATTENDEE(RESOURCE_ID);
 
+  
+  create table GROUP_SHAREE_RECONCILE_WORK (
+  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  JOB_ID                        integer not null references JOB,
+  CALENDAR_ID                   integer	not null references CALENDAR on delete cascade,
+  GROUP_ID                      integer not null references GROUPS on delete cascade
+);
 
+create index GROUP_SHAREE_RECONCILE_WORK_JOB_ID on
+  GROUP_SHAREE_RECONCILE_WORK(JOB_ID);
+
+
 create table GROUP_SHAREE (
   GROUP_ID                      integer not null references GROUPS on delete cascade,
-  CALENDAR_HOME_RESOURCE_ID 	integer not null references CALENDAR_HOME on delete cascade,
-  CALENDAR_RESOURCE_ID      	integer not null references CALENDAR on delete cascade,
+  CALENDAR_HOME_ID 				integer not null references CALENDAR_HOME on delete cascade,
+  CALENDAR_ID      				integer not null references CALENDAR on delete cascade,
   GROUP_BIND_MODE               integer not null, -- enum CALENDAR_BIND_MODE
   MEMBERSHIP_HASH               varchar(255) not null,
   
-  primary key (GROUP_ID, CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID) -- implicit index
+  primary key (GROUP_ID, CALENDAR_HOME_ID, CALENDAR_ID)
 );
 
-create index GROUP_SHAREE_RESOURCE_ID on
-  CALENDAR_BIND(CALENDAR_RESOURCE_ID);
+create index GROUP_SHAREE_CALENDAR_ID on
+  GROUP_SHAREE(CALENDAR_ID);
 
 ---------------
 -- Delegates --
@@ -1098,7 +1110,7 @@
   VALUE                         varchar(255)
 );
 
-insert into CALENDARSERVER values ('VERSION', '43');
+insert into CALENDARSERVER values ('VERSION', '44');
 insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '6');
 insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
 insert into CALENDARSERVER values ('NOTIFICATION-DATAVERSION', '1');

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/old/oracle-dialect/v43.sql
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/old/oracle-dialect/v43.sql	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/old/oracle-dialect/v43.sql	2014-06-25 09:28:53 UTC (rev 13684)
@@ -569,7 +569,7 @@
     "VALUE" nvarchar2(255)
 );
 
-insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '44');
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '43');
 insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '6');
 insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
 insert into CALENDARSERVER (NAME, VALUE) values ('NOTIFICATION-DATAVERSION', '1');

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_43_to_44.sql
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_43_to_44.sql	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_43_to_44.sql	2014-06-25 09:28:53 UTC (rev 13684)
@@ -18,20 +18,33 @@
 -- Upgrade database schema from VERSION 43 to 44 --
 ---------------------------------------------------
 
-insert into CALENDAR_BIND_MODE values (5, 'group');			-- bind mode is determined by group bind mode. TODO: May not be needed
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('group', 5);
 
+create table GROUP_SHAREE_RECONCILE_WORK (
+  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  JOB_ID                        integer not null references JOB,
+  CALENDAR_ID                   integer	not null references CALENDAR on delete cascade,
+  GROUP_ID                      integer not null references GROUPS on delete cascade
+);
+
+create index GROUP_SHAREE_RECONCILE_WORK_JOB_ID on GROUP_SHAREE_RECONCILE_WORK(
+	JOB_ID
+);
+
+
 create table GROUP_SHAREE (
   GROUP_ID                      integer not null references GROUPS on delete cascade,
-  CALENDAR_HOME_RESOURCE_ID 	integer not null references CALENDAR_HOME on delete cascade,
-  CALENDAR_RESOURCE_ID      	integer not null references CALENDAR on delete cascade,
+  CALENDAR_HOME_ID 				integer not null references CALENDAR_HOME on delete cascade,
+  CALENDAR_ID      				integer not null references CALENDAR on delete cascade,
   GROUP_BIND_MODE               integer not null, -- enum CALENDAR_BIND_MODE
   MEMBERSHIP_HASH               varchar(255) not null,
   
-  primary key (GROUP_ID, CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID) -- implicit index
+  primary key (GROUP_ID, CALENDAR_HOME_ID, CALENDAR_ID) -- implicit index
 );
 
-create index GROUP_SHAREE_RESOURCE_ID on
-  CALENDAR_BIND(CALENDAR_RESOURCE_ID);
+create index GROUP_SHAREE_CALENDAR_ID on GROUP_SHAREE(
+	CALENDAR_ID
+);
 
 -- update the version
 update CALENDARSERVER set VALUE = '44' where NAME = 'VERSION';

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_43_to_44.sql
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_43_to_44.sql	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_43_to_44.sql	2014-06-25 09:28:53 UTC (rev 13684)
@@ -18,20 +18,31 @@
 -- Upgrade database schema from VERSION 43 to 44 --
 ---------------------------------------------------
 
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values (5, 'group');			-- bind mode is determined by group bind mode. TODO: May not be needed
+insert into CALENDAR_BIND_MODE values (5, 'group');
 
+create table GROUP_SHAREE_RECONCILE_WORK (
+  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  JOB_ID                        integer not null references JOB,
+  CALENDAR_ID                   integer	not null references CALENDAR on delete cascade,
+  GROUP_ID                      integer not null references GROUPS on delete cascade
+);
+
+create index GROUP_SHAREE_RECONCILE_WORK_JOB_ID on
+  GROUP_SHAREE_RECONCILE_WORK(JOB_ID);
+
+
 create table GROUP_SHAREE (
   GROUP_ID                      integer not null references GROUPS on delete cascade,
-  CALENDAR_HOME_RESOURCE_ID 	integer not null references CALENDAR_HOME on delete cascade,
-  CALENDAR_RESOURCE_ID      	integer not null references CALENDAR on delete cascade,
+  CALENDAR_HOME_ID 				integer not null references CALENDAR_HOME on delete cascade,
+  CALENDAR_ID      				integer not null references CALENDAR on delete cascade,
   GROUP_BIND_MODE               integer not null, -- enum CALENDAR_BIND_MODE
   MEMBERSHIP_HASH               varchar(255) not null,
   
-  primary key (GROUP_ID, CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID) -- implicit index
+  primary key (GROUP_ID, CALENDAR_HOME_ID, CALENDAR_ID) -- implicit index
 );
 
-create index GROUP_SHAREE_RESOURCE_ID on
-  CALENDAR_BIND(CALENDAR_RESOURCE_ID);
+create index GROUP_SHAREE_CALENDAR_ID on
+  GROUP_SHAREE(CALENDAR_ID);
 
-  -- update the version
+-- update the version
 update CALENDARSERVER set VALUE = '44' where NAME = 'VERSION';

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_tables.py	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/common/datastore/sql_tables.py	2014-06-25 09:28:53 UTC (rev 13684)
@@ -230,6 +230,7 @@
 _BIND_MODE_WRITE = _bindMode('write')
 _BIND_MODE_DIRECT = _bindMode('direct')
 _BIND_MODE_INDIRECT = _bindMode('indirect')
+_BIND_MODE_GROUP = _bindMode('group')
 
 
 _addressBookObjectKind = _schemaConstants(

Modified: CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py
===================================================================
--- CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py	2014-06-25 02:26:01 UTC (rev 13683)
+++ CalendarServer/branches/users/gaya/groupsharee2/txdav/who/groups.py	2014-06-25 09:28:53 UTC (rev 13684)
@@ -29,7 +29,7 @@
 from twistedcaldav.config import config
 from txdav.caldav.datastore.scheduling.icalsplitter import iCalSplitter
 from txdav.caldav.datastore.sql import CalendarStoreFeatures, ComponentUpdateState
-from txdav.common.datastore.sql_tables import schema
+from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
 import datetime
 import hashlib
 
@@ -218,6 +218,41 @@
 
 
 
+class GroupShareeReconciliationWork(
+    WorkItem, fromTable(schema.GROUP_SHAREE_RECONCILE_WORK)
+):
+
+    group = property(
+        lambda self: (self.table.CALENDAR_ID == self.calendarID)
+    )
+
+
+    @inlineCallbacks
+    def doWork(self):
+
+        # Delete all other work items for this event
+        yield Delete(
+            From=self.table,
+            Where=self.group,
+        ).on(self.transaction)
+
+        bind = schema.CALENDAR_BIND
+        rows = yield Select(
+            [bind.HOME_RESOURCE_ID],
+            From=bind,
+            Where=bind.CALENDAR_RESOURCE_ID == self.calendarID.And(
+                bind.BIND_MODE == _BIND_MODE_OWN
+            ),
+        ).on(self.transaction)
+        if rows:
+            homeID = rows[0][0]
+            home = yield self.transaction.calendarHomeWithResourceID(homeID)
+            calendar = yield home.childWithID(self.calendarID)
+
+            yield calendar.reconcileGroupSharee(self.groupUID)
+
+
+
 def diffAssignments(old, new):
     """
     Compare two proxy assignment lists and return their differences in the form
@@ -310,11 +345,11 @@
             ) in changed:
                 readDelegateGroupID = writeDelegateGroupID = None
                 if readDelegateUID:
-                    readDelegateGroupID, _ignore_name, hash, _ignore_modified = (
+                    readDelegateGroupID, _ignore_name, _ignore_hash, _ignore_modified = (
                         yield txn.groupByUID(readDelegateUID)
                     )
                 if writeDelegateUID:
-                    writeDelegateGroupID, _ignore_name, hash, _ignore_modified = (
+                    writeDelegateGroupID, _ignore_name, _ignore_hash, _ignore_modified = (
                         yield txn.groupByUID(writeDelegateUID)
                     )
                 yield txn.assignExternalDelegates(
@@ -384,7 +419,8 @@
                     newMemberUIDs.add(member.uid)
                 yield self.synchronizeMembers(txn, groupID, newMemberUIDs)
 
-                wps = yield self.scheduleEventReconciliations(txn, groupID)
+                wps = yield self.scheduleGroupAttendeeReconciliations(txn, groupID)
+                wps = wps + (yield self.scheduleGroupShareeReconciliations(txn, groupID))
 
         returnValue(wps)
 
@@ -429,7 +465,7 @@
 
 
     @inlineCallbacks
-    def scheduleEventReconciliations(self, txn, groupID):
+    def scheduleGroupAttendeeReconciliations(self, txn, groupID):
         """
         Find all events who have this groupID as an attendee and create
         work items for them.
@@ -455,22 +491,48 @@
 
 
     @inlineCallbacks
+    def scheduleGroupShareeReconciliations(self, txn, groupID):
+        """
+        Find all calendars who have shared to this groupID and create
+        work items for them.
+        returns: WorkProposal
+        """
+        gs = schema.GROUP_SHAREE
+        rows = yield Select(
+            [gs.CALENDAR_ID, ],
+            From=gs,
+            Where=gs.GROUP_ID == groupID,
+        ).on(txn)
+
+        wps = []
+        for [calendarID] in rows:
+            wp = yield GroupShareeReconciliationWork.reschedule(
+                txn,
+                seconds=float(config.Sharing.Calendar.Groups.ReconciliationDelaySeconds),
+                calendarID=calendarID,
+                groupID=groupID,
+            )
+            wps.append(wp)
+        returnValue(tuple(wps))
+
+
+    @inlineCallbacks
     def groupsToRefresh(self, txn):
         delegatedUIDs = set((yield txn.allGroupDelegates()))
         self.log.info(
             "There are {count} group delegates", count=len(delegatedUIDs)
         )
 
-        # Get groupUIDs for aoo group attendees
-        groupAttendee = schema.GROUP_ATTENDEE
+        # Get groupUIDs for all group attendees
+        ga = schema.GROUP_ATTENDEE
         gr = schema.GROUPS
         rows = yield Select(
             [gr.GROUP_UID],
             From=gr,
             Where=gr.GROUP_ID.In(
                 Select(
-                    [groupAttendee.GROUP_ID],
-                    From=groupAttendee,
+                    [ga.GROUP_ID],
+                    From=ga,
                     Distinct=True
                 )
             )
@@ -480,6 +542,25 @@
             "There are {count} group attendees", count=len(attendeeGroupUIDs)
         )
 
+        # Get groupUIDs for all group shares
+        gs = schema.GROUP_SHAREE
+        gr = schema.GROUPS
+        rows = yield Select(
+            [gr.GROUP_UID],
+            From=gr,
+            Where=gr.GROUP_ID.In(
+                Select(
+                    [gs.GROUP_ID],
+                    From=gs,
+                    Distinct=True
+                )
+            )
+        ).on(txn)
+        shareeGroupUIDs = set([row[0] for row in rows])
+        self.log.info(
+            "There are {count} group sharees", count=len(shareeGroupUIDs)
+        )
+
         # FIXME: is this a good place to clear out unreferenced groups?
 
-        returnValue(delegatedUIDs.union(attendeeGroupUIDs))
+        returnValue((delegatedUIDs | attendeeGroupUIDs | shareeGroupUIDs))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140625/c5139526/attachment-0001.html>


More information about the calendarserver-changes mailing list