[CalendarServer-changes] [395]
CalendarServer/branches/users/wsanchez/provisioning
source_changes at macosforge.org
source_changes at macosforge.org
Tue Nov 7 20:48:25 PST 2006
Revision: 395
http://trac.macosforge.org/projects/calendarserver/changeset/395
Author: wsanchez at apple.com
Date: 2006-11-07 20:48:25 -0800 (Tue, 07 Nov 2006)
Log Message:
-----------
Pull up patches from trunk
Modified Paths:
--------------
CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.dav.resource.patch
CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.dav.static.patch
CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.server.patch
CalendarServer/branches/users/wsanchez/provisioning/twistedcaldav/directory/appleopendirectory.py
CalendarServer/branches/users/wsanchez/provisioning/twistedcaldav/directory/resource.py
Modified: CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.dav.resource.patch
===================================================================
--- CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.dav.resource.patch 2006-11-08 04:47:22 UTC (rev 394)
+++ CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.dav.resource.patch 2006-11-08 04:48:25 UTC (rev 395)
@@ -26,7 +26,7 @@
return succeed(qname in self.liveProperties or self.deadProperties().contains(qname))
def readProperty(self, property, request):
-@@ -286,6 +296,32 @@
+@@ -286,7 +296,33 @@
d.addCallback(gotACL)
return d
return ifAllowed((davxml.ReadACL(),), callback)
@@ -43,7 +43,7 @@
+ d = self.quota(request)
+ d.addCallback(callback)
+ return d
-+
+
+ if name == "quota-used-bytes":
+ def callback(qvalue):
+ if qvalue is None:
@@ -56,10 +56,11 @@
+ d = self.quota(request)
+ d.addCallback(callback)
+ return d
-
++
elif namespace == twisted_dav_namespace:
if name == "resource-class":
-@@ -366,6 +402,18 @@
+ class ResourceClass (davxml.WebDAVTextElement):
+@@ -366,12 +402,26 @@
# FIXME: A set would be better here, that that's a python 2.4+ feature.
qnames = list(self.liveProperties)
@@ -78,27 +79,76 @@
for qname in self.deadProperties().list():
if (qname not in qnames) and (qname[0] != twisted_private_namespace):
qnames.append(qname)
-@@ -370,7 +418,9 @@
- if (qname not in qnames) and (qname[0] != twisted_private_namespace):
- qnames.append(qname)
- return succeed(qnames)
+ yield qnames
+
++ listProperties = deferredGenerator(listProperties)
+
-+ listProperties = deferredGenerator(listProperties)
-
def listAllprop(self, request):
"""
-@@ -535,7 +585,7 @@
+ Some DAV properties should not be returned to a C{DAV:allprop} query.
+@@ -509,6 +559,9 @@
+ reactor.callLater(0, getChild)
+
+ def checkPrivileges(child):
++ if child is None:
++ return None
++
+ if privileges is None:
+ return child
+
+@@ -517,14 +570,17 @@
+ return d
+
+ def gotChild(child, childpath):
+- if child.isCollection():
+- callback(child, childpath + "/")
+- if depth == "infinity":
+- d = child.findChildren(depth, request, callback, privileges)
+- d.addCallback(lambda x: reactor.callLater(0, getChild))
+- return d
++ if child is None:
++ callback(None, childpath + "/")
+ else:
+- callback(child, childpath)
++ if child.isCollection():
++ callback(child, childpath + "/")
++ if depth == "infinity":
++ d = child.findChildren(depth, request, callback, privileges)
++ d.addCallback(lambda x: reactor.callLater(0, getChild))
++ return d
++ else:
++ callback(child, childpath)
+
+ reactor.callLater(0, getChild)
+
+@@ -535,10 +591,11 @@
completionDeferred.callback(None)
else:
childpath = joinURL(basepath, childname)
- child = request.locateResource(childpath)
-+ child = request.locateChildResource(self, childname)
- child.addCallback(checkPrivileges)
- child.addCallbacks(gotChild, checkPrivilegesError, (childpath,))
- child.addErrback(completionDeferred.errback)
-@@ -574,9 +624,9 @@
+- child.addCallback(checkPrivileges)
+- child.addCallbacks(gotChild, checkPrivilegesError, (childpath,))
+- child.addErrback(completionDeferred.errback)
++ print "*"*10, childname, childpath
++ d = request.locateChildResource(self, childname)
++ d.addCallback(checkPrivileges)
++ d.addCallbacks(gotChild, checkPrivilegesError, (childpath,))
++ d.addErrback(completionDeferred.errback)
+
+ getChild()
+
+@@ -564,7 +621,7 @@
+ See L{IDAVResource.authorize}.
+ """
+ def onError(failure):
+- log.err("Invalid authentication details: %s" % (request,))
++ log.err("Invalid authentication details: %s" % (failure,))
+ raise HTTPError(UnauthorizedResponse(
+ request.credentialFactories,
+ request.remoteAddr
+@@ -574,9 +631,9 @@
def onErrors(failure):
failure.trap(AccessDeniedError)
@@ -110,8 +160,16 @@
response = UnauthorizedResponse(request.credentialFactories,
request.remoteAddr)
else:
-@@ -600,8 +650,13 @@
+@@ -594,22 +651,29 @@
+ return d
+ d = maybeDeferred(self.authenticate, request)
+- d.addCallbacks(onAuth, onError)
++ d.addCallback(onAuth)
++ d.addErrback(onError)
+
+ return d
+
def authenticate(self, request):
def loginSuccess(result):
- request.user = result[1]
@@ -126,7 +184,6 @@
if not (
hasattr(request, 'portal') and
-@@ -608,8 +663,9 @@
hasattr(request, 'credentialFactories') and
hasattr(request, 'loginInterfaces')
):
@@ -138,7 +195,7 @@
authHeader = request.headers.getHeader('authorization')
-@@ -625,9 +681,11 @@
+@@ -625,9 +689,11 @@
# Try to match principals in each principal collection on the resource
def gotDetails(details):
@@ -153,7 +210,7 @@
def login(pcreds):
d = request.portal.login(pcreds, None, *request.loginInterfaces)
-@@ -635,7 +693,7 @@
+@@ -635,13 +701,14 @@
return d
@@ -162,9 +219,6 @@
d.addCallback(gotDetails).addCallback(login)
return d
-@@ -640,8 +698,9 @@
-
- return d
else:
- request.user = davxml.Principal(davxml.Unauthenticated())
- return request.user
@@ -174,7 +228,7 @@
##
# ACL
-@@ -650,10 +709,10 @@
+@@ -650,10 +717,10 @@
def currentPrincipal(self, request):
"""
@param request: the request being processed.
@@ -188,8 +242,60 @@
else:
return unauthenticatedPrincipal
-@@ -1149,8 +1208,12 @@
+@@ -666,32 +733,26 @@
+ present on this resource, it tries to get it from the parent, unless it
+ is the root or has no parent.
+ """
+- try:
+- principalCollections = self.readDeadProperty(davxml.PrincipalCollectionSet).childrenOfType(davxml.HRef)
+- except HTTPError, e:
+- if e.response.code != responsecode.NOT_FOUND:
+- raise
++ if self.hasDeadProperty(davxml.PrincipalCollectionSet):
++ return succeed([
++ str(href) for href in
++ self.readDeadProperty(davxml.PrincipalCollectionSet).childrenOfType(davxml.HRef)
++ ])
+- principalCollections = []
++ myURL = request.urlForResource(self)
++ if myURL == "/":
++ return succeed(())
+
+- # Try the parent
+- myURL = request.urlForResource(self)
+- if myURL != "/":
+- parentURL = parentForURL(myURL)
++ def gotParent(parent):
++ if parent is None:
++ return ()
++ else:
++ return parent.principalCollections(request)
+
+- parent = waitForDeferred(request.locateResource(parentURL))
+- yield parent
+- parent = parent.getResult()
++ d = request.locateResource(parentForURL(myURL))
++ d.addCallback(gotParent)
++ return d
+
+- if parent:
+- principalCollections = waitForDeferred(parent.principalCollections(request))
+- yield principalCollections
+- principalCollections = principalCollections.getResult()
+-
+- yield principalCollections
+-
+- principalCollections = deferredGenerator(principalCollections)
+-
+ def defaultAccessControlList(self):
+ """
+ @return: the L{davxml.ACL} element containing the default access control
+@@ -1146,49 +1207,95 @@
+
+ This implementation returns an empty set.
+ """
+-
return []
- def findPrincipalForAuthID(self, request, authid):
@@ -202,9 +308,6 @@
@param request: the L{IRequest} for the request in progress.
@param authid: a string containing the
authentication/authorization identifier for the principal
-@@ -1155,12 +1218,55 @@
- @param authid: a string containing the
- authentication/authorization identifier for the principal
to lookup.
- @return: a deferred tuple of C{(principal, principalURI)}
- where: C{principal} is the L{Principal} that is found;
@@ -217,33 +320,25 @@
It will errback with an HTTPError(responsecode.FORBIDDEN) if
the principal isn't found.
"""
++ def gotAuthn(principal):
++ if principal is None:
++ log.msg("Could not find principal matching user id: %s" % (authid,))
++ raise HTTPError(responsecode.FORBIDDEN)
+
-+ # Try to match principals in each principal collection on the resource
-+ d = waitForDeferred(self.findPrincipalForAuthID(request, authid))
-+ yield d
-+ result = d.getResult()
-+
-+ if result is not None:
-+ authnPrincipal = result[0]
-+ authnURI = result[1]
-+ d = waitForDeferred(self.authorizationPrincipal(request, authid, authnPrincipal, authnURI))
-+ yield d
-+ authzPrincipal, authzURI = d.getResult()
-+ yield ((authnPrincipal, authnURI), (authzPrincipal, authzURI),)
-+ return
-+ else:
-+ principalCollections = waitForDeferred(self.principalCollections(request))
-+ yield principalCollections
-+ principalCollections = principalCollections.getResult()
++ authnPrincipal, authnURI = principal
+
-+ if len(principalCollections) == 0:
-+ log.msg("DAV:principal-collection-set property cannot be found on the resource being authorized: %s" % self)
-+ else:
-+ log.msg("Could not find principal matching user id: %s" % authid)
-+ raise HTTPError(responsecode.FORBIDDEN)
++ def gotAuthz(principal):
++ authzPrincipal, authzURI = principal
++ return ((authnPrincipal, authnURI), (authzPrincipal, authzURI))
+
-+ principalsForAuthID = deferredGenerator(principalsForAuthID)
++ d = self.authorizationPrincipal(request, authid, authnPrincipal, authnURI)
++ d.addCallback(gotAuthz)
++ return d
+
++ d = self.findPrincipalForAuthID(request, authid)
++ d.addCallback(gotAuthn)
++ return d
++
+ def findPrincipalForAuthID(self, request, authid):
+ """
+ Return authentication and authoirization prinicipal identifiers for the
@@ -261,7 +356,13 @@
# Try to match principals in each principal collection on the resource
collections = waitForDeferred(self.principalCollections(request))
yield collections
-@@ -1173,22 +1279,30 @@
+ collections = collections.getResult()
+
+ for collection in collections:
+- principalURI = joinURL(str(collection), authid)
++ principalURI = joinURL(collection, authid)
+
+ principal = waitForDeferred(request.locateResource(principalURI))
yield principal
principal = principal.getResult()
@@ -274,15 +375,15 @@
- principalCollections = waitForDeferred(self.principalCollections(request))
- yield principalCollections
- principalCollections = principalCollections.getResult()
--
++ yield None
++ return
+
- if len(principalCollections) == 0:
- log.msg("DAV:principal-collection-set property cannot be found on the resource being authorized: %s" % self)
- else:
- log.msg("Could not find principal matching user id: %s" % authid)
- raise HTTPError(responsecode.FORBIDDEN)
-+ yield None
-+ return
-
+-
findPrincipalForAuthID = deferredGenerator(findPrincipalForAuthID)
+ def authorizationPrincipal(self, request, authid, authnPrincipal, authnURI):
@@ -303,7 +404,7 @@
def samePrincipal(self, principal1, principal2):
"""
Check whether the two prinicpals are exactly the same in terms of
-@@ -1511,6 +1625,265 @@
+@@ -1511,6 +1618,265 @@
return None
##
@@ -569,7 +670,7 @@
# HTTP
##
-@@ -1558,7 +1931,7 @@
+@@ -1558,7 +1924,7 @@
"""
DAV resource with no children.
"""
@@ -578,7 +679,7 @@
return succeed(None)
class DAVPrincipalResource (DAVLeafResource):
-@@ -1712,6 +2085,37 @@
+@@ -1712,6 +2078,37 @@
davxml.registerElement(TwistedACLInheritable)
davxml.ACE.allowed_children[(twisted_dav_namespace, "inheritable")] = (0, 1)
Modified: CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.dav.static.patch
===================================================================
--- CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.dav.static.patch 2006-11-08 04:47:22 UTC (rev 394)
+++ CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.dav.static.patch 2006-11-08 04:48:25 UTC (rev 395)
@@ -96,12 +96,94 @@
# Workarounds for issues with File
##
-@@ -164,7 +213,7 @@
- children = []
+@@ -142,53 +191,50 @@
+ directory contents that they have read permissions for.
+ """
+ if not self.fp.exists():
+- yield responsecode.NOT_FOUND
+- return
++ return responsecode.NOT_FOUND
- def found(request, uri):
+- if self.fp.isdir():
+- if request.uri[-1] != "/":
+- # Redirect to include trailing '/' in URI
+- yield RedirectResponse(
+- request.unparseURL(path=request.path+'/'))
+- return
+- else:
+- ifp = self.fp.childSearchPreauth(*self.indexNames)
+- if ifp:
+- # Render from the index file
+- standin = self.createSimilarFile(ifp.path)
+- else:
+- filtered_aces = waitForDeferred(self.inheritedACEsforChildren(request))
+- yield filtered_aces
+- filtered_aces = filtered_aces.getResult()
++ if not self.fp.isdir():
++ # Do regular resource behavior from superclass
++ return super(DAVFile, self).render(request)
+
+- children = []
++ #
++ # Do custom rendering of directory so that we can enforce ACLs.
++ #
+
+- def found(request, uri):
- children.append(uri.split("/")[-1].rstrip("/"))
-+ children.append(uri.rstrip("/").split("/")[-1])
++ if request.uri[-1] != "/":
++ # Redirect to include trailing '/' in URI
++ return RedirectResponse(request.unparseURL(path=request.path+'/'))
- x = waitForDeferred(
- self.findChildren("1", request, found, (davxml.Read(),),
+- x = waitForDeferred(
+- self.findChildren("1", request, found, (davxml.Read(),),
+- inherited_aces=filtered_aces)
+- )
+- yield x
+- x = x.getResult()
++ # Render from the index file, if we have one
++ index_fp = self.fp.childSearchPreauth(*self.indexNames)
++ if index_fp:
++ return self.createSimilarFile(index_fp.path).render(request)
+
+- # Render from a DirectoryLister
+- standin = dirlist.DirectoryLister(
+- self.fp.path,
+- children,
+- self.contentTypes,
+- self.contentEncodings,
+- self.defaultType
+- )
+- yield standin.render(request)
+- return
++ # Render from a DirectoryLister
++ def findChildren(filtered_aces):
++ children = []
+
+- # Do regular resource behavior from superclass
+- yield super(DAVFile, self).render(request)
+-
+- render = deferredGenerator(render)
++ def found(request, uri):
++ children.append(uri.rstrip("/").split("/")[-1])
+
++ d = self.findChildren("1", request, found,
++ (davxml.Read(),), inherited_aces=filtered_aces)
++ d.addCallback(render, children)
++ return d
++
++ def render(_, children):
++ return dirlist.DirectoryLister(
++ self.fp.path,
++ children,
++ self.contentTypes,
++ self.contentEncodings,
++ self.defaultType
++ ).render(request)
++
++ d = self.inheritedACEsforChildren(request)
++ d.addCallback(findChildren)
++ return d
++
+ #
+ # Attach method handlers to DAVFile
+ #
Modified: CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.server.patch
===================================================================
--- CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.server.patch 2006-11-08 04:47:22 UTC (rev 394)
+++ CalendarServer/branches/users/wsanchez/provisioning/lib-patches/Twisted/twisted.web2.server.patch 2006-11-08 04:48:25 UTC (rev 395)
@@ -2,15 +2,7 @@
===================================================================
--- twisted/web2/server.py (revision 18545)
+++ twisted/web2/server.py (working copy)
-@@ -19,6 +19,7 @@
- from zope.interface import implements
- # Twisted Imports
- from twisted.internet import defer
-+from twisted.internet.defer import succeed
- from twisted.python import log, failure
-
- # Sibling Imports
-@@ -26,6 +27,7 @@
+@@ -26,6 +26,7 @@
from twisted.web2 import http_headers
from twisted.web2.filter.range import rangefilter
from twisted.web2 import error
@@ -18,7 +10,7 @@
from twisted.web2 import version as web2_version
from twisted import __version__ as twisted_version
-@@ -150,6 +152,9 @@
+@@ -150,17 +151,32 @@
self._initialprepath = kw['prepathuri']
del kw['prepathuri']
@@ -28,7 +20,6 @@
# Copy response filters from the class
self.responseFilters = self.responseFilters[:]
self.files = {}
-@@ -156,11 +161,23 @@
self.resources = []
http.Request.__init__(self, *args, **kw)
@@ -55,7 +46,7 @@
def unparseURL(self, scheme=None, host=None, port=None,
path=None, params=None, querystring=None, fragment=None):
-@@ -265,6 +282,7 @@
+@@ -265,6 +281,7 @@
d = defer.Deferred()
d.addCallback(self._getChild, self.site.resource, self.postpath)
@@ -63,7 +54,7 @@
d.addCallback(lambda res, req: res.renderHTTP(req), self)
d.addCallback(self._cbFinishRender)
d.addErrback(self._processingFailed)
-@@ -320,8 +338,6 @@
+@@ -320,8 +337,6 @@
url = "/" + "/".join(path)
else:
url = "/"
@@ -72,7 +63,7 @@
return res
#else:
# raise ValueError("locateChild must not return StopTraversal with a resource other than self.")
-@@ -342,17 +358,16 @@
+@@ -342,17 +357,16 @@
self.prepath.append(self.postpath.pop(0))
child = self._getChild(None, newres, newpath, updatepaths=updatepaths)
@@ -94,7 +85,7 @@
def urlForResource(self, resource):
"""
-@@ -367,10 +382,7 @@
+@@ -367,10 +381,7 @@
@return: the URL of C{resource} if known, otherwise C{None}.
"""
@@ -106,21 +97,22 @@
def locateResource(self, url):
"""
-@@ -385,7 +397,12 @@
+@@ -385,8 +396,13 @@
The contained response will have a status code of
L{responsecode.BAD_REQUEST}.
"""
- if url is None: return None
+ if url is None:
-+ return None
-+
++ return defer.succeed(None)
+
+ cached = self._urlsByResource.get(url, None)
+ if cached is not None:
-+ return succeed(cached)
-
++ return defer.succeed(cached)
++
#
# Parse the URL
-@@ -406,10 +423,50 @@
+ #
+@@ -406,19 +422,66 @@
"URL is not on this site (%s://%s/): %s" % (scheme, self.headers.getHeader("host"), url)
))
@@ -129,18 +121,20 @@
assert segments[0] == "", "URL path didn't begin with '/': %s" % (path,)
segments = segments[1:]
- segments = map(unquote, segments)
-+
-+ def notFound(f):
-+ f.trap(http.HTTPError)
-+ if f.response.code != responsecode.NOT_FOUND:
+
+ def notFound(f):
+ f.trap(http.HTTPError)
+ if f.response.code != responsecode.NOT_FOUND:
+- raise f
+ return f
-+ return None
-+
+ return None
+
+- return defer.maybeDeferred(self._getChild, None, self.site.resource, segments, updatepaths=False)
+ d = defer.maybeDeferred(self._getChild, None, self.site.resource, segments, updatepaths=False)
+ d.addCallback(self._rememberResource, path)
+ d.addErrback(notFound)
+ return d
-+
+
+ def locateChildResource(self, parent, child_name):
+ """
+ Looks up the child resource with the given name given the parent
@@ -159,33 +153,33 @@
+ L{responsecode.BAD_REQUEST}.
+ """
+ if parent is None or child_name is None:
-+ return None
++ return defer.succeed(None)
+
-+ url = joinURL(self.urlForResource(parent), child_name)
++ parent_resource = self.urlForResource(parent)
+
++ assert parent_resource is not None
++
++ url = joinURL(parent_resource, child_name)
++
+ cached = self._urlsByResource.get(url, None)
+ if cached is not None:
-+ return succeed(cached)
++ return defer.succeed(cached)
+
+ assert "/" not in child_name, "Child name may not contain '/': %s" % (child_name,)
+
+ segment = unquote(child_name)
-
- def notFound(f):
- f.trap(http.HTTPError)
-@@ -414,10 +471,13 @@
- def notFound(f):
- f.trap(http.HTTPError)
- if f.response.code != responsecode.NOT_FOUND:
-- raise f
++
++ def notFound(f):
++ f.trap(http.HTTPError)
++ if f.response.code != responsecode.NOT_FOUND:
+ return f
- return None
-
-- return defer.maybeDeferred(self._getChild, None, self.site.resource, segments, updatepaths=False)
++ return None
++
+ d = defer.maybeDeferred(self._getChild, None, parent, [segment], updatepaths=False)
+ d.addCallback(self._rememberResource, url)
+ d.addErrback(notFound)
+ return d
-
++
def _processingFailed(self, reason):
if reason.check(http.HTTPError) is not None:
+ # If the exception was an HTTPError, leave it alone
Modified: CalendarServer/branches/users/wsanchez/provisioning/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/wsanchez/provisioning/twistedcaldav/directory/appleopendirectory.py 2006-11-08 04:47:22 UTC (rev 394)
+++ CalendarServer/branches/users/wsanchez/provisioning/twistedcaldav/directory/appleopendirectory.py 2006-11-08 04:48:25 UTC (rev 395)
@@ -67,7 +67,7 @@
def recordWithShortName(self, recordType, shortName):
if recordType == "user":
result = opendirectory.listUsersWithAttributes(self._directory, [shortName])
- if shortName not in result:
+ if result is None or shortName not in result:
return None
result = result[shortName]
elif recordType == "group":
Modified: CalendarServer/branches/users/wsanchez/provisioning/twistedcaldav/directory/resource.py
===================================================================
--- CalendarServer/branches/users/wsanchez/provisioning/twistedcaldav/directory/resource.py 2006-11-08 04:47:22 UTC (rev 394)
+++ CalendarServer/branches/users/wsanchez/provisioning/twistedcaldav/directory/resource.py 2006-11-08 04:48:25 UTC (rev 395)
@@ -27,6 +27,8 @@
]
from twisted.python import log
+from twisted.web2 import responsecode
+from twisted.web2.http import HTTPError
from twisted.web2.dav.static import DAVFile
from twisted.web2.dav.util import joinURL
@@ -52,7 +54,7 @@
self.directory = IDirectoryService(directory)
def createSimilarFile(self, path):
- raise AssertionError("createSimilarFile() not allowed in DirectoryPrincipalProvisioningResource.")
+ raise HTTPError(responsecode.NOT_FOUND)
def getChild(self, name):
if name == "":
@@ -87,7 +89,7 @@
self.recordType = name
def createSimilarFile(self, path):
- raise AssertionError("createSimilarFile() not allowed in DirectoryPrincipalTypeResource.")
+ raise HTTPError(responsecode.NOT_FOUND)
def getChild(self, name):
if name == "":
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20061107/6ef3eb96/attachment.html
More information about the calendarserver-changes
mailing list