39 """ |
39 """ |
40 |
40 |
41 def __init__(self, *args, **kwargs): |
41 def __init__(self, *args, **kwargs): |
42 super(GAEAuthenticationManager, self).__init__(*args, **kwargs) |
42 super(GAEAuthenticationManager, self).__init__(*args, **kwargs) |
43 self._repo = self.config.repository(vreg=self.vreg) |
43 self._repo = self.config.repository(vreg=self.vreg) |
44 |
44 |
45 def authenticate(self, req, _login=None, _password=None): |
45 def authenticate(self, req, _login=None, _password=None): |
46 """authenticate user and return an established connection for this user |
46 """authenticate user and return an established connection for this user |
47 |
47 |
48 :raise ExplicitLogin: if authentication is required (no authentication |
48 :raise ExplicitLogin: if authentication is required (no authentication |
49 info found or wrong user/password) |
49 info found or wrong user/password) |
50 """ |
50 """ |
51 if _login is not None: |
51 if _login is not None: |
52 login, password = _login, _password |
52 login, password = _login, _password |
73 """manage session data associated to a session identifier""" |
73 """manage session data associated to a session identifier""" |
74 |
74 |
75 def __init__(self, *args, **kwargs): |
75 def __init__(self, *args, **kwargs): |
76 super(GAEPersistentSessionManager, self).__init__(*args, **kwargs) |
76 super(GAEPersistentSessionManager, self).__init__(*args, **kwargs) |
77 self._repo = self.config.repository(vreg=self.vreg) |
77 self._repo = self.config.repository(vreg=self.vreg) |
78 |
78 |
79 def get_session(self, req, sessionid): |
79 def get_session(self, req, sessionid): |
80 """return existing session for the given session identifier""" |
80 """return existing session for the given session identifier""" |
81 # search a record for the given session |
81 # search a record for the given session |
82 key = Key.from_path('CubicWebSession', 'key_' + sessionid, parent=None) |
82 key = Key.from_path('CubicWebSession', 'key_' + sessionid, parent=None) |
83 try: |
83 try: |
124 record['login'] = cnx.login |
124 record['login'] = cnx.login |
125 record['password'] = cnx.password |
125 record['password'] = cnx.password |
126 record['anonymous_connection'] = cnx.anonymous_connection |
126 record['anonymous_connection'] = cnx.anonymous_connection |
127 Put(record) |
127 Put(record) |
128 return self._get_proxy(req, record, cnx, user) |
128 return self._get_proxy(req, record, cnx, user) |
129 |
129 |
130 def close_session(self, proxy): |
130 def close_session(self, proxy): |
131 """close session on logout or on invalid session detected (expired out, |
131 """close session on logout or on invalid session detected (expired out, |
132 corrupted...) |
132 corrupted...) |
133 """ |
133 """ |
134 proxy.close() |
134 proxy.close() |
135 |
135 |
136 def current_sessions(self): |
136 def current_sessions(self): |
137 for record in Query('CubicWebSession').Run(): |
137 for record in Query('CubicWebSession').Run(): |
138 yield ConnectionProxy(record) |
138 yield ConnectionProxy(record) |
139 |
139 |
140 def _get_proxy(self, req, record, cnx, user): |
140 def _get_proxy(self, req, record, cnx, user): |
141 proxy = ConnectionProxy(record, cnx, user) |
141 proxy = ConnectionProxy(record, cnx, user) |
142 user.req = req |
142 user.req = req |
143 req.set_connection(proxy, user) |
143 req.set_connection(proxy, user) |
144 return proxy |
144 return proxy |
145 |
145 |
146 |
146 |
147 class ConnectionProxy(object): |
147 class ConnectionProxy(object): |
148 |
148 |
149 def __init__(self, record, cnx=None, user=None): |
149 def __init__(self, record, cnx=None, user=None): |
150 self.__record = record |
150 self.__record = record |
151 self.__cnx = cnx |
151 self.__cnx = cnx |
152 self.__user = user |
152 self.__user = user |
153 self.__data = None |
153 self.__data = None |
154 self.__is_dirty = False |
154 self.__is_dirty = False |
155 self.sessionid = record.key().name()[4:] # remove 'key_' prefix |
155 self.sessionid = record.key().name()[4:] # remove 'key_' prefix |
156 |
156 |
157 def __repr__(self): |
157 def __repr__(self): |
158 sstr = '<ConnectionProxy %s' % self.sessionid |
158 sstr = '<ConnectionProxy %s' % self.sessionid |
159 if self.anonymous_connection: |
159 if self.anonymous_connection: |
160 sstr += ' (anonymous)' |
160 sstr += ' (anonymous)' |
161 elif self.__user: |
161 elif self.__user: |
162 sstr += ' for %s' % self.__user.login |
162 sstr += ' for %s' % self.__user.login |
163 sstr += ', last used %s>' % strftime('%T', localtime(self.last_usage_time)) |
163 sstr += ', last used %s>' % strftime('%T', localtime(self.last_usage_time)) |
164 return sstr |
164 return sstr |
165 |
165 |
166 def __getattribute__(self, name): |
166 def __getattribute__(self, name): |
167 try: |
167 try: |
168 return super(ConnectionProxy, self).__getattribute__(name) |
168 return super(ConnectionProxy, self).__getattribute__(name) |
169 except AttributeError: |
169 except AttributeError: |
170 return getattr(self.__cnx, name) |
170 return getattr(self.__cnx, name) |
172 def _set_last_usage_time(self, value): |
172 def _set_last_usage_time(self, value): |
173 self.__is_dirty = True |
173 self.__is_dirty = True |
174 self.__record['last_usage_time'] = value |
174 self.__record['last_usage_time'] = value |
175 def _get_last_usage_time(self): |
175 def _get_last_usage_time(self): |
176 return self.__record['last_usage_time'] |
176 return self.__record['last_usage_time'] |
177 |
177 |
178 last_usage_time = property(_get_last_usage_time, _set_last_usage_time) |
178 last_usage_time = property(_get_last_usage_time, _set_last_usage_time) |
179 |
179 |
180 @property |
180 @property |
181 def anonymous_connection(self): |
181 def anonymous_connection(self): |
182 # use get() for bw compat if sessions without anonymous information are |
182 # use get() for bw compat if sessions without anonymous information are |
183 # found. Set default to True to limit lifetime of those sessions. |
183 # found. Set default to True to limit lifetime of those sessions. |
184 return self.__record.get('anonymous_connection', True) |
184 return self.__record.get('anonymous_connection', True) |
185 |
185 |
186 @property |
186 @property |
187 @cached |
187 @cached |
188 def data(self): |
188 def data(self): |
189 if self.__record.get('data') is not None: |
189 if self.__record.get('data') is not None: |
190 try: |
190 try: |
204 return value |
204 return value |
205 except KeyError: |
205 except KeyError: |
206 return default |
206 return default |
207 else: |
207 else: |
208 return self.data.get(key, default) |
208 return self.data.get(key, default) |
209 |
209 |
210 def set_session_data(self, key, value): |
210 def set_session_data(self, key, value): |
211 """set value associated to `key` in session data""" |
211 """set value associated to `key` in session data""" |
212 self.data[key] = value |
212 self.data[key] = value |
213 self.__is_dirty = True |
213 self.__is_dirty = True |
214 |
214 |
215 def del_session_data(self, key): |
215 def del_session_data(self, key): |
216 """remove value associated to `key` in session data""" |
216 """remove value associated to `key` in session data""" |
217 try: |
217 try: |
218 del self.data[key] |
218 del self.data[key] |
219 self.__is_dirty = True |
219 self.__is_dirty = True |
220 except KeyError: |
220 except KeyError: |
221 pass |
221 pass |
222 |
222 |
223 def commit(self): |
223 def commit(self): |
224 if self.__is_dirty: |
224 if self.__is_dirty: |
225 self.__save() |
225 self.__save() |
226 self.__cnx.commit() |
226 self.__cnx.commit() |
227 |
227 |
231 |
231 |
232 def close(self): |
232 def close(self): |
233 if self.__cnx is not None: |
233 if self.__cnx is not None: |
234 self.__cnx.close() |
234 self.__cnx.close() |
235 Delete(self.__record) |
235 Delete(self.__record) |
236 |
236 |
237 def __save(self): |
237 def __save(self): |
238 if self.__is_dirty: |
238 if self.__is_dirty: |
239 self.__record['data'] = Blob(dumps(self.data)) |
239 self.__record['data'] = Blob(dumps(self.data)) |
240 Put(self.__record) |
240 Put(self.__record) |
241 self.__is_dirty = False |
241 self.__is_dirty = False |
242 |
242 |
243 def user(self, req=None, props=None): |
243 def user(self, req=None, props=None): |
244 """return the User object associated to this connection""" |
244 """return the User object associated to this connection""" |
245 return self.__user |
245 return self.__user |
246 |
246 |
247 |
247 |
248 import logging |
248 import logging |
249 from cubicweb import set_log_methods |
249 from cubicweb import set_log_methods |
250 set_log_methods(ConnectionProxy, logging.getLogger('cubicweb.web.goa.session')) |
250 set_log_methods(ConnectionProxy, logging.getLogger('cubicweb.web.goa.session')) |
251 |
251 |
268 nbclosed = repo.clean_sessions() |
268 nbclosed = repo.clean_sessions() |
269 self.w(u'%s repository sessions closed<br/>\n' % nbclosed) |
269 self.w(u'%s repository sessions closed<br/>\n' % nbclosed) |
270 self.w(u'%s remaining sessions<br/>\n' % remaining) |
270 self.w(u'%s remaining sessions<br/>\n' % remaining) |
271 self.w(u'</div>') |
271 self.w(u'</div>') |
272 |
272 |
273 |
273 |
274 def registration_callback(vreg): |
274 def registration_callback(vreg): |
275 vreg.register(SessionsCleaner) |
275 vreg.register(SessionsCleaner) |
276 vreg.register(GAEAuthenticationManager, clear=True) |
276 vreg.register(GAEAuthenticationManager, clear=True) |
277 vreg.register(GAEPersistentSessionManager, clear=True) |
277 vreg.register(GAEPersistentSessionManager, clear=True) |