changeset 5265:8394211b1c32

AuthUser: refactor AuthUser cookie/session serialization * All serialization/deserialization logic is now in one place. * CookieStoreWrapper is gone; any login sessions established in 2012 or earlier will be terminated and users will have to log in again. * The term "cookie store" has been dropped in favor of simply "cookie" (the value is not a cookie "store" or data repository, but just the actual cookie/session serialization of AuthUser). Note: from_cookie_store was never used.
author Søren Løvborg <kwi@kwi.dk>
date Tue, 14 Jul 2015 14:00:15 +0200
parents bf1fc4c84e5f
children f103b1a2383b
files kallithea/lib/auth.py kallithea/lib/base.py
diffstat 2 files changed, 27 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/lib/auth.py	Tue Jul 14 13:59:59 2015 +0200
+++ b/kallithea/lib/auth.py	Tue Jul 14 14:00:15 2015 +0200
@@ -144,21 +144,6 @@
     return KallitheaCrypto.hash_check(password, hashed)
 
 
-class CookieStoreWrapper(object):
-
-    def __init__(self, cookie_store):
-        self.cookie_store = cookie_store
-
-    def __repr__(self):
-        return 'CookieStore<%s>' % (self.cookie_store)
-
-    def get(self, key, other=None):
-        if isinstance(self.cookie_store, dict):
-            return self.cookie_store.get(key, other)
-        elif isinstance(self.cookie_store, AuthUser):
-            return self.cookie_store.__dict__.get(key, other)
-
-
 
 def _cached_perms_data(user_id, user_is_admin, user_inherit_default_permissions,
                        explicit, algo):
@@ -642,23 +627,28 @@
         if self.user_id != self.anonymous_user.user_id:
             self.is_authenticated = authenticated
 
-    def get_cookie_store(self):
-        return {'username': self.username,
-                'user_id': self.user_id,
-                'is_authenticated': self.is_authenticated}
+    def to_cookie(self):
+        """ Serializes this login session to a cookie `dict`. """
+        return {
+            'user_id': self.user_id,
+            'username': self.username,
+            'is_authenticated': self.is_authenticated,
+        }
 
-    @classmethod
-    def from_cookie_store(cls, cookie_store):
+    @staticmethod
+    def from_cookie(cookie):
         """
-        Creates AuthUser from a cookie store
-
-        :param cls:
-        :param cookie_store:
+        Deserializes an `AuthUser` from a cookie `dict`.
         """
-        user_id = cookie_store.get('user_id')
-        username = cookie_store.get('username')
-        api_key = cookie_store.get('api_key')
-        return AuthUser(user_id, api_key, username)
+
+        au = AuthUser(
+            user_id=cookie.get('user_id'),
+            username=cookie.get('username'),
+        )
+        if not au.is_authenticated and au.user_id is not None:
+            # user is not authenticated and not empty
+            au.set_authenticated(cookie.get('is_authenticated'))
+        return au
 
     @classmethod
     def get_allowed_ips(cls, user_id, cache=False, inherit_from_default=False):
--- a/kallithea/lib/base.py	Tue Jul 14 13:59:59 2015 +0200
+++ b/kallithea/lib/base.py	Tue Jul 14 14:00:15 2015 +0200
@@ -49,7 +49,7 @@
 from kallithea.lib.utils2 import str2bool, safe_unicode, AttributeDict,\
     safe_str, safe_int
 from kallithea.lib import auth_modules
-from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware, CookieStoreWrapper
+from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware
 from kallithea.lib.utils import get_repo_slug
 from kallithea.lib.exceptions import UserCreationError
 from kallithea.lib.vcs.exceptions import RepositoryError, EmptyRepositoryError, ChangesetDoesNotExistError
@@ -120,8 +120,7 @@
 
     # Start new session to prevent session fixation attacks.
     session.invalidate()
-    cs = auth_user.get_cookie_store()
-    session['authuser'] = cs
+    session['authuser'] = cookie = auth_user.to_cookie()
 
     # If they want to be remembered, update the cookie
     if remember:
@@ -131,7 +130,7 @@
     session.save()
 
     log.info('user %s is now authenticated and stored in '
-             'session, session attrs %s', user.username, cs)
+             'session, session attrs %s', user.username, cookie)
 
     # dumps session attrs back to cookie
     session._update_cookie_out()
@@ -388,11 +387,12 @@
             return AuthUser(api_key=api_key)
 
         # Authenticate by session cookie
-        cookie_store = CookieStoreWrapper(session_authuser)
-        user_id = cookie_store.get('user_id')
-        if user_id is not None:
+        cookie = session.get('authuser')
+        # In ancient login sessions, 'authuser' may not be a dict.
+        # In that case, the user will have to log in again.
+        if isinstance(cookie, dict):
             try:
-                auth_user = AuthUser(user_id=user_id)
+                return AuthUser.from_cookie(cookie)
             except UserCreationError as e:
                 # container auth or other auth functions that create users on
                 # the fly can throw UserCreationError to signal issues with
@@ -400,14 +400,6 @@
                 # exception object.
                 from kallithea.lib import helpers as h
                 h.flash(e, 'error', logf=log.error)
-            else:
-                authenticated = cookie_store.get('is_authenticated')
-
-                if not auth_user.is_authenticated and auth_user.user_id is not None:
-                    # user is not authenticated and not empty
-                    auth_user.set_authenticated(authenticated)
-
-                return auth_user
 
         # Authenticate by auth_container plugin (if enabled)
         if any(