move login by email functionnality on the repository side to avoid buggy call to internal_session from the web interface side stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 06 Jul 2009 09:34:40 +0200
branchstable
changeset 2267 e1d2df3f1091
parent 2266 efc6de279644
child 2268 2f336fd5e040
move login by email functionnality on the repository side to avoid buggy call to internal_session from the web interface side
cwconfig.py
server/repository.py
web/test/unittest_application.py
web/views/authentication.py
web/webconfig.py
--- a/cwconfig.py	Mon Jul 06 09:33:36 2009 +0200
+++ b/cwconfig.py	Mon Jul 06 09:34:40 2009 +0200
@@ -194,6 +194,12 @@
           'help': 'web server root url',
           'group': 'main', 'inputlevel': 1,
           }),
+        ('allow-email-login',
+         {'type' : 'yn',
+          'default': False,
+          'help': 'allow users to login with their primary email if set',
+          'group': 'main', 'inputlevel': 2,
+          }),
         ('use-request-subdomain',
          {'type' : 'yn',
           'default': None,
--- a/server/repository.py	Mon Jul 06 09:33:36 2009 +0200
+++ b/server/repository.py	Mon Jul 06 09:34:40 2009 +0200
@@ -392,10 +392,23 @@
         except ZeroDivisionError:
             pass
 
+    def _login_from_email(self, login):
+        session = self.internal_session()
+        try:
+            rset = session.execute('Any L WHERE U login L, U primary_email M, '
+                                   'M address %(login)s', {'login': login})
+            if rset.rowcount == 1:
+                login = rset[0][0]
+        finally:
+            session.close()
+        return login
+
     def authenticate_user(self, session, login, password):
         """validate login / password, raise AuthenticationError on failure
         return associated CWUser instance on success
         """
+        if self.vreg.config['allow-email-login'] and '@' in login:
+            login = self._login_from_email(login)
         for source in self.sources:
             if source.support_entity('CWUser'):
                 try:
--- a/web/test/unittest_application.py	Mon Jul 06 09:33:36 2009 +0200
+++ b/web/test/unittest_application.py	Mon Jul 06 09:34:40 2009 +0200
@@ -307,7 +307,7 @@
         self.assertEquals(cnx.password, origcnx.password)
         self.assertEquals(cnx.anonymous_connection, False)
         self.assertEquals(path, 'view')
-        self.assertEquals(params, {'__message': 'welcome %s !' % origcnx.login})
+        self.assertEquals(params, {'__message': 'welcome %s !' % cnx.user().login})
 
     def _test_auth_fail(self, req):
         self.assertRaises(AuthenticationError, self.app.connect, req)
@@ -351,8 +351,8 @@
         req.form['__password'] = origcnx.password
         self._test_auth_fail(req)
         # option allow-email-login set
+        origcnx.login = address
         self.set_option('allow-email-login', True)
-        req, origcnx = self._init_auth('cookie')
         req.form['__login'] = address
         req.form['__password'] = origcnx.password
         self._test_auth_succeed(req, origcnx)
--- a/web/views/authentication.py	Mon Jul 06 09:33:36 2009 +0200
+++ b/web/views/authentication.py	Mon Jul 06 09:34:40 2009 +0200
@@ -36,7 +36,10 @@
             # calling cnx.user() check connection validity, raise
             # BadConnectionId on failure
             user = cnx.user(req)
-            if login and user.login != login:
+            # check cnx.login and not user.login, since in case of login by
+            # email, login and cnx.login are the email while user.login is the
+            # actual user login
+            if login and cnx.login != login:
                 cnx.close()
                 raise InvalidSession('login mismatch')
         except BadConnectionId:
@@ -53,18 +56,6 @@
         req.set_connection(cnx, user)
         return cnx
 
-    def login_from_email(self, login):
-        # XXX should not be called from web interface
-        session = self.repo.internal_session()
-        try:
-            rset = session.execute('Any L WHERE U login L, U primary_email M, '
-                                   'M address %(login)s', {'login': login})
-            if rset.rowcount == 1:
-                login = rset[0][0]
-        finally:
-            session.close()
-        return login
-
     def authenticate(self, req, _login=None, _password=None):
         """authenticate user and return corresponding user object
 
@@ -79,8 +70,6 @@
             login, password = _login, _password
         else:
             login, password = req.get_authorization()
-        if self.vreg.config['allow-email-login'] and '@' in (login or u''):
-            login = self.login_from_email(login)
         if not login:
             # No session and no login -> try anonymous
             login, password = self.vreg.config.anonymous_user()
--- a/web/webconfig.py	Mon Jul 06 09:33:36 2009 +0200
+++ b/web/webconfig.py	Mon Jul 06 09:34:40 2009 +0200
@@ -80,12 +80,6 @@
           'if anonymous-user is set',
           'group': 'main', 'inputlevel': 1,
           }),
-        ('allow-email-login',
-         {'type' : 'yn',
-          'default': False,
-          'help': 'allow users to login with their primary email if set',
-          'group': 'main', 'inputlevel': 2,
-          }),
         ('query-log-file',
          {'type' : 'string',
           'default': None,