author | Sylvain Thénault <sylvain.thenault@logilab.fr> |
Thu, 21 Oct 2010 08:23:38 +0200 | |
changeset 6570 | 7e9a1a5919e8 |
parent 6427 | c8a5ac2d1eaa |
child 6582 | 8eb7883b4223 |
permissions | -rw-r--r-- |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
1 |
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
2 |
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
3 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
4 |
# This file is part of CubicWeb. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
5 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
6 |
# CubicWeb is free software: you can redistribute it and/or modify it under the |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
7 |
# terms of the GNU Lesser General Public License as published by the Free |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
8 |
# Software Foundation, either version 2.1 of the License, or (at your option) |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
9 |
# any later version. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
10 |
# |
5424
8ecbcbff9777
replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5421
diff
changeset
|
11 |
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
12 |
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
13 |
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
14 |
# details. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
15 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
16 |
# You should have received a copy of the GNU Lesser General Public License along |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5377
diff
changeset
|
17 |
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
5722
61d6a4caa963
[iprogress] move adapter to entities.adapters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5655
diff
changeset
|
18 |
"""CubicWeb web client application object""" |
0 | 19 |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
20 |
from __future__ import with_statement |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
21 |
|
0 | 22 |
__docformat__ = "restructuredtext en" |
23 |
||
24 |
import sys |
|
25 |
from time import clock, time |
|
26 |
||
2613
5e19c2bb370e
R [all] logilab.common 0.44 provides only deprecated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
2476
diff
changeset
|
27 |
from logilab.common.deprecation import deprecated |
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
28 |
|
0 | 29 |
from rql import BadRQLQuery |
30 |
||
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
31 |
from cubicweb import set_log_methods, cwvreg |
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
32 |
from cubicweb import ( |
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
33 |
ValidationError, Unauthorized, AuthenticationError, NoSelectableObject, |
6012
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
34 |
RepositoryError, BadConnectionId, CW_EVENT_MANAGER) |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
35 |
from cubicweb.dbapi import DBAPISession |
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
36 |
from cubicweb.web import LOGGER, component |
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
37 |
from cubicweb.web import ( |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
38 |
StatusResponse, DirectResponse, Redirect, NotFound, LogOut, |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
39 |
RemoteCallFailed, InvalidSession, RequestError) |
0 | 40 |
|
41 |
# make session manager available through a global variable so the debug view can |
|
42 |
# print information about web session |
|
43 |
SESSION_MANAGER = None |
|
44 |
||
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
45 |
class AbstractSessionManager(component.Component): |
0 | 46 |
"""manage session data associated to a session identifier""" |
3408
c92170fca813
[api] use __regid__ instead of deprecated id
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2887
diff
changeset
|
47 |
__regid__ = 'sessionmanager' |
1426 | 48 |
|
2887
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
49 |
def __init__(self, vreg): |
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
50 |
self.session_time = vreg.config['http-session-time'] or None |
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
51 |
self.authmanager = vreg['components'].select('authmanager', vreg=vreg) |
6012
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
52 |
interval = (self.session_time or 0) / 2. |
5325
f1c660e1169e
[web] consistent cleanup session interval time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5283
diff
changeset
|
53 |
if vreg.config.anonymous_user() is not None: |
6012
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
54 |
self.cleanup_anon_session_time = vreg.config['cleanup-anonymous-session-time'] or 5 * 60 |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
55 |
assert self.cleanup_anon_session_time > 0 |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
56 |
if self.session_time is not None: |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
57 |
self.cleanup_anon_session_time = min(self.session_time, |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
58 |
self.cleanup_anon_session_time) |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
59 |
interval = self.cleanup_anon_session_time / 2. |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
60 |
# we don't want to check session more than once every 5 minutes |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
61 |
self.clean_sessions_interval = max(5 * 60, interval) |
1426 | 62 |
|
0 | 63 |
def clean_sessions(self): |
64 |
"""cleanup sessions which has not been unused since a given amount of |
|
65 |
time. Return the number of sessions which have been closed. |
|
66 |
""" |
|
67 |
self.debug('cleaning http sessions') |
|
6012
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
68 |
session_time = self.session_time |
0 | 69 |
closed, total = 0, 0 |
70 |
for session in self.current_sessions(): |
|
71 |
total += 1 |
|
6012
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
72 |
try: |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
73 |
last_usage_time = session.cnx.check() |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
74 |
except BadConnectionId: |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
75 |
self.close_session(session) |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
76 |
closed += 1 |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
77 |
else: |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
78 |
no_use_time = (time() - last_usage_time) |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
79 |
if session.anonymous_session: |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
80 |
if no_use_time >= self.cleanup_anon_session_time: |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
81 |
self.close_session(session) |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
82 |
closed += 1 |
d56fd78006cd
[session] cleanup session-time / cleanup-session-time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
83 |
elif session_time is not None and no_use_time >= session_time: |
0 | 84 |
self.close_session(session) |
85 |
closed += 1 |
|
86 |
return closed, total - closed |
|
1426 | 87 |
|
0 | 88 |
def current_sessions(self): |
89 |
"""return currently open sessions""" |
|
90 |
raise NotImplementedError() |
|
1426 | 91 |
|
0 | 92 |
def get_session(self, req, sessionid): |
93 |
"""return existing session for the given session identifier""" |
|
94 |
raise NotImplementedError() |
|
95 |
||
96 |
def open_session(self, req): |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
97 |
"""open and return a new session for the given request. The session is |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
98 |
also bound to the request. |
1426 | 99 |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
100 |
raise :exc:`cubicweb.AuthenticationError` if authentication failed |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
101 |
(no authentication info found or wrong user/password) |
0 | 102 |
""" |
103 |
raise NotImplementedError() |
|
1426 | 104 |
|
0 | 105 |
def close_session(self, session): |
106 |
"""close session on logout or on invalid session detected (expired out, |
|
107 |
corrupted...) |
|
108 |
""" |
|
109 |
raise NotImplementedError() |
|
110 |
||
111 |
||
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
112 |
class AbstractAuthenticationManager(component.Component): |
0 | 113 |
"""authenticate user associated to a request and check session validity""" |
114 |
id = 'authmanager' |
|
2887
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
115 |
vreg = None # XXX necessary until property for deprecation warning is on appobject |
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
116 |
|
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
117 |
def __init__(self, vreg): |
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
118 |
self.vreg = vreg |
0 | 119 |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
120 |
def validate_session(self, req, session): |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
121 |
"""check session validity, reconnecting it to the repository if the |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
122 |
associated connection expired in the repository side (hence the |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
123 |
necessity for this method). |
1426 | 124 |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
125 |
raise :exc:`InvalidSession` if session is corrupted for a reason or |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
126 |
another and should be closed |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
127 |
""" |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
128 |
raise NotImplementedError() |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
129 |
|
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
130 |
def authenticate(self, req): |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
131 |
"""authenticate user using connection information found in the request, |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
132 |
and return corresponding a :class:`~cubicweb.dbapi.Connection` instance, |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
133 |
as well as login and authentication information dictionary used to open |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
134 |
the connection. |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
135 |
|
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
136 |
raise :exc:`cubicweb.AuthenticationError` if authentication failed |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
137 |
(no authentication info found or wrong user/password) |
0 | 138 |
""" |
139 |
raise NotImplementedError() |
|
140 |
||
1426 | 141 |
|
0 | 142 |
class CookieSessionHandler(object): |
143 |
"""a session handler using a cookie to store the session identifier |
|
144 |
||
145 |
:cvar SESSION_VAR: |
|
146 |
string giving the name of the variable used to store the session |
|
147 |
identifier |
|
148 |
""" |
|
149 |
SESSION_VAR = '__session' |
|
1426 | 150 |
|
0 | 151 |
def __init__(self, appli): |
2706
09baf5175196
[web session] proper reloading of the session manager on vreg update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2705
diff
changeset
|
152 |
self.vreg = appli.vreg |
2887
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
153 |
self.session_manager = self.vreg['components'].select('sessionmanager', |
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
154 |
vreg=self.vreg) |
0 | 155 |
global SESSION_MANAGER |
156 |
SESSION_MANAGER = self.session_manager |
|
2706
09baf5175196
[web session] proper reloading of the session manager on vreg update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2705
diff
changeset
|
157 |
if not 'last_login_time' in self.vreg.schema: |
0 | 158 |
self._update_last_login_time = lambda x: None |
5000
f1a10b41417a
[test] don't try to reset session manager during test,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4914
diff
changeset
|
159 |
if self.vreg.config.mode != 'test': |
f1a10b41417a
[test] don't try to reset session manager during test,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4914
diff
changeset
|
160 |
# don't try to reset session manager during test, this leads to |
f1a10b41417a
[test] don't try to reset session manager during test,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4914
diff
changeset
|
161 |
# weird failures when running multiple tests |
f1a10b41417a
[test] don't try to reset session manager during test,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4914
diff
changeset
|
162 |
CW_EVENT_MANAGER.bind('after-registry-reload', |
f1a10b41417a
[test] don't try to reset session manager during test,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4914
diff
changeset
|
163 |
self.reset_session_manager) |
2706
09baf5175196
[web session] proper reloading of the session manager on vreg update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2705
diff
changeset
|
164 |
|
09baf5175196
[web session] proper reloading of the session manager on vreg update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2705
diff
changeset
|
165 |
def reset_session_manager(self): |
09baf5175196
[web session] proper reloading of the session manager on vreg update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2705
diff
changeset
|
166 |
data = self.session_manager.dump_data() |
2887
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
167 |
self.session_manager = self.vreg['components'].select('sessionmanager', |
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
168 |
vreg=self.vreg) |
2706
09baf5175196
[web session] proper reloading of the session manager on vreg update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2705
diff
changeset
|
169 |
self.session_manager.restore_data(data) |
09baf5175196
[web session] proper reloading of the session manager on vreg update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2705
diff
changeset
|
170 |
global SESSION_MANAGER |
09baf5175196
[web session] proper reloading of the session manager on vreg update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2705
diff
changeset
|
171 |
SESSION_MANAGER = self.session_manager |
0 | 172 |
|
5325
f1c660e1169e
[web] consistent cleanup session interval time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5283
diff
changeset
|
173 |
@property |
f1c660e1169e
[web] consistent cleanup session interval time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5283
diff
changeset
|
174 |
def clean_sessions_interval(self): |
f1c660e1169e
[web] consistent cleanup session interval time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5283
diff
changeset
|
175 |
return self.session_manager.clean_sessions_interval |
f1c660e1169e
[web] consistent cleanup session interval time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5283
diff
changeset
|
176 |
|
0 | 177 |
def clean_sessions(self): |
178 |
"""cleanup sessions which has not been unused since a given amount of |
|
179 |
time |
|
180 |
""" |
|
181 |
self.session_manager.clean_sessions() |
|
1426 | 182 |
|
0 | 183 |
def set_session(self, req): |
184 |
"""associate a session to the request |
|
185 |
||
186 |
Session id is searched from : |
|
187 |
- # form variable |
|
188 |
- cookie |
|
189 |
||
190 |
if no session id is found, open a new session for the connected user |
|
191 |
or request authentification as needed |
|
192 |
||
6109
47d9c0e0f7b7
integrate Celso's work on translation file: proper/complete spanish translation, fixed some typos in french translation, occured -> occurred fix in various places
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5868
diff
changeset
|
193 |
:raise Redirect: if authentication has occurred and succeed |
0 | 194 |
""" |
195 |
cookie = req.get_cookie() |
|
196 |
try: |
|
197 |
sessionid = str(cookie[self.SESSION_VAR].value) |
|
198 |
except KeyError: # no session cookie |
|
199 |
session = self.open_session(req) |
|
200 |
else: |
|
201 |
try: |
|
202 |
session = self.get_session(req, sessionid) |
|
203 |
except InvalidSession: |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
204 |
# try to open a new session, so we get an anonymous session if |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
205 |
# allowed |
0 | 206 |
try: |
207 |
session = self.open_session(req) |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
208 |
except AuthenticationError: |
0 | 209 |
req.remove_cookie(cookie, self.SESSION_VAR) |
210 |
raise |
|
211 |
||
212 |
def get_session(self, req, sessionid): |
|
213 |
return self.session_manager.get_session(req, sessionid) |
|
1426 | 214 |
|
0 | 215 |
def open_session(self, req): |
216 |
session = self.session_manager.open_session(req) |
|
217 |
cookie = req.get_cookie() |
|
218 |
cookie[self.SESSION_VAR] = session.sessionid |
|
6570
7e9a1a5919e8
#1346310: Add `Secure` attribute to cookie when navigating on https
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
219 |
if req.https: |
7e9a1a5919e8
#1346310: Add `Secure` attribute to cookie when navigating on https
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
220 |
cookie[self.SESSION_VAR]['secure'] = True |
0 | 221 |
req.set_cookie(cookie, self.SESSION_VAR, maxage=None) |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
222 |
if not session.anonymous_session: |
0 | 223 |
self._postlogin(req) |
224 |
return session |
|
225 |
||
226 |
def _update_last_login_time(self, req): |
|
5587
72679e450f6d
[web] dont attempt to update last login time on ldap users, avoiding spurious tb in logs (closes #914464)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5584
diff
changeset
|
227 |
# XXX should properly detect missing permission / non writeable source |
72679e450f6d
[web] dont attempt to update last login time on ldap users, avoiding spurious tb in logs (closes #914464)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5584
diff
changeset
|
228 |
# and avoid "except (RepositoryError, Unauthorized)" below |
6427
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6333
diff
changeset
|
229 |
if req.user.cw_metainformation()['source']['type'] == 'ldapuser': |
5587
72679e450f6d
[web] dont attempt to update last login time on ldap users, avoiding spurious tb in logs (closes #914464)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5584
diff
changeset
|
230 |
return |
0 | 231 |
try: |
232 |
req.execute('SET X last_login_time NOW WHERE X eid %(x)s', |
|
5174
78438ad513ca
#759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5000
diff
changeset
|
233 |
{'x' : req.user.eid}) |
0 | 234 |
req.cnx.commit() |
235 |
except (RepositoryError, Unauthorized): |
|
236 |
req.cnx.rollback() |
|
237 |
except: |
|
238 |
req.cnx.rollback() |
|
239 |
raise |
|
1426 | 240 |
|
0 | 241 |
def _postlogin(self, req): |
242 |
"""postlogin: the user has been authenticated, redirect to the original |
|
243 |
page (index by default) with a welcome message |
|
244 |
""" |
|
245 |
# Update last connection date |
|
246 |
# XXX: this should be in a post login hook in the repository, but there |
|
247 |
# we can't differentiate actual login of automatic session |
|
248 |
# reopening. Is it actually a problem? |
|
249 |
self._update_last_login_time(req) |
|
250 |
args = req.form |
|
4639
82afdc7d8cd8
cleanup internal forms parameters in postlogin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4490
diff
changeset
|
251 |
for forminternal_key in ('__form_id', '__domid', '__errorurl'): |
82afdc7d8cd8
cleanup internal forms parameters in postlogin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4490
diff
changeset
|
252 |
args.pop(forminternal_key, None) |
0 | 253 |
args['__message'] = req._('welcome %s !') % req.user.login |
254 |
if 'vid' in req.form: |
|
255 |
args['vid'] = req.form['vid'] |
|
256 |
if 'rql' in req.form: |
|
257 |
args['rql'] = req.form['rql'] |
|
258 |
path = req.relative_path(False) |
|
259 |
if path == 'login': |
|
260 |
path = 'view' |
|
261 |
raise Redirect(req.build_url(path, **args)) |
|
1426 | 262 |
|
4911
898c35be5873
#750055: make it easier to change post logout url
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4709
diff
changeset
|
263 |
def logout(self, req, goto_url): |
2476
1294a6bdf3bf
application -> instance where it makes sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2293
diff
changeset
|
264 |
"""logout from the instance by cleaning the session and raising |
0 | 265 |
`AuthenticationError` |
266 |
""" |
|
5494
f3bb53f1737c
[web session] fix potential key error on logout (occurs once the session has been transparently reconnected, hence session.sessionid and session.cnx.sessionid differs)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
267 |
self.session_manager.close_session(req.session) |
0 | 268 |
req.remove_cookie(req.get_cookie(), self.SESSION_VAR) |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
269 |
raise LogOut(url=goto_url) |
0 | 270 |
|
271 |
||
272 |
class CubicWebPublisher(object): |
|
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
273 |
"""the publisher is a singleton hold by the web frontend, and is responsible |
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
274 |
to publish HTTP request. |
0 | 275 |
""" |
1426 | 276 |
|
5442
3ed8afbbdf70
[webconfig] refactor/cleanup debug mode management on startup: simply use config.debugmode instead of debug argument everywhere...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
277 |
def __init__(self, config, |
0 | 278 |
session_handler_fact=CookieSessionHandler, |
279 |
vreg=None): |
|
4484
d87989d91635
fix duplicated vregistry initialization during tests
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
280 |
self.info('starting web instance from %s', config.apphome) |
0 | 281 |
if vreg is None: |
5442
3ed8afbbdf70
[webconfig] refactor/cleanup debug mode management on startup: simply use config.debugmode instead of debug argument everywhere...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
282 |
vreg = cwvreg.CubicWebVRegistry(config) |
0 | 283 |
self.vreg = vreg |
4484
d87989d91635
fix duplicated vregistry initialization during tests
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
284 |
# connect to the repository and get instance's schema |
0 | 285 |
self.repo = config.repository(vreg) |
286 |
if not vreg.initialized: |
|
5650
86e874fe30ea
[web] cleanup use of config in web application initialisation
Julien Jehannet <julien.jehannet@logilab.fr>
parents:
5587
diff
changeset
|
287 |
config.init_cubes(self.repo.get_cubes()) |
0 | 288 |
vreg.init_properties(self.repo.properties()) |
4484
d87989d91635
fix duplicated vregistry initialization during tests
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
289 |
vreg.set_schema(self.repo.get_schema()) |
0 | 290 |
# set the correct publish method |
291 |
if config['query-log-file']: |
|
292 |
from threading import Lock |
|
293 |
self._query_log = open(config['query-log-file'], 'a') |
|
294 |
self.publish = self.log_publish |
|
1426 | 295 |
self._logfile_lock = Lock() |
0 | 296 |
else: |
297 |
self._query_log = None |
|
298 |
self.publish = self.main_publish |
|
299 |
# instantiate session and url resolving helpers |
|
300 |
self.session_handler = session_handler_fact(self) |
|
2685
0518ca8f63e3
[autoreload] recompute urlresolver / urlrewriter after autoreload
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2666
diff
changeset
|
301 |
self.set_urlresolver() |
2705
30bcdbd92820
[events] renamed source-reload into registry-reload to avoid potential confusions with datasources
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2685
diff
changeset
|
302 |
CW_EVENT_MANAGER.bind('after-registry-reload', self.set_urlresolver) |
2685
0518ca8f63e3
[autoreload] recompute urlresolver / urlrewriter after autoreload
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2666
diff
changeset
|
303 |
|
0518ca8f63e3
[autoreload] recompute urlresolver / urlrewriter after autoreload
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2666
diff
changeset
|
304 |
def set_urlresolver(self): |
2887
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
305 |
self.url_resolver = self.vreg['components'].select('urlpublisher', |
1282dc6525c5
give vreg where we need it (eg no bound request)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2867
diff
changeset
|
306 |
vreg=self.vreg) |
1426 | 307 |
|
0 | 308 |
def connect(self, req): |
309 |
"""return a connection for a logged user object according to existing |
|
310 |
sessions (i.e. a new connection may be created or an already existing |
|
311 |
one may be reused |
|
312 |
""" |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
313 |
try: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
314 |
self.session_handler.set_session(req) |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
315 |
except AuthenticationError: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
316 |
req.set_session(DBAPISession(None)) |
0 | 317 |
|
318 |
# publish methods ######################################################### |
|
1426 | 319 |
|
0 | 320 |
def log_publish(self, path, req): |
321 |
"""wrapper around _publish to log all queries executed for a given |
|
322 |
accessed path |
|
323 |
""" |
|
324 |
try: |
|
325 |
return self.main_publish(path, req) |
|
326 |
finally: |
|
327 |
cnx = req.cnx |
|
5244
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
328 |
if cnx: |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
329 |
with self._logfile_lock: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
330 |
try: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
331 |
result = ['\n'+'*'*80] |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
332 |
result.append(req.url()) |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
333 |
result += ['%s %s -- (%.3f sec, %.3f CPU sec)' % q |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
334 |
for q in cnx.executed_queries] |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
335 |
cnx.executed_queries = [] |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
336 |
self._query_log.write('\n'.join(result).encode(req.encoding)) |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
337 |
self._query_log.flush() |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
338 |
except Exception: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
339 |
self.exception('error while logging queries') |
0 | 340 |
|
2788
8d3dbe577d3a
R put version info in deprecation warnings
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
2706
diff
changeset
|
341 |
@deprecated("[3.4] use vreg['controllers'].select(...)") |
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
342 |
def select_controller(self, oid, req): |
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
343 |
try: |
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
344 |
return self.vreg['controllers'].select(oid, req=req, appli=self) |
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
345 |
except NoSelectableObject: |
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
346 |
raise Unauthorized(req._('not authorized')) |
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
347 |
|
0 | 348 |
def main_publish(self, path, req): |
349 |
"""method called by the main publisher to process <path> |
|
1426 | 350 |
|
0 | 351 |
should return a string containing the resulting page or raise a |
352 |
`NotFound` exception |
|
353 |
||
354 |
:type path: str |
|
355 |
:param path: the path part of the url to publish |
|
1426 | 356 |
|
0 | 357 |
:type req: `web.Request` |
358 |
:param req: the request object |
|
359 |
||
360 |
:rtype: str |
|
361 |
:return: the result of the pusblished url |
|
362 |
""" |
|
363 |
path = path or 'view' |
|
364 |
# don't log form values they may contains sensitive information |
|
6318
de6264ac7c50
[publisher] add session id when logging published path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6273
diff
changeset
|
365 |
self.info('publish "%s" (%s, form params: %s)', |
de6264ac7c50
[publisher] add session id when logging published path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6273
diff
changeset
|
366 |
path, req.session.sessionid, req.form.keys()) |
0 | 367 |
# remove user callbacks on a new request (except for json controllers |
368 |
# to avoid callbacks being unregistered before they could be called) |
|
369 |
tstart = clock() |
|
5865
af414723598d
[publisher] avoid useless rollback after successful commit, which clutters debug logs and may also not be cost-free
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5721
diff
changeset
|
370 |
commited = False |
0 | 371 |
try: |
372 |
try: |
|
373 |
ctrlid, rset = self.url_resolver.process(req, path) |
|
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
374 |
try: |
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
375 |
controller = self.vreg['controllers'].select(ctrlid, req, |
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
376 |
appli=self) |
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
377 |
except NoSelectableObject: |
5584
c1823448f81d
[web] disallow authenticated users to access to the login form (closes #914873)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5494
diff
changeset
|
378 |
if ctrlid == 'login': |
c1823448f81d
[web] disallow authenticated users to access to the login form (closes #914873)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5494
diff
changeset
|
379 |
raise Unauthorized(req._('log out first')) |
2058
7ef12c03447c
nicer vreg api, try to make rset an optional named argument in select and derivated (including selectors)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
380 |
raise Unauthorized(req._('not authorized')) |
581
09f87f2c535e
update_search_state in the publisher since it should be done whatever the controller
sylvain.thenault@logilab.fr
parents:
168
diff
changeset
|
381 |
req.update_search_state() |
0 | 382 |
result = controller.publish(rset=rset) |
5244
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
383 |
if req.cnx: |
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
384 |
# no req.cnx if anonymous aren't allowed and we are |
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
385 |
# displaying some anonymous enabled view such as the cookie |
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
386 |
# authentication form |
0 | 387 |
req.cnx.commit() |
5865
af414723598d
[publisher] avoid useless rollback after successful commit, which clutters debug logs and may also not be cost-free
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5721
diff
changeset
|
388 |
commited = True |
0 | 389 |
except (StatusResponse, DirectResponse): |
5244
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
390 |
if req.cnx: |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
391 |
req.cnx.commit() |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
392 |
raise |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
393 |
except (AuthenticationError, LogOut): |
0 | 394 |
raise |
395 |
except Redirect: |
|
396 |
# redirect is raised by edit controller when everything went fine, |
|
397 |
# so try to commit |
|
398 |
try: |
|
4913
083b4d454192
server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents:
4897
diff
changeset
|
399 |
txuuid = req.cnx.commit() |
083b4d454192
server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents:
4897
diff
changeset
|
400 |
if txuuid is not None: |
083b4d454192
server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents:
4897
diff
changeset
|
401 |
msg = u'<span class="undo">[<a href="%s">%s</a>]</span>' %( |
083b4d454192
server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents:
4897
diff
changeset
|
402 |
req.build_url('undo', txuuid=txuuid), req._('undo')) |
083b4d454192
server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents:
4897
diff
changeset
|
403 |
req.append_to_redirect_message(msg) |
0 | 404 |
except ValidationError, ex: |
405 |
self.validation_error_handler(req, ex) |
|
406 |
except Unauthorized, ex: |
|
407 |
req.data['errmsg'] = req._('You\'re not authorized to access this page. ' |
|
408 |
'If you think you should, please contact the site administrator.') |
|
409 |
self.error_handler(req, ex, tb=False) |
|
410 |
except Exception, ex: |
|
411 |
self.error_handler(req, ex, tb=True) |
|
412 |
else: |
|
413 |
# delete validation errors which may have been previously set |
|
414 |
if '__errorurl' in req.form: |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
415 |
req.session.data.pop(req.form['__errorurl'], None) |
0 | 416 |
raise |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
417 |
except RemoteCallFailed, ex: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
418 |
req.set_header('content-type', 'application/json') |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
419 |
raise StatusResponse(500, ex.dumps()) |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
420 |
except NotFound: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
421 |
raise StatusResponse(404, self.notfound_content(req)) |
0 | 422 |
except ValidationError, ex: |
423 |
self.validation_error_handler(req, ex) |
|
2272
f27a3a75be0d
no tb for RequestError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2263
diff
changeset
|
424 |
except (Unauthorized, BadRQLQuery, RequestError), ex: |
0 | 425 |
self.error_handler(req, ex, tb=False) |
6272
bb546568e466
[publisher] with python>=2.5, we should catch BaseException here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6109
diff
changeset
|
426 |
except BaseException, ex: |
0 | 427 |
self.error_handler(req, ex, tb=True) |
5377
84d14ddfae13
[python2.6] prefer python2.6's builtin json module over simplejson
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents:
5326
diff
changeset
|
428 |
except: |
84d14ddfae13
[python2.6] prefer python2.6's builtin json module over simplejson
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents:
5326
diff
changeset
|
429 |
self.critical('Catch all triggered!!!') |
84d14ddfae13
[python2.6] prefer python2.6's builtin json module over simplejson
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents:
5326
diff
changeset
|
430 |
self.exception('this is what happened') |
6273
8dbdd4cc7938
[publisher] avoid extra Name error on unexpected error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6272
diff
changeset
|
431 |
result = 'oops' |
0 | 432 |
finally: |
5865
af414723598d
[publisher] avoid useless rollback after successful commit, which clutters debug logs and may also not be cost-free
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5721
diff
changeset
|
433 |
if req.cnx and not commited: |
0 | 434 |
try: |
435 |
req.cnx.rollback() |
|
436 |
except: |
|
437 |
pass # ignore rollback error at this point |
|
438 |
self.info('query %s executed in %s sec', req.relative_path(), clock() - tstart) |
|
439 |
return result |
|
440 |
||
441 |
def validation_error_handler(self, req, ex): |
|
442 |
ex.errors = dict((k, v) for k, v in ex.errors.items()) |
|
443 |
if '__errorurl' in req.form: |
|
4224
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3408
diff
changeset
|
444 |
forminfo = {'error': ex, |
0 | 445 |
'values': req.form, |
446 |
'eidmap': req.data.get('eidmap', {}) |
|
447 |
} |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5174
diff
changeset
|
448 |
req.session.data[req.form['__errorurl']] = forminfo |
4679
d8ad65dab3e9
remove #<formid> from url used to redirect after a validation error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4639
diff
changeset
|
449 |
# XXX form session key / __error_url should be differentiated: |
d8ad65dab3e9
remove #<formid> from url used to redirect after a validation error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4639
diff
changeset
|
450 |
# session key is 'url + #<form dom id', though we usually don't want |
d8ad65dab3e9
remove #<formid> from url used to redirect after a validation error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4639
diff
changeset
|
451 |
# the browser to move to the form since it hides the global |
d8ad65dab3e9
remove #<formid> from url used to redirect after a validation error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4639
diff
changeset
|
452 |
# messages. |
d8ad65dab3e9
remove #<formid> from url used to redirect after a validation error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4639
diff
changeset
|
453 |
raise Redirect(req.form['__errorurl'].rsplit('#', 1)[0]) |
0 | 454 |
self.error_handler(req, ex, tb=False) |
1426 | 455 |
|
0 | 456 |
def error_handler(self, req, ex, tb=False): |
457 |
excinfo = sys.exc_info() |
|
458 |
self.exception(repr(ex)) |
|
459 |
req.set_header('Cache-Control', 'no-cache') |
|
460 |
req.remove_header('Etag') |
|
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4709
diff
changeset
|
461 |
req.reset_message() |
0 | 462 |
req.reset_headers() |
4709
6a71fc0b4274
[web] fix #724769: Use RemoteCallFailed in the publisher's error_handler
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4679
diff
changeset
|
463 |
if req.json_request: |
6a71fc0b4274
[web] fix #724769: Use RemoteCallFailed in the publisher's error_handler
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4679
diff
changeset
|
464 |
raise RemoteCallFailed(unicode(ex)) |
0 | 465 |
try: |
466 |
req.data['ex'] = ex |
|
467 |
if tb: |
|
468 |
req.data['excinfo'] = excinfo |
|
469 |
req.form['vid'] = 'error' |
|
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
470 |
errview = self.vreg['views'].select('error', req) |
882
75488a2a875e
fix ui.main-template property handling
sylvain.thenault@logilab.fr
parents:
871
diff
changeset
|
471 |
template = self.main_template_id(req) |
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
472 |
content = self.vreg['views'].main_template(req, template, view=errview) |
0 | 473 |
except: |
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
474 |
content = self.vreg['views'].main_template(req, 'error-template') |
0 | 475 |
raise StatusResponse(500, content) |
1426 | 476 |
|
0 | 477 |
def need_login_content(self, req): |
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
478 |
return self.vreg['views'].main_template(req, 'login') |
1426 | 479 |
|
0 | 480 |
def loggedout_content(self, req): |
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
481 |
return self.vreg['views'].main_template(req, 'loggedout') |
1426 | 482 |
|
0 | 483 |
def notfound_content(self, req): |
484 |
req.form['vid'] = '404' |
|
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
485 |
view = self.vreg['views'].select('404', req) |
882
75488a2a875e
fix ui.main-template property handling
sylvain.thenault@logilab.fr
parents:
871
diff
changeset
|
486 |
template = self.main_template_id(req) |
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
487 |
return self.vreg['views'].main_template(req, template, view=view) |
0 | 488 |
|
882
75488a2a875e
fix ui.main-template property handling
sylvain.thenault@logilab.fr
parents:
871
diff
changeset
|
489 |
def main_template_id(self, req): |
2263
1f59cd5b710f
accept a __template parameter that specifies a different (main) template
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
1977
diff
changeset
|
490 |
template = req.form.get('__template', req.property_value('ui.main-template')) |
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
491 |
if template not in self.vreg['views']: |
882
75488a2a875e
fix ui.main-template property handling
sylvain.thenault@logilab.fr
parents:
871
diff
changeset
|
492 |
template = 'main-template' |
75488a2a875e
fix ui.main-template property handling
sylvain.thenault@logilab.fr
parents:
871
diff
changeset
|
493 |
return template |
1426 | 494 |
|
0 | 495 |
|
496 |
set_log_methods(CubicWebPublisher, LOGGER) |
|
497 |
set_log_methods(CookieSessionHandler, LOGGER) |