[CalendarServer-changes] [10826] CalendarServer/branches/users/gaya/sharedgroups

source_changes at macosforge.org source_changes at macosforge.org
Fri Mar 1 22:22:42 PST 2013


Revision: 10826
          http://trac.calendarserver.org//changeset/10826
Author:   gaya at apple.com
Date:     2013-03-01 22:22:42 -0800 (Fri, 01 Mar 2013)
Log Message:
-----------
add per-vCard ACLs

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/migrate.py

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py	2013-03-01 20:22:14 UTC (rev 10825)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py	2013-03-02 06:22:42 UTC (rev 10826)
@@ -380,7 +380,8 @@
         @rtype: L{davxml.ACL}
         """
 
-        assert self._isShareeResource, "Only call this for a sharee collection"
+        assert self._isShareeResource, "Only call this for a sharee resource"
+        assert self.isCalendarCollection() or self.isAddressBookCollection(), "Only call this for a address book or calendar resource"
 
         sharee = self.principalForUID(self._share.shareeUID())
         access = yield self._checkAccessControl()
@@ -392,8 +393,7 @@
             returnValue(result)
 
         # Direct shares use underlying privileges of shared collection
-        userprivs = [
-        ]
+        userprivs = []
         if access in ("read-only", "read-write",):
             userprivs.append(element.Privilege(element.Read()))
             userprivs.append(element.Privilege(element.ReadACL()))
@@ -435,7 +435,7 @@
         # Give all access to config.AdminPrincipals
         aces += config.AdminACEs
 
-        if config.EnableProxyPrincipals:
+        if self.isCalendarCollection() and config.EnableProxyPrincipals:
             aces += (
                 # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
                 element.ACE(

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py	2013-03-01 20:22:14 UTC (rev 10825)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py	2013-03-02 06:22:42 UTC (rev 10826)
@@ -1734,7 +1734,7 @@
         return davxml.ACL(*aces)
 
 
-    def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
+    def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None): #@UnusedVariable
         # Permissions here are fixed, and are not subject to inheritance rules, etc.
         return succeed(self.defaultAccessControlList())
 
@@ -2958,7 +2958,69 @@
                 "Sharee cannot delete a shared group",)
             )
 
+    @inlineCallbacks
+    def accessControlList(self, request, *a, **kw):
+        """
+        Return WebDAV ACLs appropriate for the current user accessing the
+        a vcard in a shared addressbook or shared group.
+        
+        Items in an "invite" share get read-onlly privileges.
+        (It's not clear if that case ever occurs)
+        
+        "direct" shares are not supported.
 
+        @param request: the request used to locate the owner resource.
+        @type request: L{twext.web2.iweb.IRequest}
+
+        @param args: The arguments for
+            L{twext.web2.dav.idav.IDAVResource.accessControlList}
+
+        @param kwargs: The keyword arguments for
+            L{twext.web2.dav.idav.IDAVResource.accessControlList}, plus
+            keyword-only arguments.
+
+        @return: the appropriate WebDAV ACL for the sharee
+        @rtype: L{davxml.ACL}
+        """
+        if not self.exists():
+            log.debug("Resource not found: %s" % (self,))
+            raise HTTPError(NOT_FOUND)
+
+        if self._newStoreObject.addressbook().owned():
+            returnValue((yield super(AddressBookObjectResource, self).accessControlList(request, *a, **kw)))
+
+        # Direct shares use underlying privileges of shared collection
+        userprivs = []
+        userprivs.append(davxml.Privilege(davxml.Read()))
+        userprivs.append(davxml.Privilege(davxml.ReadACL()))
+        userprivs.append(davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()))
+
+        if (yield self._newStoreObject.readWriteAccess()):
+            userprivs.append(davxml.Privilege(davxml.Write()))
+        else:
+            userprivs.append(davxml.Privilege(davxml.WriteProperties()))
+
+        sharee = self.principalForUID(self._newStoreObject.viewerHome().uid())
+        aces = (
+            # Inheritable specific access for the resource's associated principal.
+            davxml.ACE(
+                davxml.Principal(davxml.HRef(sharee.principalURL())),
+                davxml.Grant(*userprivs),
+                davxml.Protected(),
+                TwistedACLInheritable(),
+            ),
+        )
+
+        # Give read access to config.ReadPrincipals
+        aces += config.ReadACEs
+
+        # Give all access to config.AdminPrincipals
+        aces += config.AdminACEs
+
+        returnValue(davxml.ACL(*aces))
+
+
+
 class _NotificationChildHelper(object):
     """
     Methods for things which are like notification objects.

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2013-03-01 20:22:14 UTC (rev 10825)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2013-03-02 06:22:42 UTC (rev 10826)
@@ -662,7 +662,6 @@
             returnValue(child)
 
         #all shared address books now
-
         rows = None
         queryCacher = home._txn._queryCacher
         ownerHome = None
@@ -892,7 +891,7 @@
 
     @classmethod
     @inlineCallbacks
-    def _objectIDsInExpandedGroupIDs(cls, txn, groupIDs, includeGroupIDs=True):
+    def expandGroupIDs(cls, txn, groupIDs, includeGroupIDs=True):
         """
         Get all AddressBookObject resource IDs contains in the given shared groups with the given groupIDs
         """
@@ -942,32 +941,32 @@
             groupBindRows = yield AddressBookObject._acceptedBindWithHomeIDAndAddressBookID.on(
                     self._txn, homeID=self._home._resourceID, addressbookID=self._resourceID
             )
-            readwriteGroupIDs = []
-            readonlyGroupIDs = []
+            readWriteGroupIDs = []
+            readOnlyGroupIDs = []
             for bindMode, homeID, resourceID, bindName, bindStatus, bindMessage in groupBindRows: #@UnusedVariable
                 if bindMode == _BIND_MODE_WRITE:
-                    readwriteGroupIDs.append(resourceID)
+                    readWriteGroupIDs.append(resourceID)
                 else:
-                    readonlyGroupIDs.append(resourceID)
+                    readOnlyGroupIDs.append(resourceID)
 
-            if readonlyGroupIDs and readwriteGroupIDs:
+            if readOnlyGroupIDs and readWriteGroupIDs:
                 # expand read-write groups and remove any subgroups from read-only group list
-                allWriteableIDs = yield self._objectIDsInExpandedGroupIDs(self._txn, readwriteGroupIDs)
-                adjustedReadOnlyGroupIDs = set(readonlyGroupIDs) - set(allWriteableIDs)
-                adjustedReadWriteGroupIDs = set(readwriteGroupIDs) | (set(readonlyGroupIDs) - adjustedReadOnlyGroupIDs)
+                allWriteableIDs = yield self.expandGroupIDs(self._txn, readWriteGroupIDs)
+                adjustedReadOnlyGroupIDs = set(readOnlyGroupIDs) - set(allWriteableIDs)
+                adjustedReadWriteGroupIDs = set(readWriteGroupIDs) | (set(readOnlyGroupIDs) - adjustedReadOnlyGroupIDs)
             else:
-                adjustedReadOnlyGroupIDs = readonlyGroupIDs
-                adjustedReadWriteGroupIDs = readwriteGroupIDs
+                adjustedReadOnlyGroupIDs = readOnlyGroupIDs
+                adjustedReadWriteGroupIDs = readWriteGroupIDs
             returnValue((tuple(adjustedReadOnlyGroupIDs), tuple(adjustedReadWriteGroupIDs)))
 
-
+    '''
     @inlineCallbacks
-    def readonlyGroupIDs(self):
+    def readOnlyGroupIDs(self):
         returnValue((yield self.accessControlGroupIDs())[0])
-        
-        
+    '''
+
     @inlineCallbacks
-    def writeableGroupIDs(self):
+    def readWriteGroupIDs(self):
         returnValue((yield self.accessControlGroupIDs())[1])
 
 
@@ -1244,9 +1243,9 @@
             # convert delete in sharee shared group address book to remove of memberships
             # that make this object visible to the sharee
 
-            writeableGroupIDs = yield self._addressbook.writeableGroupIDs()
-            if writeableGroupIDs:
-                objectsIDs = yield self._addressbook._objectIDsInExpandedGroupIDs(self._txn, writeableGroupIDs)
+            readWriteGroupIDs = yield self._addressbook.readWriteGroupIDs()
+            if readWriteGroupIDs:
+                objectsIDs = yield self._addressbook.expandGroupIDs(self._txn, readWriteGroupIDs)
                 yield self._deleteMembersWithMemberIDAndGroupIDsQuery(self._resourceID, objectsIDs).on(
                     self._txn, groupIDs=objectsIDs
                 )
@@ -1278,6 +1277,22 @@
             self._component = None
 
 
+    @inlineCallbacks
+    def readWriteAccess(self):
+        assert not self.owned(), "Don't call items in owned address book"
+
+        # if fully shared and rw, must be RW since sharing group read-only has no affect
+        if self._addressbook.fullyShared() and self._addressbook.shareMode() == _BIND_MODE_WRITE:
+            yield None
+            returnValue(True)
+
+        readWriteGroupIDs = yield self._addressbook.readWriteGroupIDs()
+        if self._resourceID in (yield self._addressbook.expandGroupIDs(self._txn, readWriteGroupIDs)):
+            returnValue(True)
+
+        returnValue(False)
+
+
     @classmethod
     def _allColumnsWithResourceIDsAnd(cls, resourceIDs, column, paramName):
         """
@@ -1350,7 +1365,7 @@
                         rows = [(yield self._addressbook._groupForEntireAB_Row())]
         else:
             acceptedGroupIDs = yield self._addressbook.acceptedGroupIDs()
-            allowedObjectIDs = yield self._addressbook._objectIDsInExpandedGroupIDs(self._txn, acceptedGroupIDs)
+            allowedObjectIDs = yield self._addressbook.expandGroupIDs(self._txn, acceptedGroupIDs)
             if self._name:
                 if allowedObjectIDs:
                     rows = (yield self._allColumnsWithResourceIDsAndName(allowedObjectIDs).on(
@@ -1400,14 +1415,6 @@
             returnValue(None)
 
 
-    @inlineCallbacks
-    def _objectIDsInExpandedGroup(self):
-        """
-        Get all AddressBookObject resource IDs contained in this shared group
-        """
-        returnValue((yield self._addressbook._objectIDsInExpandedGroupIDs(self._txn, [self._resourceID])))
-
-
     @classproperty
     def _allColumns(cls): #@NoSelf
         """
@@ -1463,7 +1470,7 @@
                 rows.append((yield addressbook._groupForEntireAB_Row()))
         else:
             acceptedGroupIDs = addressbook.acceptedGroupIDs()
-            allowedObjectIDs = yield addressbook._objectIDsInExpandedGroupIDs(addressbook._txn, acceptedGroupIDs)
+            allowedObjectIDs = yield addressbook.expandGroupIDs(addressbook._txn, acceptedGroupIDs)
             rows = yield cls._columnsWithResourceIDsQuery(cls._allColumns, allowedObjectIDs).on(
                 addressbook._txn, resourceIDs=allowedObjectIDs
             )
@@ -1488,7 +1495,7 @@
                 rows.append((yield addressbook._groupForEntireAB_Row()))
         else:
             acceptedGroupIDs = addressbook.acceptedGroupIDs()
-            allowedObjectIDs = yield addressbook._objectIDsInExpandedGroupIDs(addressbook._txn, acceptedGroupIDs)
+            allowedObjectIDs = yield addressbook.expandGroupIDs(addressbook._txn, acceptedGroupIDs)
             rows = yield cls._allColumnsWithResourceIDsAndNamesQuery(allowedObjectIDs, names).on(
                 addressbook._txn, resourceIDs=allowedObjectIDs, names=names
             )
@@ -1631,7 +1638,7 @@
                         raise GroupWithUnsharedAddressNotAllowedError
 
                     acceptedGroupIDs = yield self._addressbook.acceptedGroupIDs()
-                    allowedObjectIDs = yield self._addressbook._objectIDsInExpandedGroupIDs(self._txn, acceptedGroupIDs)
+                    allowedObjectIDs = yield self._addressbook.expandGroupIDs(self._txn, acceptedGroupIDs)
                     if set(memberIDs) - set(allowedObjectIDs):
                         raise GroupWithUnsharedAddressNotAllowedError
 
@@ -1694,12 +1701,12 @@
             ).on(self._txn)
             groupIDs = [groupIDRow[0] for groupIDRow in groupIDRows]
 
-            # FIXME: Is this correct?
+            # FIXME: Is this correct? Write test case
             if not self.owned():
                 if not self._addressbook.fullyShared() or self._addressbook.shareMode() != _BIND_MODE_WRITE:
-                    writeableGroupIDs = yield self._addressbook.writeableGroupIDs()
-                    assert writeableGroupIDs, "no access"
-                    groupIDs.extend(writeableGroupIDs)
+                    readWriteGroupIDs = yield self._addressbook.readWriteGroupIDs()
+                    assert readWriteGroupIDs, "no access"
+                    groupIDs.extend(readWriteGroupIDs)
 
             # add to member table rows
             for groupID in groupIDs:

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py	2013-03-01 20:22:14 UTC (rev 10825)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py	2013-03-02 06:22:42 UTC (rev 10826)
@@ -3104,16 +3104,27 @@
         """
         rows = yield cls._bindForResourceIDAndHomeID.on(
             home._txn, resourceID=resourceID, homeID=home._resourceID)
-        if rows:
-            bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = rows[0] #@UnusedVariable
-            if bindStatus == _BIND_STATUS_ACCEPTED:
-                returnValue((yield home.childWithName(resourceName)))
-            else:
-                returnValue((yield cls.objectWithName(home, resourceName, accepted=False)))
+        if not rows:
+            returnValue(None)
 
-        returnValue(None)
+        bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = rows[0] #@UnusedVariable
 
+        if bindMode == _BIND_MODE_OWN:
+            ownerHome = home
+        else:
+            ownerHomeID = (yield cls._ownerHomeWithResourceID.on(
+                            home._txn, resourceID=resourceID))[0][0]
+            ownerHome = yield home._txn.homeWithResourceID(home._homeType, ownerHomeID)
+        child = cls(
+            home=home,
+            name=resourceName, resourceID=resourceID,
+            mode=bindMode, status=bindStatus,
+            message=bindMessage, ownerHome=ownerHome,
+        )
+        yield child.initFromStore()
+        returnValue(child)
 
+
     @classproperty
     def _insertHomeChild(cls): #@NoSelf
         """

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/migrate.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/migrate.py	2013-03-01 20:22:14 UTC (rev 10825)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/migrate.py	2013-03-02 06:22:42 UTC (rev 10826)
@@ -409,8 +409,7 @@
 
         for homeType, eachFunc in [
                 ("calendar", self.fileStore.withEachCalendarHomeDo),
-                # FIXME:
-                # ("addressbook", self.fileStore.withEachAddressbookHomeDo),
+                ("addressbook", self.fileStore.withEachAddressbookHomeDo),
             ]:
             yield eachFunc(
                 lambda txn, home: self._upgradeAction(
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130301/08d46a61/attachment-0001.html>


More information about the calendarserver-changes mailing list