[CalendarServer-changes] [8560] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Jan 19 11:39:35 PST 2012


Revision: 8560
          http://trac.macosforge.org/projects/calendarserver/changeset/8560
Author:   sagen at apple.com
Date:     2012-01-19 11:39:34 -0800 (Thu, 19 Jan 2012)
Log Message:
-----------
Support new collabd access API

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/provision/root.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_wiki.py
    CalendarServer/trunk/twistedcaldav/directory/wiki.py
    CalendarServer/trunk/twistedcaldav/stdconfig.py

Added Paths:
-----------
    CalendarServer/trunk/calendarserver/platform/darwin/wiki.py

Added: CalendarServer/trunk/calendarserver/platform/darwin/wiki.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/wiki.py	                        (rev 0)
+++ CalendarServer/trunk/calendarserver/platform/darwin/wiki.py	2012-01-19 19:39:34 UTC (rev 8560)
@@ -0,0 +1,73 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twisted.web.client import HTTPPageGetter, HTTPClientFactory
+from twisted.internet import reactor
+
+def usernameForAuthToken(token, host="localhost", port=4444):
+    """
+    Send a GET request to the wiki collabd service to retrieve the user record
+    name associated with the provided auth token.
+
+    @param token: An auth token, usually passed in via cookie when webcal
+        makes a request.
+    @type token: C{str}
+    @return: deferred returning a record name (C{str}) if successful, or
+        if the auth token is not recognized a twisted.web.error.Error with
+        status FORBIDDEN will errBack.
+    """
+    url = "http://%s:%d/cal/userForSession/%s" % (host, port, token,)
+    return _getPage(url, host, port)
+
+
+def accessForUserToWiki(user, wiki, host="localhost", port=4444):
+    """
+    Send a GET request to the wiki collabd service to retrieve the access level
+    the given user (in GUID form) has to the given wiki (in wiki short-name
+    form).
+
+    @param user: The GUID of the user
+    @type user: C{str}
+    @param wiki: The short name of the wiki
+    @type wiki: C{str}
+    @return: deferred returning a access level (C{str}) if successful, or
+        if the user is not recognized a twisted.web.error.Error with
+        status FORBIDDEN will errBack; an unknown wiki will have a status
+        of NOT_FOUND
+    """
+    url = "http://%s:%s/cal/accessLevelForUserWikiCalendar/%s/%s" % (host, port,
+        user, wiki)
+    return _getPage(url, host, port)
+
+
+def _getPage(url, host, port):
+    """
+    Fetch the body of the given url via HTTP, connecting to the given host
+    and port.
+
+    @param url: The URL to GET
+    @type url: C{str}
+    @param host: The hostname to connect to
+    @type host: C{str}
+    @param port: The port number to connect to
+    @type port: C{int}
+    @return: A deferred; upon 200 success the body of the response is returned,
+        otherwise a twisted.web.error.Error is the result.
+    """
+    factory = HTTPClientFactory(url)
+    factory.protocol = HTTPPageGetter
+    reactor.connectTCP(host, port, factory)
+    return factory.deferred

Modified: CalendarServer/trunk/calendarserver/provision/root.py
===================================================================
--- CalendarServer/trunk/calendarserver/provision/root.py	2012-01-19 15:45:24 UTC (rev 8559)
+++ CalendarServer/trunk/calendarserver/provision/root.py	2012-01-19 19:39:34 UTC (rev 8560)
@@ -30,6 +30,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.reflect import namedClass
 from twisted.web.xmlrpc import Proxy
+from twisted.web.error import Error as WebError
 
 from twistedcaldav.cache import _CachedResponseResource
 from twistedcaldav.cache import MemcacheResponseCache, MemcacheChangeNotifier
@@ -43,6 +44,7 @@
 from twistedcaldav.directory.principal import DirectoryPrincipalResource
 from twistedcaldav.storebridge import CalendarCollectionResource,\
     AddressBookCollectionResource, StoreNotificationCollectionResource
+from calendarserver.platform.darwin.wiki import usernameForAuthToken
 
 log = Logger()
 
@@ -265,9 +267,25 @@
 
                 if token is not None and token != "unauthenticated":
                     log.debug("Wiki sessionID cookie value: %s" % (token,))
-                    proxy = Proxy(wikiConfig["URL"])
+
                     try:
-                        username = (yield proxy.callRemote(wikiConfig["UserMethod"], token))
+                        if wikiConfig.LionCompatibility:
+                            proxy = Proxy(wikiConfig["URL"])
+                            username = (yield proxy.callRemote(wikiConfig["UserMethod"], token))
+                        else:
+                            username = (yield usernameForAuthToken(token,
+                                host=wikiConfig.CollabHost,
+                                port=wikiConfig.CollabPort))
+
+                    except WebError, w:
+                        username = None
+                        # FORBIDDEN status means it's an unknown token
+                        if int(w.status) == responsecode.FORBIDDEN:
+                            log.debug("Unknown wiki token: %s" % (token,))
+                        else:
+                            log.error("Failed to look up wiki token %s: %s" %
+                                (token, w.message,))
+
                     except Exception, e:
                         log.error("Failed to look up wiki token (%s)" % (e,))
                         username = None

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_wiki.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_wiki.py	2012-01-19 15:45:24 UTC (rev 8559)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_wiki.py	2012-01-19 19:39:34 UTC (rev 8560)
@@ -22,6 +22,8 @@
 from twisted.web.xmlrpc import Fault
 from twext.web2.http import HTTPError
 from twext.web2 import responsecode
+from twistedcaldav.config import config
+from twisted.web.error import Error as WebError
 
 class WikiTestCase(TestCase):
     """
@@ -41,10 +43,11 @@
 
 
     @inlineCallbacks
-    def test_getWikiAccess(self):
+    def test_getWikiAccessLion(self):
         """
         XMLRPC Faults result in HTTPErrors
         """
+        self.patch(config.Authentication.Wiki, "LionCompatibility", True)
 
         def successful(self, user, wiki):
             return succeed("read")
@@ -74,3 +77,40 @@
                 self.fail("Incorrect exception")
             else:
                 self.fail("Didn't raise exception")
+
+
+    @inlineCallbacks
+    def test_getWikiAccess(self):
+        """
+        Non-200 GET responses result in HTTPErrors
+        """
+        self.patch(config.Authentication.Wiki, "LionCompatibility", False)
+
+        def successful(user, wiki):
+            return succeed("read")
+
+        def forbidden(user, wiki):
+            raise WebError(403, message="Unknown user")
+
+        def notFound(user, wiki):
+            raise WebError(404, message="Non-existent wiki")
+
+        def other(user, wiki):
+            raise WebError(500, "Error")
+
+        access = (yield getWikiAccess("user", "wiki", method=successful))
+        self.assertEquals(access, "read")
+
+        for (method, code) in (
+            (forbidden, responsecode.FORBIDDEN),
+            (notFound, responsecode.NOT_FOUND),
+            (other, responsecode.SERVICE_UNAVAILABLE),
+        ):
+            try:
+                access = (yield getWikiAccess("user", "wiki", method=method))
+            except HTTPError, e:
+                self.assertEquals(e.response.code, code)
+            except:
+                self.fail("Incorrect exception")
+            else:
+                self.fail("Didn't raise exception")

Modified: CalendarServer/trunk/twistedcaldav/directory/wiki.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/wiki.py	2012-01-19 15:45:24 UTC (rev 8559)
+++ CalendarServer/trunk/twistedcaldav/directory/wiki.py	2012-01-19 19:39:34 UTC (rev 8560)
@@ -37,6 +37,8 @@
 from twistedcaldav.directory.directory import (DirectoryService,
                                                DirectoryRecord,
                                                UnknownRecordTypeError)
+from calendarserver.platform.darwin.wiki import accessForUserToWiki
+from twisted.web.error import Error as WebError
 
 log = Logger()
 
@@ -73,8 +75,6 @@
 
         if self.byShortName.has_key(shortName):
             record = self.byShortName[shortName]
-            self.log_info("Returning existing wiki record with UID %s" %
-                (record.uid,))
             return record
 
         record = self._addRecord(shortName)
@@ -84,8 +84,6 @@
 
         if self.byUID.has_key(uid):
             record = self.byUID[uid]
-            self.log_info("Returning existing wiki record with UID %s" %
-                (record.uid,))
             return record
 
         if uid.startswith(self.UIDPrefix):
@@ -103,7 +101,6 @@
             shortName,
             None
         )
-        self.log_info("Creating wiki record with GUID %s" % (record.guid,))
         self.byUID[record.uid] = record
         self.byShortName[shortName] = record
         return record
@@ -137,16 +134,22 @@
     """
     wikiConfig = config.Authentication.Wiki
     if method is None:
-        method = Proxy(wikiConfig["URL"]).callRemote
+        if wikiConfig.LionCompatibility:
+            method = Proxy(wikiConfig["URL"]).callRemote
+        else:
+            method = accessForUserToWiki
     try:
 
         log.debug("Looking up Wiki ACL for: user [%s], wiki [%s]" % (userID,
             wikiID))
-        access = (yield method(wikiConfig["WikiMethod"],
-            userID, wikiID))
+        if wikiConfig.LionCompatibility:
+            access = (yield method(wikiConfig["WikiMethod"],
+                userID, wikiID))
+        else:
+            access = (yield method(userID, wikiID))
 
-        log.debug("Wiki ACL result: user [%s], wiki [%s], access [%s]" % (userID,
-            wikiID, access))
+        log.debug("Wiki ACL result: user [%s], wiki [%s], access [%s]" %
+            (userID, wikiID, access))
         returnValue(access)
 
     except Fault, fault:
@@ -169,7 +172,28 @@
             raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE,
                 fault.faultString))
 
+    except WebError, w:
+        status = int(w.status)
 
+        log.debug("Wiki ACL result: user [%s], wiki [%s], status [%s]" %
+            (userID, wikiID, status))
+
+        if status == responsecode.FORBIDDEN: # non-existent user
+            raise HTTPError(StatusResponse(responsecode.FORBIDDEN,
+                "Unknown User"))
+
+        elif status == responsecode.NOT_FOUND: # non-existent wiki
+            raise HTTPError(StatusResponse(responsecode.NOT_FOUND,
+                "Unknown Wiki"))
+
+        else: # Unknown fault returned from wiki server.  Log the error and
+              # return 503 Service Unavailable to the client.
+            log.error("Wiki ACL error: user [%s], wiki [%s], status [%s]" %
+                (userID, wikiID, status))
+            raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE,
+                w.message))
+
+
 @inlineCallbacks
 def getWikiACL(resource, request):
     """
@@ -283,5 +307,5 @@
         raise
 
     except Exception, e:
-        log.error("Wiki ACL RPC failed: %s" % (e,))
-        raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE, "Wiki ACL RPC failed"))
+        log.error("Wiki ACL lookup failed: %s" % (e,))
+        raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE, "Wiki ACL lookup failed"))

Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/stdconfig.py	2012-01-19 15:45:24 UTC (rev 8559)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py	2012-01-19 19:39:34 UTC (rev 8560)
@@ -412,6 +412,9 @@
             "URL": "http://127.0.0.1:8089/RPC2",
             "UserMethod": "userForSession",
             "WikiMethod": "accessLevelForUserWikiCalendar",
+            "LionCompatibility": False,
+            "CollabHost": "localhost",
+            "CollabPort": 4444,
         },
     },
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120119/11bdd781/attachment-0001.html>


More information about the calendarserver-changes mailing list