Permalink
Browse files

Fixes for deferred support in ACL reports.

  • Loading branch information...
1 parent bc7ca44 commit 979a8f82bf208e76493bc110317397225988f230 @cyrusdaboo cyrusdaboo committed Aug 30, 2006
@@ -0,0 +1,58 @@
+Index: twisted/web2/dav/method/prop_common.py
+===================================================================
+--- twisted/web2/dav/method/prop_common.py (revision 17951)
++++ twisted/web2/dav/method/prop_common.py (working copy)
+@@ -12,6 +12,7 @@
+ "propertyListForResource",
+ ]
+
++from twisted.internet.defer import deferredGenerator, waitForDeferred
+ from twisted.python import log
+ from twisted.python.failure import Failure
+ from twisted.web2 import responsecode
+@@ -56,7 +57,9 @@
+ def responseForHref(request, responses, href, resource, propertiesForResource, propertyreq):
+
+ if propertiesForResource is not None:
+- properties_by_status = propertiesForResource(request, propertyreq, resource)
++ properties_by_status = waitForDeferred(propertiesForResource(request, propertyreq, resource))
++ yield properties_by_status
++ properties_by_status = properties_by_status.getResult()
+
+ for status in properties_by_status:
+ properties = properties_by_status[status]
+@@ -78,6 +81,8 @@
+ )
+ )
+
++responseForHref = deferredGenerator(responseForHref)
++
+ # def allPropertiesForResource(request, prop, resource):
+ # """
+ # Return all (non-hidden) properties for the specified resource.
+@@ -134,9 +139,15 @@
+ else:
+ qname = property
+
+- if qname in resource.listProperties(request):
++ props = waitForDeferred(resource.listProperties(request))
++ yield props
++ props = props.getResult()
++ if qname in props:
+ try:
+- properties_by_status[responsecode.OK].append(resource.readProperty(qname, request))
++ prop = waitForDeferred(resource.readProperty(qname, request))
++ yield prop
++ prop = prop.getResult()
++ properties_by_status[responsecode.OK].append(prop)
+ except:
+ f = Failure()
+
+@@ -149,4 +160,6 @@
+ log.err("Can't find property %r for resource %s" % (qname, request.uri))
+ properties_by_status[responsecode.NOT_FOUND].append(propertyName(qname))
+
+- return properties_by_status
++ yield properties_by_status
++
++_namedPropertiesForResource = deferredGenerator(_namedPropertiesForResource)
@@ -0,0 +1,38 @@
+Index: twisted/web2/dav/method/report.py
+===================================================================
+--- twisted/web2/dav/method/report.py (revision 17951)
++++ twisted/web2/dav/method/report.py (working copy)
+@@ -36,6 +36,7 @@
+ from twisted.web2 import responsecode
+ from twisted.web2.http import HTTPError, StatusResponse
+ from twisted.web2.dav import davxml
++from twisted.web2.dav.element.parser import lookupElement
+ from twisted.web2.dav.http import ErrorResponse
+ from twisted.web2.dav.util import davXMLFromStream
+
+@@ -99,6 +100,15 @@
+
+ try:
+ method = getattr(self, method_name)
++
++ # Also double-check via supported-reports property
++ reports = self.supportedReports()
++ test = lookupElement((namespace, name))
++ if not test:
++ raise AttributeError()
++ test = davxml.Report(test())
++ if test not in reports:
++ raise AttributeError()
+ except AttributeError:
+ #
+ # Requested report is not supported.
+@@ -111,6 +121,8 @@
+ davxml.SupportedReport()
+ ))
+
+- yield method(request, doc.root_element)
++ d = waitForDeferred(method(request, doc.root_element))
++ yield d
++ yield d.getResult()
+
+ http_REPORT = deferredGenerator(http_REPORT)
@@ -0,0 +1,47 @@
+Index: twisted/web2/dav/method/report_acl_principal_prop_set.py
+===================================================================
+--- twisted/web2/dav/method/report_acl_principal_prop_set.py (revision 17966)
++++ twisted/web2/dav/method/report_acl_principal_prop_set.py (working copy)
+@@ -53,9 +53,8 @@
+ # Depth must be "0"
+ depth = request.headers.getHeader("depth", "0")
+ if depth != "0":
+- log.err("Non-zero depth is not allowed: %s" % (depth,))
+- yield StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,))
+- return
++ log.err("Error in prinicpal-prop-set REPORT, Depth set to %s" % (depth,))
++ raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,)))
+
+ #
+ # Check authentication and access controls
+@@ -90,7 +89,9 @@
+ acl = acl.getResult()
+
+ for ace in acl.children:
+- resolved = self.resolvePrincipal(ace.principal.children[0], request)
++ resolved = waitForDeferred(self.resolvePrincipal(ace.principal.children[0], request))
++ yield resolved
++ resolved = resolved.getResult()
+ if resolved is not None and resolved not in principals:
+ principals.append(resolved)
+
+@@ -122,7 +123,7 @@
+ davxml.Status.fromResponseCode(responsecode.FORBIDDEN)
+ ))
+ else:
+- prop_common.responseForHref(
++ d = waitForDeferred(prop_common.responseForHref(
+ request,
+ responses,
+ principal,
+@@ -129,7 +130,9 @@
+ resource,
+ propertiesForResource,
+ propElement
+- )
++ ))
++ yield d
++ d.getResult()
+ else:
+ log.err("Requested principal resource not found: %s" % (str(principal),))
+ responses.append(davxml.StatusResponse(
@@ -2,21 +2,92 @@ Index: twisted/web2/dav/method/report_principal_match.py
===================================================================
--- twisted/web2/dav/method/report_principal_match.py (revision 17951)
+++ twisted/web2/dav/method/report_principal_match.py (working copy)
-@@ -104,7 +104,7 @@
- prop_common.responseForHref(
+@@ -56,8 +56,7 @@
+ depth = request.headers.getHeader("depth", "0")
+ if depth != "0":
+ log.err("Non-zero depth is not allowed: %s" % (depth,))
+- yield StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,))
+- return
++ raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,)))
+
+ # Get a single DAV:prop element from the REPORT request body
+ propertiesForResource = None
+@@ -94,7 +93,12 @@
+ if lookForPrincipals:
+ selfPrincipal = self.currentPrincipal(request).children[0]
+
+- for child, uri in self.findChildrenWithPrivileges("infinity", (davxml.Read(),), request):
++ children = []
++ d = waitForDeferred(self.findChildren("infinity", request, lambda x, y: children.append((x,y)), privileges=(davxml.Read(),)))
++ yield d
++ d.getResult()
++
++ for child, uri in children:
+ if isPrincipalResource(child) and child.principalMatch(selfPrincipal):
+ # Check size of results is within limit
+ matchcount += 1
+@@ -101,21 +105,30 @@
+ if matchcount > max_number_of_matches:
+ raise NumberOfMatchesWithinLimits
+
+- prop_common.responseForHref(
++ d = waitForDeferred(prop_common.responseForHref(
request,
responses,
- davxml.HRef.fromString(joinURL(request.uri, uri)),
+ davxml.HRef.fromString(uri),
child,
propertiesForResource,
propElement
-@@ -133,7 +133,7 @@
- prop_common.responseForHref(
+- )
++ ))
++ yield d
++ d.getResult()
+ else:
+ selfPrincipal = self.currentPrincipal(request).children[0]
+
+- for child, uri in self.findChildrenWithPrivileges("infinity", (davxml.Read(),), request):
++ children = []
++ d = waitForDeferred(self.findChildren("infinity", request, lambda x, y: children.append((x,y)), privileges=(davxml.Read(),)))
++ yield d
++ d.getResult()
++
++ for child, uri in children:
+ # Try to read the requested property from this resource
+ try:
+- prop = child.readProperty(principalPropElement.qname(), request)
++ prop = waitForDeferred(child.readProperty(principalPropElement.qname(), request))
++ yield prop
++ prop = prop.getResult()
+ if prop: prop.removeWhitespaceNodes()
+
+ if prop and len(prop.children) == 1 and isinstance(prop.children[0], davxml.HRef):
+@@ -120,7 +133,7 @@
+
+ if prop and len(prop.children) == 1 and isinstance(prop.children[0], davxml.HRef):
+ # Find principal associated with this property and test it
+- principal = waitForDeferred(self.locateResource(str(prop.children[0])))
++ principal = waitForDeferred(request.locateResource(str(prop.children[0])))
+ yield principal
+ principal = principal.getResult()
+
+@@ -130,14 +143,16 @@
+ if matchcount > max_number_of_matches:
+ raise NumberOfMatchesWithinLimits
+
+- prop_common.responseForHref(
++ d = waitForDeferred(prop_common.responseForHref(
request,
responses,
- davxml.HRef.fromString(joinURL(request.uri, uri)),
+ davxml.HRef.fromString(uri),
child,
propertiesForResource,
propElement
+- )
++ ))
++ yield d
++ d.getResult()
+ except HTTPError:
+ # Just ignore a failure to access the property. We treat this like a property that does not exist
+ # or does not match the principal.
@@ -2,12 +2,88 @@ Index: twisted/web2/dav/method/report_principal_property_search.py
===================================================================
--- twisted/web2/dav/method/report_principal_property_search.py (revision 18009)
+++ twisted/web2/dav/method/report_principal_property_search.py (working copy)
-@@ -150,7 +150,7 @@
- prop_common.responseForHref(
- request,
- responses,
+@@ -56,8 +56,7 @@
+ depth = request.headers.getHeader("depth", "0")
+ if depth != "0":
+ log.err("Error in prinicpal-property-search REPORT, Depth set to %s" % (depth,))
+- yield StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,))
+- return
++ raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,)))
+
+ # Get a single DAV:prop element from the REPORT request body
+ propertiesForResource = None
+@@ -107,15 +106,21 @@
+ # Test each property
+ for prop in props:
+ try:
+- propvalue = resource.readProperty(prop.qname(), request)
++ propvalue = waitForDeferred(resource.readProperty(prop.qname(), request))
++ yield propvalue
++ propvalue = propvalue.getResult()
+ if propvalue and not nodeMatch(propvalue, match):
+- return False
++ yield False
++ return
+ except HTTPError:
+ # No property => no match
+- return False
++ yield False
++ return
+
+- return True
+-
++ yield True
++
++ propertySearch = deferredGenerator(propertySearch)
++
+ # Run report
+ try:
+ resources = []
+@@ -140,21 +145,33 @@
+
+ # Loop over all collections and principal resources within
+ for resource, ruri in resources:
+- for child, uri in resource.findChildrenWithPrivileges("infinity", (davxml.Read(),), request):
+- if isPrincipalResource(child) and propertySearch(child, request):
+- # Check size of results is within limit
+- matchcount += 1
+- if matchcount > max_number_of_matches:
+- raise NumberOfMatchesWithinLimits
++
++ children = []
++ d = waitForDeferred(resource.findChildren("infinity", request, lambda x, y: children.append((x,y)), privileges=(davxml.Read(),)))
++ yield d
++ d.getResult()
+
+- prop_common.responseForHref(
+- request,
+- responses,
- davxml.HRef.fromString(joinURL(ruri, uri)),
-+ davxml.HRef.fromString(uri),
- child,
- propertiesForResource,
- propElement
+- child,
+- propertiesForResource,
+- propElement
+- )
++ for child, uri in children:
++ if isPrincipalResource(child):
++ d = waitForDeferred(propertySearch(child, request))
++ yield d
++ d = d.getResult()
++ if d:
++ # Check size of results is within limit
++ matchcount += 1
++ if matchcount > max_number_of_matches:
++ raise NumberOfMatchesWithinLimits
++
++ d = waitForDeferred(prop_common.responseForHref(
++ request,
++ responses,
++ davxml.HRef.fromString(uri),
++ child,
++ propertiesForResource,
++ propElement
++ ))
++ yield d
++ d.getResult()
+
+ except NumberOfMatchesWithinLimits:
+ log.err("Too many matching components in prinicpal-property-search report")
@@ -0,0 +1,38 @@
+Index: twisted/web2/dav/method/report_principal_search_property_set.py
+===================================================================
+--- twisted/web2/dav/method/report_principal_search_property_set.py (revision 17951)
++++ twisted/web2/dav/method/report_principal_search_property_set.py (working copy)
+@@ -29,11 +29,11 @@
+
+ __all__ = ["report_DAV__principal_search_property_set"]
+
++from twisted.internet.defer import deferredGenerator
+ from twisted.python import log
+ from twisted.web2 import responsecode
+ from twisted.web2.dav import davxml
+-from twisted.web2.http import Response
+-from twisted.web2.http import StatusResponse
++from twisted.web2.http import HTTPError, Response, StatusResponse
+ from twisted.web2.stream import MemoryStream
+
+ def report_DAV__principal_search_property_set(self, request, principal_search_property_set):
+@@ -49,7 +49,7 @@
+ depth = request.headers.getHeader("depth", "0")
+ if depth != "0":
+ log.err("Error in principal-search-property-set REPORT, Depth set to %s" % (depth,))
+- return StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,))
++ raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,)))
+
+ # Get details from the resource
+ result = self.principalSearchPropertySet()
+@@ -55,6 +55,8 @@
+ result = self.principalSearchPropertySet()
+ if result is None:
+ log.err("Error in principal-search-property-set REPORT not supported on: %s" % (self,))
+- return StatusResponse(responsecode.BAD_REQUEST, "Not allowed on this resource")
++ raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Not allowed on this resource"))
+
+- return Response(code=responsecode.OK, stream=MemoryStream(result.toxml()))
++ yield Response(code=responsecode.OK, stream=MemoryStream(result.toxml()))
++
++report_DAV__principal_search_property_set = deferredGenerator(report_DAV__principal_search_property_set)

0 comments on commit 979a8f8

Please sign in to comment.