[CalendarServer-changes] [10726] CalendarServer/trunk/twistedcaldav/storebridge.py

source_changes at macosforge.org source_changes at macosforge.org
Thu Feb 14 09:42:23 PST 2013


Revision: 10726
          http://trac.calendarserver.org//changeset/10726
Author:   cdaboo at apple.com
Date:     2013-02-14 09:42:23 -0800 (Thu, 14 Feb 2013)
Log Message:
-----------
Fix direct sharing and managed attachments.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/storebridge.py

Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py	2013-02-14 17:40:02 UTC (rev 10725)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py	2013-02-14 17:42:23 UTC (rev 10726)
@@ -15,63 +15,63 @@
 # limitations under the License.
 ##
 
-import time
-import hashlib
-from urlparse import urlsplit
+from pycalendar.datetime import PyCalendarDateTime
 
-from twisted.python.hashlib import md5
-from twisted.python.log import err as logDefaultException
-from twisted.python.util import FancyEqMixin
-from twisted.internet.defer import succeed, inlineCallbacks, returnValue, maybeDeferred
-from twisted.internet.protocol import Protocol
-
 from twext.python.log import Logger
-
-from txdav.xml import element as davxml
-from txdav.xml.base import dav_namespace, WebDAVUnknownElement, encodeXMLName
-from txdav.base.propertystore.base import PropertyName
-from txdav.caldav.icalendarstore import QuotaExceeded, AttachmentStoreFailed, \
-    AttachmentStoreValidManagedID, AttachmentRemoveFailed, \
-    AttachmentDropboxNotAllowed
-from txdav.common.icommondatastore import NoSuchObjectResourceError
-from txdav.common.datastore.sql_tables import _BIND_MODE_READ, _BIND_MODE_WRITE
-from txdav.idav import PropertyChangeNotAllowedError
-
-from twext.web2.stream import ProducerStream, readStream, MemoryStream
-from twext.web2.http import HTTPError, StatusResponse, Response
-from twext.web2.http_headers import ETag, MimeType, MimeDisposition
 from twext.web2.dav.http import ErrorResponse, ResponseQueue, MultiStatusResponse
 from twext.web2.dav.noneprops import NonePropertyStore
 from twext.web2.dav.resource import TwistedACLInheritable, AccessDeniedError, \
     davPrivilegeSet
 from twext.web2.dav.util import parentForURL, allDataFromStream, joinURL, davXMLFromStream
-from twext.web2.responsecode import (
-    FORBIDDEN, NO_CONTENT, NOT_FOUND, CREATED, CONFLICT, PRECONDITION_FAILED,
-    BAD_REQUEST, OK, INSUFFICIENT_STORAGE_SPACE, SERVICE_UNAVAILABLE
-, INTERNAL_SERVER_ERROR)
+from twext.web2.filter.location import addLocation
+from twext.web2.http import HTTPError, StatusResponse, Response
+from twext.web2.http_headers import ETag, MimeType, MimeDisposition
+from twext.web2.responsecode import \
+    FORBIDDEN, NO_CONTENT, NOT_FOUND, CREATED, CONFLICT, PRECONDITION_FAILED, \
+    BAD_REQUEST, OK, INSUFFICIENT_STORAGE_SPACE, SERVICE_UNAVAILABLE, \
+    INTERNAL_SERVER_ERROR
+from twext.web2.stream import ProducerStream, readStream, MemoryStream
 
+from twisted.internet.defer import succeed, inlineCallbacks, returnValue, maybeDeferred
+from twisted.internet.protocol import Protocol
+from twisted.python.hashlib import md5
+from twisted.python.log import err as logDefaultException
+from twisted.python.util import FancyEqMixin
+
 from twistedcaldav import customxml, carddavxml, caldavxml
 from twistedcaldav.cache import CacheStoreNotifier, ResponseCacheMixin, \
     DisabledCacheNotifier
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.carddavxml import carddav_namespace
 from twistedcaldav.config import config
+from twistedcaldav.directory.wiki import WikiDirectoryService, getWikiAccess
 from twistedcaldav.ical import Component as VCalendar, Property as VProperty, \
     InvalidICalendarDataError, iCalendarProductID, allowedComponents
 from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
 from twistedcaldav.method.put_addressbook_common import StoreAddressObjectResource
 from twistedcaldav.method.put_common import StoreCalendarObjectResource
-from twistedcaldav.notifications import (
-    NotificationCollectionResource, NotificationResource
-)
+from twistedcaldav.notifications import NotificationCollectionResource, NotificationResource
 from twistedcaldav.resource import CalDAVResource, GlobalAddressBookResource, \
     DefaultAlarmPropertyMixin
 from twistedcaldav.scheduling.caldav.resource import ScheduleInboxResource
 from twistedcaldav.scheduling.implicit import ImplicitScheduler
 from twistedcaldav.vcard import Component as VCard, InvalidVCardDataError
-from pycalendar.datetime import PyCalendarDateTime
+
+from txdav.base.propertystore.base import PropertyName
+from txdav.caldav.icalendarstore import QuotaExceeded, AttachmentStoreFailed, \
+    AttachmentStoreValidManagedID, AttachmentRemoveFailed, \
+    AttachmentDropboxNotAllowed
+from txdav.common.datastore.sql_tables import _BIND_MODE_READ, _BIND_MODE_WRITE, \
+    _BIND_MODE_DIRECT
+from txdav.common.icommondatastore import NoSuchObjectResourceError
+from txdav.idav import PropertyChangeNotAllowedError
+from txdav.xml import element as davxml
+from txdav.xml.base import dav_namespace, WebDAVUnknownElement, encodeXMLName
+
+from urlparse import urlsplit
+import hashlib
+import time
 import uuid
-from twext.web2.filter.location import addLocation
 
 """
 Wrappers to translate between the APIs in L{txdav.caldav.icalendarstore} and
@@ -1811,7 +1811,7 @@
         All principals identified as ATTENDEEs on the event for this dropbox
         may read all its children. Also include proxies of ATTENDEEs. Ignore
         unknown attendees. Do not allow attendees to write as we don't support
-        that with managed attachments.
+        that with managed attachments. Also include sharees of the event.
         """
         originalACL = yield super(
             AttachmentsChildCollection, self).accessControlList(request, *a, **kw)
@@ -1872,24 +1872,63 @@
 
 
     @inlineCallbacks
+    def _sharedAccessControl(self, calendar, shareMode):
+        """
+        Check the shared access mode of this resource, potentially consulting
+        an external access method if necessary.
+
+        @return: a L{Deferred} firing a L{bytes} or L{None}, with one of the
+            potential values: C{"own"}, which means that the home is the owner
+            of the collection and it is not shared; C{"read-only"}, meaning
+            that the home that this collection is bound into has only read
+            access to this collection; C{"read-write"}, which means that the
+            home has both read and write access; C{"original"}, which means
+            that it should inherit the ACLs of the owner's collection, whatever
+            those happen to be, or C{None}, which means that the external
+            access control mechanism has dictate the home should no longer have
+            any access at all.
+        """
+        if shareMode in (_BIND_MODE_DIRECT,):
+            ownerUID = calendar.ownerHome().uid()
+            owner = self.principalForUID(ownerUID)
+            shareeUID = calendar.viewerHome().uid()
+            if owner.record.recordType == WikiDirectoryService.recordType_wikis:
+                # Access level comes from what the wiki has granted to the
+                # sharee
+                sharee = self.principalForUID(shareeUID)
+                userID = sharee.record.guid
+                wikiID = owner.record.shortNames[0]
+                access = (yield getWikiAccess(userID, wikiID))
+                if access == "read":
+                    returnValue("read-only")
+                elif access in ("write", "admin"):
+                    returnValue("read-write")
+                else:
+                    returnValue(None)
+            else:
+                returnValue("original")
+        elif shareMode in (_BIND_MODE_READ,):
+            returnValue("read-only")
+        elif shareMode in (_BIND_MODE_WRITE,):
+            returnValue("read-write")
+        returnValue("original")
+
+
+    @inlineCallbacks
     def sharedDropboxACEs(self):
 
         aces = ()
         calendars = yield self._newStoreCalendarObject._parentCollection.asShared()
         for calendar in calendars:
 
-            userprivs = [
+            privileges = [
+                davxml.Privilege(davxml.Read()),
+                davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
             ]
-            if calendar.shareMode() in (_BIND_MODE_READ, _BIND_MODE_WRITE,):
-                userprivs.append(davxml.Privilege(davxml.Read()))
-                userprivs.append(davxml.Privilege(davxml.ReadACL()))
-                userprivs.append(davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()))
-            if calendar.shareMode() in (_BIND_MODE_READ,):
-                userprivs.append(davxml.Privilege(davxml.WriteProperties()))
-            if calendar.shareMode() in (_BIND_MODE_WRITE,):
-                userprivs.append(davxml.Privilege(davxml.Write()))
-            proxyprivs = list(userprivs)
-            proxyprivs.remove(davxml.Privilege(davxml.ReadACL()))
+            userprivs = []
+            access = (yield self._sharedAccessControl(calendar, calendar.shareMode()))
+            if access in ("read-only", "read-write",):
+                userprivs.extend(privileges)
 
             principal = self.principalForUID(calendar._home.uid())
             aces += (
@@ -1907,17 +1946,14 @@
                     # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
                     davxml.ACE(
                         davxml.Principal(davxml.HRef(joinURL(principal.principalURL(), "calendar-proxy-read/"))),
-                        davxml.Grant(
-                            davxml.Privilege(davxml.Read()),
-                            davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
-                        ),
+                        davxml.Grant(*userprivs),
                         davxml.Protected(),
                         TwistedACLInheritable(),
                     ),
                     # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
                     davxml.ACE(
                         davxml.Principal(davxml.HRef(joinURL(principal.principalURL(), "calendar-proxy-write/"))),
-                        davxml.Grant(*proxyprivs),
+                        davxml.Grant(*userprivs),
                         davxml.Protected(),
                         TwistedACLInheritable(),
                     ),
@@ -2050,101 +2086,7 @@
         return succeed(davPrivilegeSet)
 
 
-    @inlineCallbacks
-    def accessControlList(self, request, *a, **kw):
-        """
-        Special case managed attachments, but not dropbox (which is handled by parent collection).
-        All principals identified as ATTENDEEs on the event for this attachment
-        may read it. Also include proxies of ATTENDEEs. Ignore unknown attendees.
-        """
 
-        originalACL = yield super(CalendarAttachment, self).accessControlList(request, *a, **kw)
-        if not self._managed or not self.exists():
-            returnValue(originalACL)
-        originalACEs = list(originalACL.children)
-
-        # Look at attendees
-        if self._newStoreCalendarObject is None:
-            self._newStoreCalendarObject = (yield self._newStoreAttachment.objectResource())
-
-        cuas = (yield self._newStoreCalendarObject.component()).getAttendees()
-        newACEs = []
-        for calendarUserAddress in cuas:
-            principal = self.principalForCalendarUserAddress(
-                calendarUserAddress
-            )
-            if principal is None:
-                continue
-
-            principalURL = principal.principalURL()
-            privileges = (
-                davxml.Privilege(davxml.Read()),
-                davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
-            )
-            newACEs.append(davxml.ACE(
-                davxml.Principal(davxml.HRef(principalURL)),
-                davxml.Grant(*privileges),
-                davxml.Protected(),
-            ))
-            newACEs.append(davxml.ACE(
-                davxml.Principal(davxml.HRef(joinURL(principalURL, "calendar-proxy-write/"))),
-                davxml.Grant(*privileges),
-                davxml.Protected(),
-            ))
-            newACEs.append(davxml.ACE(
-                davxml.Principal(davxml.HRef(joinURL(principalURL, "calendar-proxy-read/"))),
-                davxml.Grant(*privileges),
-                davxml.Protected(),
-            ))
-
-        # Now also need sharees
-        newACEs.extend((yield self.sharedManagedACEs()))
-
-        returnValue(davxml.ACL(*tuple(originalACEs + newACEs)))
-
-
-    @inlineCallbacks
-    def sharedManagedACEs(self):
-
-        aces = ()
-        calendars = yield self._newStoreCalendarObject._parentCollection.asShared()
-        for calendar in calendars:
-
-            read_privs = (
-                davxml.Privilege(davxml.Read()),
-                davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
-            )
-
-            principal = self.principalForUID(calendar._home.uid())
-            aces += (
-                # Specific access for the resource's associated principal.
-                davxml.ACE(
-                    davxml.Principal(davxml.HRef(principal.principalURL())),
-                    davxml.Grant(*read_privs),
-                    davxml.Protected(),
-                ),
-            )
-
-            if config.EnableProxyPrincipals:
-                aces += (
-                    # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
-                    davxml.ACE(
-                        davxml.Principal(davxml.HRef(joinURL(principal.principalURL(), "calendar-proxy-read/"))),
-                        davxml.Grant(*read_privs),
-                        davxml.Protected(),
-                    ),
-                    # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
-                    davxml.ACE(
-                        davxml.Principal(davxml.HRef(joinURL(principal.principalURL(), "calendar-proxy-write/"))),
-                        davxml.Grant(*read_privs),
-                        davxml.Protected(),
-                    ),
-                )
-
-        returnValue(aces)
-
-
-
 class NoParent(CalDAVResource):
 
     def http_MKCALENDAR(self, request):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130214/da7847a7/attachment-0001.html>


More information about the calendarserver-changes mailing list