changeset 5264:bf1fc4c84e5f

BaseController: enable container authentication on all pages Previously, user had to visit the login page to log in using container authentication; this now happens on every page load, unless user has an existing login session. The container authentication result is cached in session on success.
author Søren Løvborg <kwi@kwi.dk>
date Tue, 14 Jul 2015 13:59:59 +0200
parents 64eba8fcde2b
children 8394211b1c32
files kallithea/controllers/login.py kallithea/lib/base.py kallithea/tests/functional/test_admin_auth_settings.py
diffstat 3 files changed, 85 insertions(+), 20 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
@@ -38,7 +38,6 @@
 
 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, log_in_user, render
 from kallithea.lib.exceptions import UserCreationError
 from kallithea.lib.utils2 import safe_str
@@ -120,24 +119,6 @@
                 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()
-        if any((importplugin(name).is_container_auth for name in auth_plugins)):
-            from kallithea.lib import auth_modules
-            try:
-                auth_info = auth_modules.authenticate('', '', request.environ)
-            except UserCreationError, e:
-                log.error(e)
-                h.flash(e, 'error')
-                # render login, with flash message about limit
-                return render('/login.html')
-
-            if auth_info:
-                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')
 
     @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate',
--- 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
@@ -109,6 +109,8 @@
     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.
+
+    Returns populated `AuthUser` object.
     """
     user.update_lastlogin()
     meta.Session().commit()
@@ -134,6 +136,8 @@
     # dumps session attrs back to cookie
     session._update_cookie_out()
 
+    return auth_user
+
 
 class BasicAuth(paste.auth.basic.AuthBasicAuthenticator):
 
@@ -395,7 +399,7 @@
                 # user creation. Explanation should be provided in the
                 # exception object.
                 from kallithea.lib import helpers as h
-                h.flash(e, 'error')
+                h.flash(e, 'error', logf=log.error)
             else:
                 authenticated = cookie_store.get('is_authenticated')
 
@@ -405,6 +409,22 @@
 
                 return auth_user
 
+        # Authenticate by auth_container plugin (if enabled)
+        if any(
+            auth_modules.importplugin(name).is_container_auth
+            for name in Setting.get_auth_plugins()
+        ):
+            try:
+                auth_info = auth_modules.authenticate('', '', request.environ)
+            except UserCreationError as e:
+                from kallithea.lib import helpers as h
+                h.flash(e, 'error', logf=log.error)
+            else:
+                if auth_info:
+                    username = auth_info['username']
+                    user = User.get_by_username(username, case_insensitive=True)
+                    return log_in_user(user, remember=False)
+
         # User is anonymous
         return AuthUser()
 
--- a/kallithea/tests/functional/test_admin_auth_settings.py	Tue Jul 14 13:59:59 2015 +0200
+++ b/kallithea/tests/functional/test_admin_auth_settings.py	Tue Jul 14 13:59:59 2015 +0200
@@ -111,3 +111,67 @@
 
     def test_ldap_login_incorrect(self):
         pass
+
+    def _container_auth_setup(self, **settings):
+        self.log_user()
+
+        params = self._enable_plugins('kallithea.lib.auth_modules.auth_internal,kallithea.lib.auth_modules.auth_container')
+        params.update(settings)
+
+        test_url = url(controller='admin/auth_settings',
+                       action='auth_settings')
+
+        response = self.app.post(url=test_url, params=params)
+        response = response.follow()
+        response.click('Log Out') # end admin login session
+
+    def _container_auth_verify_login(self, resulting_username, **get_kwargs):
+        response = self.app.get(
+            url=url(controller='admin/my_account', action='my_account'),
+            **get_kwargs
+        )
+        response.mustcontain('My Account %s' % resulting_username)
+
+    def test_container_auth_login_header(self):
+        self._container_auth_setup(
+            auth_container_header='THE_USER_NAME',
+            auth_container_fallback_header='',
+            auth_container_clean_username='False',
+        )
+        self._container_auth_verify_login(
+            extra_environ={'THE_USER_NAME': 'john@example.org'},
+            resulting_username='john@example.org',
+        )
+
+    def test_container_auth_login_fallback_header(self):
+        self._container_auth_setup(
+            auth_container_header='THE_USER_NAME',
+            auth_container_fallback_header='HTTP_X_YZZY',
+            auth_container_clean_username='False',
+        )
+        self._container_auth_verify_login(
+            headers={'X-Yzzy': r'foo\bar'},
+            resulting_username=r'foo\bar',
+        )
+
+    def test_container_auth_clean_username_at(self):
+        self._container_auth_setup(
+            auth_container_header='REMOTE_USER',
+            auth_container_fallback_header='',
+            auth_container_clean_username='True',
+        )
+        self._container_auth_verify_login(
+            extra_environ={'REMOTE_USER': 'john@example.org'},
+            resulting_username='john',
+        )
+
+    def test_container_auth_clean_username_backslash(self):
+        self._container_auth_setup(
+            auth_container_header='REMOTE_USER',
+            auth_container_fallback_header='',
+            auth_container_clean_username='True',
+        )
+        self._container_auth_verify_login(
+            extra_environ={'REMOTE_USER': r'example\jane'},
+            resulting_username=r'jane',
+        )