web/views/sessions.py
changeset 9071 46885bfa4150
parent 9019 e08f9c55dab5
child 9543 39f981482e34
equal deleted inserted replaced
9070:4a803380f718 9071:46885bfa4150
    24 from cubicweb import (RepositoryError, Unauthorized, AuthenticationError,
    24 from cubicweb import (RepositoryError, Unauthorized, AuthenticationError,
    25                       BadConnectionId)
    25                       BadConnectionId)
    26 from cubicweb.web import InvalidSession, Redirect
    26 from cubicweb.web import InvalidSession, Redirect
    27 from cubicweb.web.application import AbstractSessionManager
    27 from cubicweb.web.application import AbstractSessionManager
    28 from cubicweb.dbapi import ProgrammingError, DBAPISession
    28 from cubicweb.dbapi import ProgrammingError, DBAPISession
       
    29 from cubicweb import repoapi
    29 
    30 
    30 
    31 
    31 class InMemoryRepositorySessionManager(AbstractSessionManager):
    32 class InMemoryRepositorySessionManager(AbstractSessionManager):
    32     """manage session data associated to a session identifier"""
    33     """manage session data associated to a session identifier"""
    33 
    34 
    51     def get_session(self, req, sessionid):
    52     def get_session(self, req, sessionid):
    52         """return existing session for the given session identifier"""
    53         """return existing session for the given session identifier"""
    53         if sessionid not in self._sessions:
    54         if sessionid not in self._sessions:
    54             raise InvalidSession()
    55             raise InvalidSession()
    55         session = self._sessions[sessionid]
    56         session = self._sessions[sessionid]
    56         if session.cnx:
    57         try:
    57             try:
    58             user = self.authmanager.validate_session(req, session)
    58                 user = self.authmanager.validate_session(req, session)
    59         except InvalidSession:
    59             except InvalidSession:
    60             self.close_session(session)
    60                 # invalid session
    61             raise
    61                 self.close_session(session)
    62         if session.closed:
    62                 raise
    63             self.close_session(session)
       
    64             raise InvalidSession()
    63         return session
    65         return session
    64 
    66 
    65     def open_session(self, req):
    67     def open_session(self, req):
    66         """open and return a new session for the given request. The session is
    68         """open and return a new session for the given request. The session is
    67         also bound to the request.
    69         also bound to the request.
    68 
    70 
    69         raise :exc:`cubicweb.AuthenticationError` if authentication failed
    71         raise :exc:`cubicweb.AuthenticationError` if authentication failed
    70         (no authentication info found or wrong user/password)
    72         (no authentication info found or wrong user/password)
    71         """
    73         """
    72         cnx, login = self.authmanager.authenticate(req)
    74         session, login = self.authmanager.authenticate(req)
    73         session = DBAPISession(cnx, login)
       
    74         self._sessions[session.sessionid] = session
    75         self._sessions[session.sessionid] = session
    75         return session
    76         return session
    76 
    77 
    77     def postlogin(self, req, session):
    78     def postlogin(self, req, session):
    78         """postlogin: the user have been related to a session
    79         """postlogin: the user have been related to a session
    85         # XXX: this should be in a post login hook in the repository, but there
    86         # XXX: this should be in a post login hook in the repository, but there
    86         #      we can't differentiate actual login of automatic session
    87         #      we can't differentiate actual login of automatic session
    87         #      reopening. Is it actually a problem?
    88         #      reopening. Is it actually a problem?
    88         if 'last_login_time' in req.vreg.schema:
    89         if 'last_login_time' in req.vreg.schema:
    89             self._update_last_login_time(session)
    90             self._update_last_login_time(session)
    90         req.set_message(req._('welcome %s !') % session.cnx.user().login)
    91         req.set_message(req._('welcome %s !') % session.user.login)
    91 
    92 
    92     def _update_last_login_time(self, session):
    93     def _update_last_login_time(self, session):
    93         # XXX should properly detect missing permission / non writeable source
    94         # XXX should properly detect missing permission / non writeable source
    94         # and avoid "except (RepositoryError, Unauthorized)" below
    95         # and avoid "except (RepositoryError, Unauthorized)" below
    95         try:
    96         try:
    96             cu = session.cnx.cursor()
    97             cnx = repoapi.ClientConnection(session)
    97             cu.execute('SET X last_login_time NOW WHERE X eid %(x)s',
    98             with cnx:
    98                        {'x' : session.cnx.user().eid})
    99                 cnx.execute('SET X last_login_time NOW WHERE X eid %(x)s',
    99             session.cnx.commit()
   100                            {'x' : session.user.eid})
       
   101                 cnx.commit()
   100         except (RepositoryError, Unauthorized):
   102         except (RepositoryError, Unauthorized):
   101             session.cnx.rollback()
   103             pass
   102         except Exception:
       
   103             session.cnx.rollback()
       
   104             raise
       
   105 
   104 
   106     def close_session(self, session):
   105     def close_session(self, session):
   107         """close session on logout or on invalid session detected (expired out,
   106         """close session on logout or on invalid session detected (expired out,
   108         corrupted...)
   107         corrupted...)
   109         """
   108         """
   110         self.info('closing http session %s' % session.sessionid)
   109         self.info('closing http session %s' % session.sessionid)
   111         del self._sessions[session.sessionid]
   110         self._sessions.pop(session.sessionid, None)
   112         if session.cnx:
   111         if not session.closed:
   113             try:
   112             session.repo.close(session.id)
   114                 session.cnx.close()
       
   115             except (ProgrammingError, BadConnectionId): # expired on the repository side
       
   116                 pass
       
   117             session.cnx = None