1 """user authentication component |
1 """user authentication component |
2 |
2 |
3 :organization: Logilab |
3 :organization: Logilab |
4 :copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
4 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
6 """ |
6 """ |
7 __docformat__ = "restructuredtext en" |
7 __docformat__ = "restructuredtext en" |
8 |
8 |
9 from logilab.common.decorators import clear_cache |
9 from logilab.common.decorators import clear_cache |
10 |
10 |
11 from cubicweb import AuthenticationError, BadConnectionId |
11 from cubicweb import AuthenticationError, BadConnectionId |
12 from cubicweb.dbapi import repo_connect, ConnectionProperties |
12 from cubicweb.dbapi import repo_connect, ConnectionProperties |
13 from cubicweb.web import ExplicitLogin, InvalidSession |
13 from cubicweb.web import ExplicitLogin, InvalidSession |
14 from cubicweb.web.application import AbstractAuthenticationManager |
14 from cubicweb.web.application import AbstractAuthenticationManager |
15 |
15 |
16 |
16 |
17 class RepositoryAuthenticationManager(AbstractAuthenticationManager): |
17 class RepositoryAuthenticationManager(AbstractAuthenticationManager): |
18 """authenticate user associated to a request and check session validity""" |
18 """authenticate user associated to a request and check session validity""" |
19 |
19 |
20 def __init__(self): |
20 def __init__(self): |
21 self.repo = self.config.repository(self.vreg) |
21 self.repo = self.config.repository(self.vreg) |
22 self.log_queries = self.config['query-log-file'] |
22 self.log_queries = self.config['query-log-file'] |
23 |
23 |
24 def validate_session(self, req, session): |
24 def validate_session(self, req, session): |
49 else: |
49 else: |
50 raise InvalidSession('bad connection id') |
50 raise InvalidSession('bad connection id') |
51 # associate the connection to the current request |
51 # associate the connection to the current request |
52 req.set_connection(cnx, user) |
52 req.set_connection(cnx, user) |
53 return cnx |
53 return cnx |
54 |
54 |
|
55 def login_from_email(self, login): |
|
56 # XXX should not be called from web interface |
|
57 session = self.repo.internal_session() |
|
58 try: |
|
59 rset = session.execute('Any L WHERE U login L, U primary_email M, ' |
|
60 'M address %(login)s', {'login': login}) |
|
61 if rset.rowcount == 1: |
|
62 login = rset[0][0] |
|
63 finally: |
|
64 session.close() |
|
65 return login |
|
66 |
55 def authenticate(self, req, _login=None, _password=None): |
67 def authenticate(self, req, _login=None, _password=None): |
56 """authenticate user and return corresponding user object |
68 """authenticate user and return corresponding user object |
57 |
69 |
58 :raise ExplicitLogin: if authentication is required (no authentication |
70 :raise ExplicitLogin: if authentication is required (no authentication |
59 info found or wrong user/password) |
71 info found or wrong user/password) |
60 |
72 |
61 Note: this method is violating AuthenticationManager interface by |
73 Note: this method is violating AuthenticationManager interface by |
62 returning a session instance instead of the user. This is expected by |
74 returning a session instance instead of the user. This is expected by |
64 """ |
76 """ |
65 if _login is not None: |
77 if _login is not None: |
66 login, password = _login, _password |
78 login, password = _login, _password |
67 else: |
79 else: |
68 login, password = req.get_authorization() |
80 login, password = req.get_authorization() |
|
81 if self.vreg.config['allow-email-login'] and '@' in (login or u''): |
|
82 login = self.login_from_email(login) |
69 if not login: |
83 if not login: |
70 # No session and no login -> try anonymous |
84 # No session and no login -> try anonymous |
71 login, password = self.vreg.config.anonymous_user() |
85 login, password = self.vreg.config.anonymous_user() |
72 if not login: # anonymous not authorized |
86 if not login: # anonymous not authorized |
73 raise ExplicitLogin() |
87 raise ExplicitLogin() |