changeset 5256:c5ff0bfefdf8

log_in_user: extract user session setup from LoginController The next changeset will need to set up a user login session outside LoginController. 'log_in_user' extracted and added as a top-level function in kallithea.lib.base since the code doesn't need access to the current controller. Code refactored to take a User object instead of a username, to allow callers flexibility in how the user should be looked up.
author Søren Løvborg <kwi@kwi.dk>
date Tue, 14 Jul 2015 13:59:59 +0200
parents ad70180effaf
children a45113998d07
files kallithea/controllers/login.py kallithea/lib/base.py
diffstat 2 files changed, 41 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/controllers/login.py	Tue Jul 14 13:59:59 2015 +0200
+++ b/kallithea/controllers/login.py	Tue Jul 14 13:59:59 2015 +0200
@@ -28,7 +28,6 @@
 
 import logging
 import formencode
-import datetime
 import urlparse
 
 from formencode import htmlfill
@@ -40,7 +39,7 @@
 import kallithea.lib.helpers as h
 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator
 from kallithea.lib.auth_modules import importplugin
-from kallithea.lib.base import BaseController, render
+from kallithea.lib.base import BaseController, log_in_user, render
 from kallithea.lib.exceptions import UserCreationError
 from kallithea.lib.utils2 import safe_str
 from kallithea.model.db import User, Setting
@@ -57,29 +56,6 @@
     def __before__(self):
         super(LoginController, self).__before__()
 
-    def _store_user_in_session(self, username, remember=False):
-        user = User.get_by_username(username, case_insensitive=True)
-        auth_user = AuthUser(user.user_id)
-        auth_user.set_authenticated()
-        cs = auth_user.get_cookie_store()
-        session['authuser'] = cs
-        user.update_lastlogin()
-        Session().commit()
-
-        # If they want to be remembered, update the cookie
-        if remember:
-            _year = (datetime.datetime.now() +
-                     datetime.timedelta(seconds=60 * 60 * 24 * 365))
-            session._set_cookie_expires(_year)
-
-        session.save()
-
-        log.info('user %s is now authenticated and stored in '
-                 'session, session attrs %s' % (username, cs))
-
-        # dumps session attrs back to cookie
-        session._update_cookie_out()
-
     def _validate_came_from(self, came_from):
         """Return True if came_from is valid and can and should be used"""
         if not came_from:
@@ -119,14 +95,10 @@
             # import Login Form validator class
             login_form = LoginForm()
             try:
-                session.invalidate()
                 c.form_result = login_form.to_python(dict(request.POST))
                 # form checks for username/password, now we're authenticated
-                self._store_user_in_session(
-                                        username=c.form_result['username'],
-                                        remember=c.form_result['remember'])
-                return self._redirect_to_origin(c.came_from)
-
+                username = c.form_result['username']
+                user = User.get_by_username(username, case_insensitive=True)
             except formencode.Invalid, errors:
                 defaults = errors.value
                 # remove password from filling in form again
@@ -144,6 +116,9 @@
                 # with user creation, explanation should be provided in
                 # Exception itself
                 h.flash(e, 'error')
+            else:
+                log_in_user(user, c.form_result['remember'])
+                return self._redirect_to_origin(c.came_from)
 
         # check if we use container plugin, and try to login using it.
         auth_plugins = Setting.get_auth_plugins()
@@ -158,7 +133,9 @@
                 return render('/login.html')
 
             if auth_info:
-                self._store_user_in_session(auth_info.get('username'))
+                username = auth_info.get('username')
+                user = User.get_by_username(username, case_insensitive=True)
+                log_in_user(user, remember=False)
                 return self._redirect_to_origin(c.came_from)
 
         return render('/login.html')
--- a/kallithea/lib/base.py	Tue Jul 14 13:59:59 2015 +0200
+++ b/kallithea/lib/base.py	Tue Jul 14 13:59:59 2015 +0200
@@ -28,6 +28,7 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import datetime
 import logging
 import time
 import traceback
@@ -103,6 +104,37 @@
     return path
 
 
+def log_in_user(user, remember):
+    """
+    Log a `User` in and update session and cookies. If `remember` is True,
+    the session cookie is set to expire in a year; otherwise, it expires at
+    the end of the browser session.
+    """
+    user.update_lastlogin()
+    meta.Session().commit()
+
+    auth_user = AuthUser(user_id=user.user_id)
+    auth_user.set_authenticated()
+
+    # Start new session to prevent session fixation attacks.
+    session.invalidate()
+    cs = auth_user.get_cookie_store()
+    session['authuser'] = cs
+
+    # If they want to be remembered, update the cookie
+    if remember:
+        t = datetime.datetime.now() + datetime.timedelta(days=365)
+        session._set_cookie_expires(t)
+
+    session.save()
+
+    log.info('user %s is now authenticated and stored in '
+             'session, session attrs %s', user.username, cs)
+
+    # dumps session attrs back to cookie
+    session._update_cookie_out()
+
+
 class BasicAuth(paste.auth.basic.AuthBasicAuthenticator):
 
     def __init__(self, realm, authfunc, auth_http_code=None):