[CalendarServer-changes] [3907] CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/ Twisted

source_changes at macosforge.org source_changes at macosforge.org
Fri Mar 20 13:11:49 PDT 2009


Revision: 3907
          http://trac.macosforge.org/projects/calendarserver/changeset/3907
Author:   washort at twistedmatrix.com
Date:     2009-03-20 13:11:49 -0700 (Fri, 20 Mar 2009)
Log Message:
-----------
migrated to Twisted

Modified Paths:
--------------
    CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.digest.patch
    CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.dav.resource.patch

Removed Paths:
-------------
    CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.basic.patch
    CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.interfaces.patch
    CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.wrapper.patch
    CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.test.test_httpauth.patch

Deleted: CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.basic.patch
===================================================================
--- CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.basic.patch	2009-03-20 19:16:57 UTC (rev 3906)
+++ CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.basic.patch	2009-03-20 20:11:49 UTC (rev 3907)
@@ -1,29 +0,0 @@
-Index: twisted/web2/auth/basic.py
-===================================================================
---- twisted/web2/auth/basic.py	(revision 19773)
-+++ twisted/web2/auth/basic.py	(working copy)
-@@ -1,6 +1,7 @@
- # -*- test-case-name: twisted.web2.test.test_httpauth -*-
- 
- from twisted.cred import credentials, error
-+from twisted.internet.defer import succeed
- from twisted.web2.auth.interfaces import ICredentialFactory
- 
- from zope.interface import implements
-@@ -18,7 +19,7 @@
-         self.realm = realm
- 
-     def getChallenge(self, peer):
--        return {'realm': self.realm}
-+        return succeed({'realm': self.realm})
- 
-     def decode(self, response, request):
-         try:
-@@ -28,6 +29,6 @@
- 
-         creds = creds.split(':', 1)
-         if len(creds) == 2:
--            return credentials.UsernamePassword(*creds)
-+            return succeed(credentials.UsernamePassword(*creds))
-         else:
-             raise error.LoginFailed('Invalid credentials')

Modified: CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.digest.patch
===================================================================
--- CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.digest.patch	2009-03-20 19:16:57 UTC (rev 3906)
+++ CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.digest.patch	2009-03-20 20:11:49 UTC (rev 3907)
@@ -2,13 +2,9 @@
 ===================================================================
 --- twisted/web2/auth/digest.py	(revision 26342)
 +++ twisted/web2/auth/digest.py	(working copy)
-@@ -11,9 +11,14 @@
- import random
+@@ -11,6 +11,10 @@
+ from twisted.internet.defer import succeed
  
- from twisted.cred import credentials, error
-+from twisted.internet.defer import succeed
- from zope.interface import implements, Interface
- 
  from twisted.web2.auth.interfaces import ICredentialFactory
 +from twisted.web2.http_headers import tokenize
 +from twisted.web2.http_headers import Token
@@ -17,33 +13,6 @@
  from twisted.python.hashlib import md5, sha1
  
  # The digest math
-@@ -231,7 +236,7 @@
-         key = "%s,%s,%s" % (nonce, clientip, str(int(self._getTime())))
-         digest = md5(key + self.privateKey).hexdigest()
-         ekey = key.encode('base64')
--        return "%s-%s" % (digest, ekey.strip('\n'))
-+        return "%s-%s" % (digest, ekey.replace('\n', ''))
- 
-     def verifyOpaque(self, opaque, nonce, clientip):
-         """
-@@ -295,11 +300,12 @@
-         c = self.generateNonce()
-         o = self.generateOpaque(c, peer.host)
- 
--        return {'nonce': c,
--                'opaque': o,
--                'qop': 'auth',
--                'algorithm': self.algorithm,
--                'realm': self.realm}
-+        return succeed({'nonce': c,
-+            'opaque': o,
-+            'qop': 'auth',
-+            'algorithm': self.algorithm,
-+            'realm': self.realm,
-+        })
- 
-     def decode(self, response, request):
-         """
 @@ -317,18 +323,18 @@
          @raise: L{error.LoginFailed} if the response does not contain a
              username, a nonce, an opaque, or if the opaque is invalid.
@@ -74,13 +43,3 @@
          username = auth.get('username')
          if not username:
              raise error.LoginFailed('Invalid response, no username given.')
-@@ -344,7 +350,7 @@
-                              auth.get('nonce'),
-                              request.remoteAddr.host):
- 
--            return DigestedCredentials(username,
-+            return succeed(DigestedCredentials(username,
-                                        request.method,
-                                        self.realm,
--                                       auth)
-+                                       auth))

Deleted: CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.interfaces.patch
===================================================================
--- CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.interfaces.patch	2009-03-20 19:16:57 UTC (rev 3906)
+++ CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.interfaces.patch	2009-03-20 20:11:49 UTC (rev 3907)
@@ -1,22 +0,0 @@
-Index: twisted/web2/auth/interfaces.py
-===================================================================
---- twisted/web2/auth/interfaces.py	(revision 19773)
-+++ twisted/web2/auth/interfaces.py	(working copy)
-@@ -18,7 +18,7 @@
-         @param peer: The client's address
- 
-         @rtype: C{dict}
--        @return: dictionary of challenge arguments
-+        @return: deferred returning dictionary of challenge arguments
-         """
- 
-     def decode(response, request):
-@@ -32,7 +32,7 @@
-         @type request: L{twisted.web2.server.Request}
-         @param request: the request being processed
- 
--        @return: ICredentials
-+        @return: deferred returning ICredentials
-         """
- 
- 

Deleted: CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.wrapper.patch
===================================================================
--- CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.wrapper.patch	2009-03-20 19:16:57 UTC (rev 3906)
+++ CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.auth.wrapper.patch	2009-03-20 20:11:49 UTC (rev 3907)
@@ -1,205 +0,0 @@
-Index: twisted/web2/auth/wrapper.py
-===================================================================
---- twisted/web2/auth/wrapper.py	(revision 19773)
-+++ twisted/web2/auth/wrapper.py	(working copy)
-@@ -5,32 +5,45 @@
- """
- from zope.interface import implements, directlyProvides
- from twisted.cred import error, credentials
--from twisted.python import failure
- from twisted.web2 import responsecode
- from twisted.web2 import http
- from twisted.web2 import iweb
- from twisted.web2.auth.interfaces import IAuthenticatedRequest
-+from twisted.internet.defer import inlineCallbacks, returnValue
- 
- class UnauthorizedResponse(http.StatusResponse):
-     """A specialized response class for generating www-authenticate headers
-     from the given L{CredentialFactory} instances
-     """
- 
--    def __init__(self, factories, remoteAddr=None):
-+    @staticmethod
-+    def makeResponse(factories, remoteAddr=None):
-+        
-+        response = UnauthorizedResponse()
-+        d = response.generateHeaders(factories, remoteAddr)
-+        d.addCallback(lambda _:response)
-+        return d
-+
-+    def __init__(self):
-+
-+        super(UnauthorizedResponse, self).__init__(
-+            responsecode.UNAUTHORIZED,
-+            "You are not authorized to access this resource."
-+    )
-+
-+    @inlineCallbacks
-+    def generateHeaders(self, factories, remoteAddr=None):
-         """
-         @param factories: A L{dict} of {'scheme': ICredentialFactory}
- 
-         @param remoteAddr: An L{IAddress} for the connecting client.
-         """
- 
--        super(UnauthorizedResponse, self).__init__(
--            responsecode.UNAUTHORIZED,
--            "You are not authorized to access this resource.")
--
-         authHeaders = []
-         for factory in factories.itervalues():
--            authHeaders.append((factory.scheme,
--                                factory.getChallenge(remoteAddr)))
-+            scheme = factory.scheme
-+            challenge = (yield factory.getChallenge(remoteAddr))
-+            authHeaders.append((scheme, challenge,))
- 
-         self.headers.setHeader('www-authenticate', authHeaders)
- 
-@@ -71,8 +84,6 @@
- 
-     def _loginSucceeded(self, avatar, request):
-         """
--        Callback for successful login.
--
-         @param avatar: A tuple of the form (interface, avatar) as
-             returned by your realm.
- 
-@@ -85,6 +96,7 @@
- 
-         directlyProvides(request, IAuthenticatedRequest)
- 
-+        @inlineCallbacks
-         def _addAuthenticateHeaders(request, response):
-             """
-             A response filter that adds www-authenticate headers
-@@ -93,14 +105,16 @@
-             """
-             if response.code == responsecode.UNAUTHORIZED:
-                 if not response.headers.hasHeader('www-authenticate'):
--                    newResp = UnauthorizedResponse(self.credentialFactories,
--                                                   request.remoteAddr)
-+                    newResp = (yield UnauthorizedResponse.makeResponse(
-+                        self.credentialFactories,
-+                        request.remoteAddr
-+                    ))
- 
-                     response.headers.setHeader(
-                         'www-authenticate',
-                         newResp.headers.getHeader('www-authenticate'))
- 
--            return response
-+            returnValue(response)
- 
-         _addAuthenticateHeaders.handleErrors = True
- 
-@@ -108,27 +122,22 @@
- 
-         return self.wrappedResource
- 
--    def _loginFailed(self, result, request):
-+    @inlineCallbacks
-+    def _loginFailed(self, request):
-         """
--        Errback for failed login.
--
--        @param result: L{Failure} returned by portal.login
--
-         @param request: L{IRequest} that encapsulates this auth
-             attempt.
- 
--        @return: A L{Failure} containing an L{HTTPError} containing the
--            L{UnauthorizedResponse} if C{result} is an L{UnauthorizedLogin}
--            or L{UnhandledCredentials} error
-+        @raise: always rais HTTPError
-         """
--        result.trap(error.UnauthorizedLogin, error.UnhandledCredentials)
- 
--        return failure.Failure(
--            http.HTTPError(
--                UnauthorizedResponse(
--                self.credentialFactories,
--                request.remoteAddr)))
-+        response = (yield UnauthorizedResponse.makeResponse(
-+            self.credentialFactories,
-+            request.remoteAddr
-+        ))
-+        raise http.HTTPError(response)
- 
-+    @inlineCallbacks
-     def login(self, factory, response, request):
-         """
-         @param factory: An L{ICredentialFactory} that understands the given
-@@ -142,50 +151,48 @@
-             or a failure containing an L{UnauthorizedResponse}
-         """
-         try:
--            creds = factory.decode(response, request)
-+            creds = (yield factory.decode(response, request))
-         except error.LoginFailed:
--            raise http.HTTPError(UnauthorizedResponse(
--                                    self.credentialFactories,
--                                    request.remoteAddr))
-+            yield self._loginFailed(request)
- 
-+        try:
-+            avatar = (yield self.portal.login(creds, None, *self.interfaces))
-+        except (error.UnauthorizedLogin, error.UnhandledCredentials):
-+            yield self._loginFailed(request)
-+        resource = self._loginSucceeded(avatar, request)
-+        returnValue(resource)
- 
--        return self.portal.login(creds, None, *self.interfaces
--                                ).addCallbacks(self._loginSucceeded,
--                                               self._loginFailed,
--                                               (request,), None,
--                                               (request,), None)
--
-+    @inlineCallbacks
-     def authenticate(self, request):
-         """
--        Attempt to authenticate the givin request
-+        Attempt to authenticate the giving request
- 
-         @param request: An L{IRequest} to be authenticated.
-         """
-         authHeader = request.headers.getHeader('authorization')
- 
-         if authHeader is None:
--            return self.portal.login(credentials.Anonymous(),
--                                     None,
--                                     *self.interfaces
--                                     ).addCallbacks(self._loginSucceeded,
--                                                    self._loginFailed,
--                                                    (request,), None,
--                                                    (request,), None)
-+            try:
-+                avatar = (yield self.portal.login(credentials.Anonymous(), None, *self.interfaces))
-+            except:
-+                yield self._loginFailed(request)
-+            resource = self._loginSucceeded(avatar, request)
-+            returnValue(resource)
- 
-         elif authHeader[0] not in self.credentialFactories:
--            raise http.HTTPError(UnauthorizedResponse(
--                                    self.credentialFactories,
--                                    request.remoteAddr))
-+            yield self._loginFailed(request)
-         else:
--            return self.login(self.credentialFactories[authHeader[0]],
--                              authHeader[1], request)
-+            result = (yield self.login(self.credentialFactories[authHeader[0]], authHeader[1], request))
-+            returnValue(result)
- 
-     def locateChild(self, request, seg):
-         """
-         Authenticate the request then return the C{self.wrappedResource}
-         and the unmodified segments.
-         """
--        return self.authenticate(request), seg
-+        d = self.authenticate(request)
-+        d.addCallback(lambda result:(result, seg,))
-+        return d
- 
-     def renderHTTP(self, request):
-         """

Modified: CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.dav.resource.patch
===================================================================
--- CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.dav.resource.patch	2009-03-20 19:16:57 UTC (rev 3906)
+++ CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.dav.resource.patch	2009-03-20 20:11:49 UTC (rev 3907)
@@ -1,8 +1,8 @@
 Index: twisted/web2/dav/resource.py
 ===================================================================
---- twisted/web2/dav/resource.py	(revision 19773)
+--- twisted/web2/dav/resource.py	(revision 26455)
 +++ twisted/web2/dav/resource.py	(working copy)
-@@ -31,20 +31,30 @@
+@@ -31,34 +31,43 @@
      "DAVResource",
      "DAVLeafResource",
      "DAVPrincipalResource",
@@ -27,15 +27,13 @@
  
  from zope.interface import implements
  from twisted.python import log
--from twisted.internet.defer import Deferred, maybeDeferred, succeed
-+from twisted.python.failure import Failure
-+from twisted.cred.error import LoginFailed, UnauthorizedLogin
-+from twisted.internet.defer import Deferred, maybeDeferred, succeed,\
-+    inlineCallbacks, returnValue
+ from twisted.python.failure import Failure
+ from twisted.internet.defer import Deferred, maybeDeferred, succeed
  from twisted.internet.defer import waitForDeferred, deferredGenerator
++from twisted.cred.error import LoginFailed, UnauthorizedLogin
  from twisted.internet import reactor
  from twisted.web2 import responsecode
-@@ -52,12 +62,13 @@
+ from twisted.web2.http import HTTPError, RedirectResponse, StatusResponse
  from twisted.web2.http_headers import generateContentType
  from twisted.web2.iweb import IResponse
  from twisted.web2.resource import LeafResource
@@ -50,7 +48,7 @@
  from twisted.web2.dav.http import NeedPrivilegesResponse
  from twisted.web2.dav.noneprops import NonePropertyStore
  from twisted.web2.dav.util import unimplemented, parentForURL, joinURL
-@@ -126,10 +137,13 @@
+@@ -127,10 +136,13 @@
         #(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
@@ -64,7 +62,7 @@
  
          (twisted_dav_namespace, "resource-class"),
      )
-@@ -166,6 +180,14 @@
+@@ -167,6 +179,14 @@
          if qname[0] == twisted_private_namespace:
              return succeed(False)
  
@@ -79,7 +77,7 @@
          return succeed(qname in self.liveProperties or self.deadProperties().contains(qname))
  
      def readProperty(self, property, request):
-@@ -201,7 +223,6 @@
+@@ -202,7 +222,6 @@
                      mimeType = self.contentType()
                      if mimeType is None:
                          return None
@@ -87,7 +85,7 @@
                      return davxml.GETContentType(generateContentType(mimeType))
  
                  if name == "getcontentlength":
-@@ -239,8 +260,10 @@
+@@ -240,8 +259,10 @@
                      )
  
                  if name == "supported-report-set":
@@ -100,7 +98,7 @@
  
                  if name == "supported-privilege-set":
                      return self.supportedPrivileges(request)
-@@ -252,9 +275,10 @@
+@@ -253,9 +274,10 @@
                      return davxml.InheritedACLSet(*self.inheritedACLSet())
  
                  if name == "principal-collection-set":
@@ -114,7 +112,7 @@
  
                  def ifAllowed(privileges, callback):
                      def onError(failure):
-@@ -286,7 +310,36 @@
+@@ -287,7 +309,36 @@
                          d.addCallback(gotACL)
                          return d
                      return ifAllowed((davxml.ReadACL(),), callback)
@@ -151,7 +149,7 @@
              elif namespace == twisted_dav_namespace:
                  if name == "resource-class":
                      class ResourceClass (davxml.WebDAVTextElement):
-@@ -309,10 +362,7 @@
+@@ -310,10 +361,7 @@
          """
          See L{IDAVResource.writeProperty}.
          """
@@ -163,7 +161,7 @@
  
          def defer():
              if property.protected:
-@@ -363,15 +413,28 @@
+@@ -364,15 +412,28 @@
          """
          See L{IDAVResource.listProperties}.
          """
@@ -196,7 +194,7 @@
      def listAllprop(self, request):
          """
          Some DAV properties should not be returned to a C{DAV:allprop} query.
-@@ -465,8 +528,22 @@
+@@ -466,8 +527,22 @@
              return super(DAVPropertyMixIn, self).displayName()
  
  class DAVResource (DAVPropertyMixIn, StaticRenderMixin):
@@ -219,7 +217,7 @@
      ##
      # DAV
      ##
-@@ -553,69 +630,65 @@
+@@ -554,12 +629,13 @@
      def supportedReports(self):
          """
          See L{IDAVResource.supportedReports}.
@@ -234,82 +232,25 @@
          return result
  
      ##
-     # Authentication
-     ##
- 
-+    @inlineCallbacks
-     def authorize(self, request, privileges, recurse=False):
-         """
+@@ -571,7 +647,7 @@
          See L{IDAVResource.authorize}.
          """
--        def onError(failure):
+         def onError(failure):
 -            log.err("Invalid authentication details: %s" % (request,))
--            raise HTTPError(UnauthorizedResponse(
-+
-+        try:
-+            yield self.authenticate(request)
-+        except (UnauthorizedLogin, LoginFailed), e:
-+            log.msg("Authentication failed: %s" % (e,))
-+            response = (yield UnauthorizedResponse.makeResponse(
-                 request.credentialFactories,
-                 request.remoteAddr
-             ))
-+            raise HTTPError(response)
- 
--        def onAuth(result):
--            def onErrors(failure):
--                failure.trap(AccessDeniedError)
--                
--                # If we were unauthorized to start with (no Authorization header from client) then
--                # we should return an unauthorized response instead to force the client to login if it can
++            log.err("Authentication failed: %s" % (failure.value,))
+             d = UnauthorizedResponse.makeResponse(request.credentialFactories,
+                                                   request.remoteAddr)
+             def _err(response):
+@@ -584,7 +660,7 @@
+                 
+                 # If we were unauthorized to start with (no Authorization header from client) then
+                 # we should return an unauthorized response instead to force the client to login if it can
 -                if request.user == davxml.Principal(davxml.Unauthenticated()):
--                    response = UnauthorizedResponse(request.credentialFactories,
--                                                    request.remoteAddr)
--                else:
--                    response = NeedPrivilegesResponse(request.uri,
--                                                      failure.value.errors)
--                #
--                # We're not adding the headers here because this response
--                # class is supposed to be a FORBIDDEN status code and
--                # "Authorization will not help" according to RFC2616
--                #
--                raise HTTPError(response)
-+        try:
-+            yield self.checkPrivileges(request, privileges, recurse)
-+        except AccessDeniedError, e:
-+            # If we were unauthenticated to start with (no Authorization header from client) then
-+            # we should return an unauthorized response instead to force the client to login if it can
-+            if request.authnUser == davxml.Principal(davxml.Unauthenticated()):
-+                response = (yield UnauthorizedResponse.makeResponse(
-+                    request.credentialFactories,
-+                    request.remoteAddr
-+                ))
-+            else:
-+                response = NeedPrivilegesResponse(request.uri, e.errors)
-+            #
-+            # We're not adding the headers here because this response
-+            # class is supposed to be a FORBIDDEN status code and
-+            # "Authorization will not help" according to RFC2616
-+            #
-+            raise HTTPError(response)
- 
--            d = self.checkPrivileges(request, privileges, recurse)
--            d.addErrback(onErrors)
--            return d
--
--        d = maybeDeferred(self.authenticate, request)
--        d.addCallbacks(onAuth, onError)
--
--        return d
--
-+    @inlineCallbacks
-     def authenticate(self, request):
--        def loginSuccess(result):
--            request.user = result[1]
--            return request.user
- 
-         if not (
-             hasattr(request, 'portal') and 
++                if request.authnUser == davxml.Principal(davxml.Unauthenticated()):
+                     d = UnauthorizedResponse.makeResponse(request.credentialFactories,
+                                                                  request.remoteAddr)
+                     def _fail(response):
+@@ -619,8 +695,9 @@
              hasattr(request, 'credentialFactories') and
              hasattr(request, 'loginInterfaces')
          ):
@@ -317,61 +258,62 @@
 -            return request.user
 +            request.authnUser = davxml.Principal(davxml.Unauthenticated())
 +            request.authzUser = davxml.Principal(davxml.Unauthenticated())
-+            returnValue((request.authnUser, request.authzUser,))
++            return (request.authnUser, request.authzUser)
  
          authHeader = request.headers.getHeader('authorization')
  
-@@ -623,31 +696,32 @@
+@@ -628,31 +705,42 @@
              if authHeader[0] not in request.credentialFactories:
                  log.err("Client authentication scheme %s is not provided by server %s"
                          % (authHeader[0], request.credentialFactories.keys()))
 -                raise HTTPError(responsecode.FORBIDDEN)
-+
-+                response = (yield UnauthorizedResponse.makeResponse(
++                d = UnauthorizedResponse.makeResponse(
 +                    request.credentialFactories,
-+                    request.remoteAddr
-+                ))
-+                raise HTTPError(response)
++                    request.remoteAddr)
++                def _fail(response):
++                    return Failure(HTTPError(response))
++                return d.addCallback(_fail)
              else:
                  factory = request.credentialFactories[authHeader[0]]
  
--                creds = factory.decode(authHeader[1], request)
-+                creds = (yield factory.decode(authHeader[1], request))
+                 d = factory.decode(authHeader[1], request)
  
+                 def gotCreds(creds):
+-                    return self.findPrincipalForAuthID(
++                    return self.principalsForAuthID(
+                         request, creds.username
+                         ).addCallback(gotDetails, creds)
                  # Try to match principals in each principal collection on the resource
--                def gotDetails(details):
+                 def gotDetails(details, creds):
 -                    principal = IDAVPrincipalResource(details[0])
 -                    principalURI = details[1]
 -                    return PrincipalCredentials(principal, principalURI, creds)
-+                authnPrincipal, authzPrincipal = (yield self.principalsForAuthID(request, creds.username))
-+                authnPrincipal = IDAVPrincipalResource(authnPrincipal)
-+                authzPrincipal = IDAVPrincipalResource(authzPrincipal)
++                    authnPrincipal = IDAVPrincipalResource(details[0])
++                    authzPrincipal = IDAVPrincipalResource(details[1])
++                    return PrincipalCredentials(authnPrincipal, authzPrincipa, creds)
  
--                def login(pcreds):
--                    d = request.portal.login(pcreds, None, *request.loginInterfaces)
--                    d.addCallback(loginSuccess)
-+                pcreds = PrincipalCredentials(authnPrincipal, authzPrincipal, creds)
- 
--                    return d
+                 def login(pcreds):
+                     return request.portal.login(pcreds, None,
+                                                 *request.loginInterfaces
+                                                 ).addCallback(loginSuccess)
 -
--                d = self.findPrincipalForAuthID(request, creds.username)
--                d.addCallback(gotDetails).addCallback(login)
--
--                return d
-+                result = (yield request.portal.login(pcreds, None, *request.loginInterfaces))
-+                request.authnUser = result[1]
-+                request.authzUser = result[2]
-+                returnValue((request.authnUser, request.authzUser,))
+-                return d.addCallback(gotCreds).addCallback(login)
++                def gotAuth(result):
++                    request.authnUser = result[1]
++                    request.authzUser = result[2]
++                    return (request.authnUser, request.authzUser)
++                d.addCallback(gotCreds).addCallback(login).addCallback(gotAuth)
++                return d
          else:
--            request.user = davxml.Principal(davxml.Unauthenticated())
+             request.user = davxml.Principal(davxml.Unauthenticated())
 -            return request.user
 +            request.authnUser = davxml.Principal(davxml.Unauthenticated())
 +            request.authzUser = davxml.Principal(davxml.Unauthenticated())
-+            returnValue((request.authnUser, request.authzUser,))
++            return (request.authnUser, request.authzUser)
  
      ##
      # ACL
-@@ -656,49 +730,23 @@
+@@ -661,49 +749,23 @@
      def currentPrincipal(self, request):
          """
          @param request: the request being processed.
@@ -430,7 +372,7 @@
          """
          @return: the L{davxml.ACL} element containing the default access control
              list for this resource.
-@@ -710,6 +758,17 @@
+@@ -715,6 +777,17 @@
          #
          return readonlyACL
  
@@ -448,7 +390,7 @@
      def setAccessControlList(self, acl):
          """
          See L{IDAVResource.setAccessControlList}.
-@@ -748,13 +807,16 @@
+@@ -753,13 +826,16 @@
          # 10. Verify that new acl is not in conflict with itself
          # 11. Update acl on the resource
  
@@ -466,7 +408,7 @@
  
          # Need to get list of supported privileges
          supported = []
-@@ -773,10 +835,7 @@
+@@ -778,10 +854,7 @@
          yield supportedPrivs
          supportedPrivs = supportedPrivs.getResult()
          for item in supportedPrivs.children:
@@ -478,7 +420,7 @@
              addSupportedPrivilege(item)
  
          # Steps 1 - 6
-@@ -910,8 +969,7 @@
+@@ -915,8 +988,7 @@
          supportedPrivs = supportedPrivs.getResult()
  
          # Other principals types don't make sense as actors.
@@ -488,7 +430,7 @@
              "Principal is not an actor: %r" % (principal,)
          )
  
-@@ -1019,15 +1077,16 @@
+@@ -1024,15 +1096,16 @@
          def getMyURL():
              url = request.urlForResource(self)
  
@@ -508,7 +450,7 @@
                  "Expected %s response from readDeadProperty() exception, not %s"
                  % (responsecode.NOT_FOUND, e.response.code)
              )
-@@ -1038,9 +1097,9 @@
+@@ -1043,9 +1116,9 @@
  
              if myURL == "/":
                  # If we get to the root without any ACLs, then use the default.
@@ -520,7 +462,7 @@
  
          # Dynamically update privileges for those ace's that are inherited.
          if inheritance:
-@@ -1076,7 +1135,7 @@
+@@ -1081,7 +1154,7 @@
                                  # Adjust ACE for inherit on this resource
                                  children = list(ace.children)
                                  children.remove(TwistedACLInheritable())
@@ -529,7 +471,7 @@
                                  aces.append(davxml.ACE(*children))
              else:
                  aces.extend(inherited_aces)
-@@ -1105,8 +1164,7 @@
+@@ -1110,8 +1183,7 @@
          the child resource loop and supply those to the checkPrivileges on each child.
  
          @param request: the L{IRequest} for the request in progress.
@@ -539,7 +481,7 @@
          """
          
          # Get the parent ACLs with inheritance and preserve the <inheritable> element.
-@@ -1128,21 +1186,9 @@
+@@ -1133,21 +1205,9 @@
                  # Adjust ACE for inherit on this resource
                  children = list(ace.children)
                  children.remove(TwistedACLInheritable())
@@ -563,7 +505,7 @@
  
      inheritedACEsforChildren = deferredGenerator(inheritedACEsforChildren)
  
-@@ -1152,49 +1198,69 @@
+@@ -1157,49 +1217,69 @@
  
          This implementation returns an empty set.
          """
@@ -661,7 +603,7 @@
      def samePrincipal(self, principal1, principal2):
          """
          Check whether the two prinicpals are exactly the same in terms of
-@@ -1219,7 +1285,6 @@
+@@ -1224,7 +1304,6 @@
              return False
                  
      def matchPrincipal(self, principal1, principal2, request):
@@ -669,7 +611,7 @@
          """
          Check whether the principal1 is a principal in the set defined by
          principal2.
-@@ -1244,6 +1309,9 @@
+@@ -1249,6 +1328,9 @@
              if isinstance(principal1, davxml.Unauthenticated):
                  yield False
                  return
@@ -679,7 +621,7 @@
              else:
                  yield True
                  return
-@@ -1260,10 +1328,7 @@
+@@ -1265,10 +1347,7 @@
              yield False
              return
  
@@ -691,7 +633,7 @@
  
          principal2 = waitForDeferred(self.resolvePrincipal(principal2, request))
          yield principal2
-@@ -1271,7 +1336,6 @@
+@@ -1276,7 +1355,6 @@
  
          assert principal2 is not None, "principal2 is None"
  
@@ -699,7 +641,7 @@
          # Compare two HRefs and do group membership test as well
          if principal1 == principal2:
              yield True
-@@ -1289,6 +1353,7 @@
+@@ -1294,6 +1372,7 @@
  
      matchPrincipal = deferredGenerator(matchPrincipal)
  
@@ -707,7 +649,7 @@
      def principalIsGroupMember(self, principal1, principal2, request):
          """
          Check whether one principal is a group member of another.
-@@ -1299,18 +1364,21 @@
+@@ -1304,18 +1383,21 @@
          @return: L{Deferred} with result C{True} if principal1 is a member of principal2, C{False} otherwise
          """
          
@@ -740,7 +682,7 @@
          
      def validPrincipal(self, ace_principal, request):
          """
-@@ -1351,11 +1419,16 @@
+@@ -1356,11 +1438,16 @@
          @return C{True} if C{href_principal} is valid, C{False} otherwise.
  
          This implementation tests for a href element that corresponds to
@@ -760,7 +702,7 @@
          return d
  
      def resolvePrincipal(self, principal, request):
-@@ -1404,8 +1477,7 @@
+@@ -1409,8 +1496,7 @@
              try:
                  principal = principal.getResult()
              except HTTPError, e:
@@ -770,7 +712,7 @@
                      "Expected %s response from readProperty() exception, not %s"
                      % (responsecode.NOT_FOUND, e.response.code)
                  )
-@@ -1432,15 +1504,15 @@
+@@ -1437,15 +1523,15 @@
                  log.err("DAV:self ACE is set on non-principal resource %r" % (self,))
                  yield None
                  return
@@ -789,7 +731,7 @@
              "Not a meta-principal: %r" % (principal,)
          )
  
-@@ -1517,6 +1589,280 @@
+@@ -1522,6 +1608,280 @@
          return None
  
      ##
@@ -1070,7 +1012,7 @@
      # HTTP
      ##
  
-@@ -1525,15 +1871,11 @@
+@@ -1530,15 +1890,11 @@
          #litmus = request.headers.getRawHeaders("x-litmus")
          #if litmus: log.msg("*** Litmus test: %s ***" % (litmus,))
  
@@ -1088,7 +1030,7 @@
  
          def setHeaders(response):
              response = IResponse(response)
-@@ -1567,7 +1909,7 @@
+@@ -1572,7 +1928,7 @@
      def findChildren(self, depth, request, callback, privileges=None, inherited_aces=None):
          return succeed(None)
  
@@ -1097,7 +1039,7 @@
      """
      Resource representing a WebDAV principal.  (RFC 3744, section 2)
      """
-@@ -1577,7 +1919,7 @@
+@@ -1582,7 +1938,7 @@
      # WebDAV
      ##
  
@@ -1106,7 +1048,7 @@
          (dav_namespace, "alternate-URI-set"),
          (dav_namespace, "principal-URL"    ),
          (dav_namespace, "group-member-set" ),
-@@ -1585,14 +1927,11 @@
+@@ -1590,14 +1946,11 @@
      )
  
      def davComplianceClasses(self):
@@ -1122,7 +1064,7 @@
      def readProperty(self, property, request):
          def defer():
              if type(property) is tuple:
-@@ -1610,10 +1949,20 @@
+@@ -1615,10 +1968,20 @@
                      return davxml.PrincipalURL(davxml.HRef(self.principalURL()))
  
                  if name == "group-member-set":
@@ -1145,7 +1087,7 @@
  
                  if name == "resourcetype":
                      if self.isCollection():
-@@ -1655,7 +2004,7 @@
+@@ -1660,7 +2023,7 @@
          principals.  Subclasses should override this method to provide member
          URLs for this resource if appropriate.
          """
@@ -1154,7 +1096,7 @@
  
      def groupMemberships(self):
          """
-@@ -1666,6 +2015,7 @@
+@@ -1671,6 +2034,7 @@
          """
          unimplemented(self)
  
@@ -1162,7 +1104,7 @@
      def principalMatch(self, href):
          """
          Check whether the supplied principal matches this principal or is a
-@@ -1675,10 +2025,33 @@
+@@ -1680,10 +2044,33 @@
          """
          uri = str(href)
          if self.principalURL() == uri:
@@ -1198,7 +1140,7 @@
  class AccessDeniedError(Exception):
      def __init__(self, errors):
          """ 
-@@ -1718,6 +2091,37 @@
+@@ -1723,6 +2110,37 @@
  davxml.registerElement(TwistedACLInheritable)
  davxml.ACE.allowed_children[(twisted_dav_namespace, "inheritable")] = (0, 1)
  

Deleted: CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.test.test_httpauth.patch
===================================================================
--- CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.test.test_httpauth.patch	2009-03-20 19:16:57 UTC (rev 3906)
+++ CalendarServer/branches/exarkun/update-twisted-3816/lib-patches/Twisted/twisted.web2.test.test_httpauth.patch	2009-03-20 20:11:49 UTC (rev 3907)
@@ -1,246 +0,0 @@
-Index: twisted/web2/test/test_httpauth.py
-===================================================================
---- twisted/web2/test/test_httpauth.py	(revision 26342)
-+++ twisted/web2/test/test_httpauth.py	(working copy)
-@@ -3,6 +3,7 @@
- 
- from twisted.python.hashlib import md5
- from twisted.internet import address
-+from twisted.internet.defer import inlineCallbacks
- from twisted.trial import unittest
- from twisted.cred import error
- from twisted.web2 import http, responsecode
-@@ -44,22 +45,25 @@
-         self.username = 'dreid'
-         self.password = 'S3CuR1Ty'
- 
-+    @inlineCallbacks
-     def testUsernamePassword(self):
-         response = base64.encodestring('%s:%s' % (
-                 self.username,
-                 self.password))
- 
--        creds = self.credentialFactory.decode(response, _trivial_GET)
-+        creds = (yield self.credentialFactory.decode(response, _trivial_GET))
-         self.failUnless(creds.checkPassword(self.password))
- 
-+    @inlineCallbacks
-     def testIncorrectPassword(self):
-         response = base64.encodestring('%s:%s' % (
-                 self.username,
-                 'incorrectPassword'))
- 
--        creds = self.credentialFactory.decode(response, _trivial_GET)
-+        creds = (yield self.credentialFactory.decode(response, _trivial_GET))
-         self.failIf(creds.checkPassword(self.password))
- 
-+    @inlineCallbacks
-     def testIncorrectPadding(self):
-         response = base64.encodestring('%s:%s' % (
-                 self.username,
-@@ -67,7 +71,7 @@
- 
-         response = response.strip('=')
- 
--        creds = self.credentialFactory.decode(response, _trivial_GET)
-+        creds = (yield self.credentialFactory.decode(response, _trivial_GET))
-         self.failUnless(creds.checkPassword(self.password))
- 
-     def testInvalidCredentials(self):
-@@ -138,6 +142,7 @@
-             )
-         return expected
- 
-+    @inlineCallbacks
-     def test_getChallenge(self):
-         """
-         Test that all the required fields exist in the challenge,
-@@ -145,42 +150,44 @@
-         DigestCredentialFactory
-         """
- 
--        challenge = self.credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield self.credentialFactory.getChallenge(clientAddress))
-         self.assertEquals(challenge['qop'], 'auth')
-         self.assertEquals(challenge['realm'], 'test realm')
-         self.assertEquals(challenge['algorithm'], 'md5')
-         self.assertTrue(challenge.has_key("nonce"))
-         self.assertTrue(challenge.has_key("opaque"))
- 
-+    @inlineCallbacks
-     def test_response(self):
-         """
-         Test that we can decode a valid response to our challenge
-         """
- 
--        challenge = self.credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield self.credentialFactory.getChallenge(clientAddress))
- 
-         clientResponse = authRequest1 % (
-             challenge['nonce'],
-             self.getDigestResponse(challenge, "00000001"),
-             challenge['opaque'])
- 
--        creds = self.credentialFactory.decode(clientResponse, _trivial_GET)
-+        creds = (yield self.credentialFactory.decode(clientResponse, _trivial_GET))
-         self.failUnless(creds.checkPassword('password'))
- 
-+    @inlineCallbacks
-     def test_multiResponse(self):
-         """
-         Test that multiple responses to to a single challenge are handled
-         successfully.
-         """
- 
--        challenge = self.credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield self.credentialFactory.getChallenge(clientAddress))
- 
-         clientResponse = authRequest1 % (
-             challenge['nonce'],
-             self.getDigestResponse(challenge, "00000001"),
-             challenge['opaque'])
- 
--        creds = self.credentialFactory.decode(clientResponse, _trivial_GET)
-+        creds = (yield self.credentialFactory.decode(clientResponse, _trivial_GET))
-         self.failUnless(creds.checkPassword('password'))
- 
-         clientResponse = authRequest2 % (
-@@ -188,24 +195,25 @@
-             self.getDigestResponse(challenge, "00000002"),
-             challenge['opaque'])
- 
--        creds = self.credentialFactory.decode(clientResponse, _trivial_GET)
-+        creds = (yield self.credentialFactory.decode(clientResponse, _trivial_GET))
-         self.failUnless(creds.checkPassword('password'))
- 
-+    @inlineCallbacks
-     def test_failsWithDifferentMethod(self):
-         """
-         Test that the response fails if made for a different request method
-         than it is being issued for.
-         """
- 
--        challenge = self.credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield self.credentialFactory.getChallenge(clientAddress))
- 
-         clientResponse = authRequest1 % (
-             challenge['nonce'],
-             self.getDigestResponse(challenge, "00000001"),
-             challenge['opaque'])
- 
--        creds = self.credentialFactory.decode(clientResponse,
--                                              SimpleRequest(None, 'POST', '/'))
-+        creds = (yield self.credentialFactory.decode(clientResponse,
-+                                              SimpleRequest(None, 'POST', '/')))
-         self.failIf(creds.checkPassword('password'))
- 
-     def test_noUsername(self):
-@@ -250,20 +258,21 @@
-                               _trivial_GET)
-         self.assertEquals(str(e), "Invalid response, no opaque given.")
- 
-+    @inlineCallbacks
-     def test_checkHash(self):
-         """
-         Check that given a hash of the form 'username:realm:password'
-         we can verify the digest challenge
-         """
- 
--        challenge = self.credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield self.credentialFactory.getChallenge(clientAddress))
- 
-         clientResponse = authRequest1 % (
-             challenge['nonce'],
-             self.getDigestResponse(challenge, "00000001"),
-             challenge['opaque'])
- 
--        creds = self.credentialFactory.decode(clientResponse, _trivial_GET)
-+        creds = (yield self.credentialFactory.decode(clientResponse, _trivial_GET))
- 
-         self.failUnless(creds.checkHash(
-                 md5('username:test realm:password').hexdigest()))
-@@ -271,6 +280,7 @@
-         self.failIf(creds.checkHash(
-                 md5('username:test realm:bogus').hexdigest()))
- 
-+    @inlineCallbacks
-     def test_invalidOpaque(self):
-         """
-         Test that login fails when the opaque does not contain all the required
-@@ -279,7 +289,7 @@
- 
-         credentialFactory = FakeDigestCredentialFactory('md5', 'test realm')
- 
--        challenge = credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield credentialFactory.getChallenge(clientAddress))
- 
-         self.assertRaises(
-             error.LoginFailed,
-@@ -305,6 +315,7 @@
-             challenge['nonce'],
-             clientAddress.host)
- 
-+    @inlineCallbacks
-     def test_incompatibleNonce(self):
-         """
-         Test that login fails when the given nonce from the response, does not
-@@ -313,7 +324,7 @@
- 
-         credentialFactory = FakeDigestCredentialFactory('md5', 'test realm')
- 
--        challenge = credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield credentialFactory.getChallenge(clientAddress))
- 
-         badNonceOpaque = credentialFactory.generateOpaque(
-             '1234567890',
-@@ -333,6 +344,7 @@
-             '',
-             clientAddress.host)
- 
-+    @inlineCallbacks
-     def test_incompatibleClientIp(self):
-         """
-         Test that the login fails when the request comes from a client ip
-@@ -341,7 +353,7 @@
- 
-         credentialFactory = FakeDigestCredentialFactory('md5', 'test realm')
- 
--        challenge = credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield credentialFactory.getChallenge(clientAddress))
- 
-         badNonceOpaque = credentialFactory.generateOpaque(
-             challenge['nonce'],
-@@ -354,6 +366,7 @@
-             challenge['nonce'],
-             clientAddress.host)
- 
-+    @inlineCallbacks
-     def test_oldNonce(self):
-         """
-         Test that the login fails when the given opaque is older than
-@@ -362,7 +375,7 @@
- 
-         credentialFactory = FakeDigestCredentialFactory('md5', 'test realm')
- 
--        challenge = credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield credentialFactory.getChallenge(clientAddress))
- 
-         key = '%s,%s,%s' % (challenge['nonce'],
-                             clientAddress.host,
-@@ -379,6 +392,7 @@
-             challenge['nonce'],
-             clientAddress.host)
- 
-+    @inlineCallbacks
-     def test_mismatchedOpaqueChecksum(self):
-         """
-         Test that login fails when the opaque checksum fails verification
-@@ -386,7 +400,7 @@
- 
-         credentialFactory = FakeDigestCredentialFactory('md5', 'test realm')
- 
--        challenge = credentialFactory.getChallenge(clientAddress)
-+        challenge = (yield credentialFactory.getChallenge(clientAddress))
- 
- 
-         key = '%s,%s,%s' % (challenge['nonce'],
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090320/cb866c40/attachment-0001.html>


More information about the calendarserver-changes mailing list