[CalendarServer-changes] [5728] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Jun 11 12:02:17 PDT 2010


Revision: 5728
          http://trac.macosforge.org/projects/calendarserver/changeset/5728
Author:   cdaboo at apple.com
Date:     2010-06-11 12:02:14 -0700 (Fri, 11 Jun 2010)
Log Message:
-----------
Quota handling of shared calendars.

Modified Paths:
--------------
    CalendarServer/trunk/twext/web2/dav/resource.py
    CalendarServer/trunk/twistedcaldav/resource.py

Modified: CalendarServer/trunk/twext/web2/dav/resource.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/resource.py	2010-06-11 18:58:32 UTC (rev 5727)
+++ CalendarServer/trunk/twext/web2/dav/resource.py	2010-06-11 19:02:14 UTC (rev 5728)
@@ -145,7 +145,7 @@
            #(dav_namespace, "group"                     ), # RFC 3744, section 5.2
             (dav_namespace, "supported-privilege-set"   ), # RFC 3744, section 5.3
             (dav_namespace, "current-user-privilege-set"), # RFC 3744, section 5.4
-            (dav_namespace, "current-user-principal"    ), # draft-sanchez-webdav-current-principal
+            (dav_namespace, "current-user-principal"    ), # RFC 5397, Section 3
             (dav_namespace, "acl"                       ), # RFC 3744, section 5.5
             (dav_namespace, "acl-restrictions"          ), # RFC 3744, section 5.6
             (dav_namespace, "inherited-acl-set"         ), # RFC 3744, section 5.7
@@ -171,7 +171,7 @@
 
         @return: a dict-like object from which one can read and to
             which one can write dead properties.  Keys are qname
-            tuples (ie. C{(namespace, name)}) as returned by
+            tuples (i.e. C{(namespace, name)}) as returned by
             L{davxml.WebDAVElement.qname()} and values are
             L{davxml.WebDAVElement} instances.
         """
@@ -220,7 +220,7 @@
 
             if namespace == dav_namespace:
                 if name == "resourcetype":
-                    # Allow live property to be overriden by dead property
+                    # Allow live property to be overridden by dead property
                     if self.deadProperties().contains(qname):
                         return self.deadProperties().get(qname)
                     if self.isCollection():
@@ -1055,7 +1055,7 @@
             access control list for this resource.
         """
         #
-        # The default behaviour is no ACL; we should inherrit from the parent
+        # The default behaviour is no ACL; we should inherit from the parent
         # collection.
         #
         return davxml.ACL()
@@ -1274,7 +1274,7 @@
             for.  If C{None}, it is deduced from C{request} by calling
             L{currentPrincipal}.
         @param inherited_aces: a list of L{davxml.ACE}s corresponding
-            to the precomputed inheritable aces from the parent
+            to the pre-computed inheritable aces from the parent
             resource hierarchy.
         @return: a L{Deferred} that callbacks with C{None} or errbacks
             with an L{AccessDeniedError}
@@ -1533,8 +1533,8 @@
 
     def principalsForAuthID(self, request, authid):
         """
-        Return authentication and authorization prinicipal identifiers
-        for the authentication identifer passed in. In this
+        Return authentication and authorization principal identifiers
+        for the authentication identifier passed in. In this
         implementation authn and authz principals are the same.
 
         @param request: the L{IRequest} for the request in progress.
@@ -1562,7 +1562,7 @@
     def findPrincipalForAuthID(self, authid):
         """
         Return authentication and authorization principal identifiers
-        for the authentication identifer passed in. In this
+        for the authentication identifier passed in. In this
         implementation authn and authz principals are the same.
 
         @param authid: a string containing the
@@ -1583,7 +1583,7 @@
         """
         Determine the authorization principal for the given request
         and authentication principal.  This implementation simply uses
-        aht authentication principalk as the authoization principal.
+        that authentication principal as the authorization principal.
         
         @param request: the L{IRequest} for the request in progress.
         @param authid: a string containing the
@@ -1599,7 +1599,7 @@
         
     def samePrincipal(self, principal1, principal2):
         """
-        Check whether the two prinicpals are exactly the same in terms of
+        Check whether the two principals are exactly the same in terms of
         elements and data.
 
         @param principal1: a L{Principal} to test.
@@ -1965,7 +1965,7 @@
     queried for quota information. If not found, no quota exists for
     the resource.
     
-    To determine tha actual quota in use we will cache the used byte
+    To determine that actual quota in use we will cache the used byte
     count on the quota-root collection in another private property. It
     is the servers responsibility to keep that property up to date by
     adjusting it after every PUT, DELETE, COPY, MOVE, MKCOL,
@@ -1980,7 +1980,7 @@
         Get current available & used quota values for this resource's
         quota root collection.
 
-        @return: an L{Defered} with result C{tuple} containing two
+        @return: an L{Deferred} with result C{tuple} containing two
             C{int}'s the first is quota-available-bytes, the second is
             quota-used-bytes, or C{None} if quota is not defined on
             the resource.
@@ -1993,60 +1993,45 @@
         else:
             request.quota = {}
 
-        # Check this resource first
-        if self.isCollection():
-            qroot = self.quotaRoot(request)
-            if qroot is not None:
-                def gotUsage(used):
-                    available = qroot - used
-                    if available < 0:
-                        available = 0
-                    request.quota[self] = (available, used)
-                    return (available, used)
+        # Find the quota root for this resource and return its data
+        def gotQuotaRootResource(qroot_resource):
+            if qroot_resource:
+                qroot = qroot_resource.quotaRoot(request)
+                if qroot is not None:
+                    def gotUsage(used):
+                        available = qroot - used
+                        if available < 0:
+                            available = 0
+                        request.quota[self] = (available, used)
+                        return (available, used)
+    
+                    d = qroot_resource.currentQuotaUse(request)
+                    d.addCallback(gotUsage)
+                    return d
 
-                d = self.currentQuotaUse(request)
-                d.addCallback(gotUsage)
-                return d
-        
-        # Check the next parent
-        url = request.urlForResource(self)
-        if url != "/":
-            def gotQuota(quota):
-                request.quota[self] = quota
-                return quota
-
-            d = request.locateResource(parentForURL(url))
-            d.addCallback(lambda p: p.quota(request))
-            d.addCallback(gotQuota)
-            return d
-        else:
             request.quota[self] = None
+            return None
 
-        return succeed(request.quota[self])
+            
+        d = self.quotaRootResource(request)
+        d.addCallback(gotQuotaRootResource)
+        return d
     
     def hasQuota(self, request):
         """
-        Check whether this resource is undre quota control by checking
+        Check whether this resource is under quota control by checking
         each parent to see if it has a quota root.
         
         @return: C{True} if under quota control, C{False} if not.
         """
+
+        def gotQuotaRootResource(qroot_resource):
+            
+            return qroot_resource is not None
         
-        # Check this one first
-        if self.hasQuotaRoot(request):
-            return succeed(True)
-        
-        # Look at each parent
-        try:
-            url = request.urlForResource(self)
-            if url != "/":
-                d = request.locateResource(parentForURL(url))
-                d.addCallback(lambda p: p.hasQuota(request))
-                return d
-            else:
-                return succeed(False)
-        except NoURLForResourceError:
-            return succeed(False)
+        d = self.quotaRootResource(request)
+        d.addCallback(gotQuotaRootResource)
+        return d
 
     def hasQuotaRoot(self, request):
         """
@@ -2066,15 +2051,21 @@
             return None
     
     @inlineCallbacks
-    def quotaRootParent(self, request):
+    def quotaRootResource(self, request):
         """
-        Return the next quota root above this resource.
+        Return the quota root for this resource.
         
         @return: L{DAVResource} or C{None}
         """
 
+        if self.hasQuotaRoot(request):
+            returnValue(self)
+
         # Check the next parent
-        url = request.urlForResource(self)
+        try:
+            url = request.urlForResource(self)
+        except NoURLForResourceError:
+            returnValue(None)
         while (url != "/"):
             url = parentForURL(url)
             parent = (yield request.locateResource(url))
@@ -2082,11 +2073,11 @@
                 returnValue(parent)
 
         returnValue(None)
-        
+
     def setQuotaRoot(self, request, maxsize):
         """
         @param maxsize: a C{int} containing the maximum allowed bytes
-            for the contents of this collection, or C{None} tp remove
+            for the contents of this collection, or C{None} to remove
             quota restriction.
         """
         assert self.isCollection(), "Only collections can have a quota root"
@@ -2111,7 +2102,6 @@
         """
         unimplemented(self)
 
-    @inlineCallbacks
     def checkQuota(self, request, available):
         """
         Check to see whether all quota roots have sufficient available
@@ -2125,19 +2115,20 @@
             quota roots, C{False} otherwise.
         """
         
-        quotaroot = self
-        while(quotaroot is not None):
-            # Check quota on this root (if it has one)
-            quota = quotaroot.quotaRoot(request)
-            if quota is not None:
-                if available > quota[0]:
-                    returnValue(False)
+        def _defer(quotaroot):
+            if quotaroot:
+                # Check quota on this root (if it has one)
+                quota = quotaroot.quotaRoot(request)
+                if quota is not None:
+                    if available > quota[0]:
+                        return False
+    
+            return True
 
-            # Check the next parent with a quota root
-            quotaroot = (yield quotaroot.quotaRootParent(request))
+        d = self.quotaRootResource(request)
+        d.addCallback(_defer)
+        return d
 
-        returnValue(True)
-
     def quotaSizeAdjust(self, request, adjust):
         """
         Update the quota used value on all quota root parents of this
@@ -2148,19 +2139,15 @@
             adjust the cached total.
         """
         
-        # Check this resource first
-        if self.isCollection():
-            if self.hasQuotaRoot(request):
-                return self.updateQuotaUse(request, adjust)
         
-        # Check the next parent
-        url = request.urlForResource(self)
-        if url != "/":
-            d = request.locateResource(parentForURL(url))
-            d.addCallback(lambda p: p.quotaSizeAdjust(request, adjust))
-            return d
+        def _defer(quotaroot):
+            if quotaroot:
+                # Check quota on this root (if it has one)
+                return quotaroot.updateQuotaUse(request, adjust)
 
-        return succeed(None)
+        d = self.quotaRootResource(request)
+        d.addCallback(_defer)
+        return d
 
     def currentQuotaUse(self, request):
         """

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py	2010-06-11 18:58:32 UTC (rev 5727)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2010-06-11 19:02:14 UTC (rev 5728)
@@ -1110,6 +1110,34 @@
         """
         return None 
 
+    @inlineCallbacks
+    def quotaRootResource(self, request):
+        """
+        Return the quota root for this resource.
+        
+        @return: L{DAVResource} or C{None}
+        """
+
+        sharedParent = None
+        isvirt = (yield self.isVirtualShare(request))
+        if isvirt:
+            # A virtual share's quota root is the resource owner's root
+            sharedParent = (yield request.locateResource(parentForURL(self._share.hosturl)))
+        else:
+            parent = (yield self.locateParent(request, request.urlForResource(self)))
+            if isCalendarCollectionResource(parent) or isAddressBookCollectionResource(parent):
+                isvirt = (yield parent.isVirtualShare(request))
+                if isvirt:
+                    # A virtual share's quota root is the resource owner's root
+                    sharedParent = (yield request.locateResource(parentForURL(parent._share.hosturl)))
+
+        if sharedParent:
+            result = (yield sharedParent.quotaRootResource(request))
+        else:
+            result = (yield super(CalDAVResource, self).quotaRootResource(request))
+
+        returnValue(result)
+
 class CalendarPrincipalCollectionResource (DAVPrincipalCollectionResource, CalDAVResource):
     """
     CalDAV principal collection.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100611/e74173b6/attachment-0001.html>


More information about the calendarserver-changes mailing list