changeset 2032:cf883a6917ea

better xmlrpc auth token handling
author Johannes Berg <johannes AT sipsolutions DOT net>
date Thu, 26 Apr 2007 13:09:26 +0200
parents 56d8a8a14114
children a6d829ec895d
files MoinMoin/action/SyncPages.py MoinMoin/wikisync.py MoinMoin/xmlrpc/__init__.py
diffstat 3 files changed, 57 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/action/SyncPages.py	Thu Apr 26 13:09:02 2007 +0200
+++ b/MoinMoin/action/SyncPages.py	Thu Apr 26 13:09:26 2007 +0200
@@ -219,6 +219,8 @@
                 self.page.saveText(self.page.get_raw_body() + "\n\n" + self.generate_log_table(), 0)
                 # XXX release readlock on self.page
 
+                remote.delete_auth_token()
+
         return self.page.send_page(msg=msg)
 
     def sync(self, params, local, remote):
--- a/MoinMoin/wikisync.py	Thu Apr 26 13:09:02 2007 +0200
+++ b/MoinMoin/wikisync.py	Thu Apr 26 13:09:26 2007 +0200
@@ -259,6 +259,11 @@
             return [("applyAuthToken", (self.token, ))]
         return []
 
+    def delete_auth_token(self):
+        if self.token:
+            self.connection.deleteAuthToken(self.token)
+            self.token = None
+
     # Methods implementing the RemoteWiki interface
 
     def get_interwiki_name(self):
--- a/MoinMoin/xmlrpc/__init__.py	Thu Apr 26 13:09:02 2007 +0200
+++ b/MoinMoin/xmlrpc/__init__.py	Thu Apr 26 13:09:26 2007 +0200
@@ -35,6 +35,9 @@
 from MoinMoin.PageEditor import PageEditor
 from MoinMoin.logfile import editlog
 from MoinMoin.action import AttachFile
+from MoinMoin import caching
+from MoinMoin.util import random_string
+from random import randint
 
 _debug = 0
 
@@ -589,23 +592,68 @@
         """ Returns a token which can be used for authentication
             in other XMLRPC calls. If the token is empty, the username
             or the password were wrong. """
+
+        def _cleanup_stale_tokens(request):
+            items = caching.get_cache_list(request, 'xmlrpc-session', 'farm')
+            tnow = time.time()
+            for item in items:
+                centry = caching.CacheEntry(self.request, 'xmlrpc-session', item,
+                                            scope='farm', use_pickle=True)
+                try:
+                    expiry, uid = centry.content()
+                    if expiry < tnow:
+                        centry.remove()
+                except caching.CacheError:
+                    pass
+
+        if randint(0, 99) == 0:
+            _cleanup_stale_tokens(self.request)
+
         u = self.request.handle_auth(None, username=username,
                                      password=password, login=True)
         if u and u.valid:
-            return u.id
+            token = random_string(32, 'abcdefghijklmnopqrstuvwxyz0123456789')
+            centry = caching.CacheEntry(self.request, 'xmlrpc-session', token,
+                                        scope='farm', use_pickle=True)
+            centry.update((time.time() + 15*3600, u.id))
+            return token
         else:
             return ""
 
     def xmlrpc_applyAuthToken(self, auth_token):
         """ Applies the auth token and thereby authenticates the user. """
-        u = user.User(self.request, id=auth_token, auth_method='xmlrpc_applytoken')
+        centry = caching.CacheEntry(self.request, 'xmlrpc-session', token,
+                                    scope='farm', use_pickle=True)
+        try:
+            expiry, uid = centry.content()
+        except caching.CacheError:
+            return xmlrpclib.Fault("INVALID", "Invalid token.")
+
+        if expiry < time.time():
+            centry.remove()
+            return xmlrpclib.Fault("EXPIRED", "Expired token.")
+
+        u = user.User(self.request, id=uid, auth_method='xmlrpc_applytoken')
         if u.valid:
             self.request.user = u
+            centry.update((time.time() + 15*3600, uid))
             return "SUCCESS"
         else:
             return xmlrpclib.Fault("INVALID", "Invalid token.")
 
 
+    def xmlrpc_deleteAuthToken(self, auth_token):
+        """ Delete the given auth token. """
+        centry = caching.CacheEntry(self.request, 'xmlrpc-session', token,
+                                    scope='farm', use_pickle=True)
+        try:
+            centry.remove()
+        except caching.CacheError:
+            return xmlrpclib.Fault("INVALID", "Invalid token.")
+        else:
+            return "SUCCESS"
+
+
     # methods for wiki synchronization
 
     def xmlrpc_getDiff(self, pagename, from_rev, to_rev, n_name=None):