# HG changeset patch # User Christophe de Vienne # Date 1405427115 -7200 # Node ID 3905c9f06d0ea611c071fe4dbcf0aa2f4abf331a # Parent 39768d122f974d05b9b86dcd102d7225bee74fe3 Use short-lived cubicweb sessions to let pyramid actually handle the web sessions Related to #4291173 diff -r 39768d122f97 -r 3905c9f06d0e pyramid_cubicweb/__init__.py --- a/pyramid_cubicweb/__init__.py Wed Jul 09 17:14:32 2014 +0200 +++ b/pyramid_cubicweb/__init__.py Tue Jul 15 14:25:15 2014 +0200 @@ -69,7 +69,7 @@ # On the other hand, we could refine the View concept and decide it works # with a cnx, and never with a WebRequest - view = vreg['views'].select(vid, request.cw_request(), **kwargs) + view = vreg['views'].select(vid, request.cw_request, **kwargs) view.set_stream() view.render() @@ -80,27 +80,25 @@ repo = request.registry['cubicweb.repository'] response = request.response - userid = None + user_eid = None if '__login' in request.params: login = request.params['__login'] password = request.params['__password'] try: - sessionid = repo.connect(login, password=password) - request.session['cubicweb.sessionid'] = sessionid - session = repo._sessions[sessionid] - userid = session.user.eid + with repo.internal_cnx() as cnx: + user = repo.authenticate_user(cnx, login, password=password) + user_eid = user.eid except cubicweb.AuthenticationError: raise - if userid is not None: - headers = security.remember(request, userid) + if user_eid is not None: + headers = security.remember(request, user_eid) - if 'postlogin_path' in request.params: - raise HTTPSeeOther( - request.params['postlogin_path'], - headers=headers) + raise HTTPSeeOther( + request.params.get('postlogin_path', '/'), + headers=headers) response.headerlist.extend(headers) @@ -109,8 +107,6 @@ def _cw_cnx(request): - # XXX We should not need to use the session. A temporary one should be - # enough. (by using repoapi.connect()) cnx = repoapi.ClientConnection(request.cw_session) def cleanup(request): @@ -125,50 +121,50 @@ return cnx +def _cw_close_session(request): + request.cw_session.close() + + def _cw_session(request): + """Obtains a cw session from a pyramid request""" repo = request.registry['cubicweb.repository'] config = request.registry['cubicweb.config'] - sessionid = request.session.get('cubicweb.sessionid') + if not request.authenticated_userid: + login, password = config.anonymous_user() + sessionid = repo.connect(login, password=password) + session = repo._sessions[sessionid] + request.add_finished_callback(_cw_close_session) + else: + session = request._cw_cached_session - if sessionid not in repo._sessions: - if not request.authenticated_userid: - login, password = config.anonymous_user() - sessionid = repo.connect(login, password=password) - request.session['cubicweb.sessionid'] = sessionid - else: - sessionid = request.session.get('cubicweb.sessionid') + # XXX Ideally we store the cw session data in the pyramid session. + # BUT some data in the cw session data dictionnary makes pyramid fail. + #session.data = request.session - return repo._sessions[sessionid] + return session def _cw_request(request): - return weakref.ref(CubicWebPyramidRequest(request)) + req = CubicWebPyramidRequest(request) + req.set_cnx(request.cw_cnx) + return req -def get_principals(userid, request): +def get_principals(login, request): repo = request.registry['cubicweb.repository'] - sessionid = request.session.get('cubicweb.sessionid') + try: + sessionid = repo.connect( + str(login), __pyramid_directauth=authplugin.EXT_TOKEN) + session = repo._sessions[sessionid] + request._cw_cached_session = session + request.add_finished_callback(_cw_close_session) + except: + log.exception("Failed") + raise - if sessionid is None or sessionid not in repo._sessions: - try: - sessionid = repo.connect( - str(userid), __pyramid_directauth=authplugin.EXT_TOKEN) - except: - log.exception("Failed") - raise - request.session['cubicweb.sessionid'] = sessionid - - #session = repo._session[sessionid] - - with repo.internal_cnx() as cnx: - groupnames = [r[1] for r in cnx.execute( - 'Any X, N WHERE X is CWGroup, X name N, ' - 'U in_group X, U eid %(userid)s', - {'userid': userid})] - - return groupnames + return session.user.groups from pyramid.authentication import SessionAuthenticationPolicy diff -r 39768d122f97 -r 3905c9f06d0e pyramid_cubicweb/handler.py --- a/pyramid_cubicweb/handler.py Wed Jul 09 17:14:32 2014 +0200 +++ b/pyramid_cubicweb/handler.py Tue Jul 15 14:25:15 2014 +0200 @@ -36,8 +36,7 @@ # core_handle and CubicWebPublisher altogether so that the various CW # exceptions are converted to their pyramid equivalent. - req = request.cw_request() - req.set_cnx(request.cw_cnx) + req = request.cw_request # XXX The main handler of CW forbid anonymous https connections # I guess we can drop this "feature" but in doubt I leave this comment @@ -55,9 +54,6 @@ except LogOut as ex: # The actual 'logging out' logic should be in separated function # that is accessible by the pyramid views - del req._request.session['cubicweb.sessionid'] - if not req.session.closed: - req.session.repo.close(req.session.sessionid) headers = security.forget(request) raise HTTPSeeOther(ex.url, headers=headers) except Redirect as ex: