web/application.py
changeset 6012 d56fd78006cd
parent 5868 c4380d8cfc25
child 6139 f76599a96238
equal deleted inserted replaced
6011:b5f15098f282 6012:d56fd78006cd
    29 from rql import BadRQLQuery
    29 from rql import BadRQLQuery
    30 
    30 
    31 from cubicweb import set_log_methods, cwvreg
    31 from cubicweb import set_log_methods, cwvreg
    32 from cubicweb import (
    32 from cubicweb import (
    33     ValidationError, Unauthorized, AuthenticationError, NoSelectableObject,
    33     ValidationError, Unauthorized, AuthenticationError, NoSelectableObject,
    34     RepositoryError, CW_EVENT_MANAGER)
    34     RepositoryError, BadConnectionId, CW_EVENT_MANAGER)
    35 from cubicweb.dbapi import DBAPISession
    35 from cubicweb.dbapi import DBAPISession
    36 from cubicweb.web import LOGGER, component
    36 from cubicweb.web import LOGGER, component
    37 from cubicweb.web import (
    37 from cubicweb.web import (
    38     StatusResponse, DirectResponse, Redirect, NotFound, LogOut,
    38     StatusResponse, DirectResponse, Redirect, NotFound, LogOut,
    39     RemoteCallFailed, InvalidSession, RequestError)
    39     RemoteCallFailed, InvalidSession, RequestError)
    46     """manage session data associated to a session identifier"""
    46     """manage session data associated to a session identifier"""
    47     __regid__ = 'sessionmanager'
    47     __regid__ = 'sessionmanager'
    48 
    48 
    49     def __init__(self, vreg):
    49     def __init__(self, vreg):
    50         self.session_time = vreg.config['http-session-time'] or None
    50         self.session_time = vreg.config['http-session-time'] or None
    51         if self.session_time is not None:
       
    52             assert self.session_time > 0
       
    53             self.cleanup_session_time = self.session_time
       
    54         else:
       
    55             self.cleanup_session_time = vreg.config['cleanup-session-time'] or 1440 * 60
       
    56             assert self.cleanup_session_time > 0
       
    57         self.cleanup_anon_session_time = vreg.config['cleanup-anonymous-session-time'] or 5 * 60
       
    58         assert self.cleanup_anon_session_time > 0
       
    59         self.authmanager = vreg['components'].select('authmanager', vreg=vreg)
    51         self.authmanager = vreg['components'].select('authmanager', vreg=vreg)
       
    52         interval = (self.session_time or 0) / 2.
    60         if vreg.config.anonymous_user() is not None:
    53         if vreg.config.anonymous_user() is not None:
    61             self.clean_sessions_interval = max(
    54             self.cleanup_anon_session_time = vreg.config['cleanup-anonymous-session-time'] or 5 * 60
    62                 5 * 60, min(self.cleanup_session_time / 2.,
    55             assert self.cleanup_anon_session_time > 0
    63                             self.cleanup_anon_session_time / 2.))
    56             if self.session_time is not None:
    64         else:
    57                 self.cleanup_anon_session_time = min(self.session_time,
    65             self.clean_sessions_interval = max(
    58                                                      self.cleanup_anon_session_time)
    66                 5 * 60,
    59             interval = self.cleanup_anon_session_time / 2.
    67                 self.cleanup_session_time / 2.)
    60         # we don't want to check session more than once every 5 minutes
       
    61         self.clean_sessions_interval = max(5 * 60, interval)
    68 
    62 
    69     def clean_sessions(self):
    63     def clean_sessions(self):
    70         """cleanup sessions which has not been unused since a given amount of
    64         """cleanup sessions which has not been unused since a given amount of
    71         time. Return the number of sessions which have been closed.
    65         time. Return the number of sessions which have been closed.
    72         """
    66         """
    73         self.debug('cleaning http sessions')
    67         self.debug('cleaning http sessions')
       
    68         session_time = self.session_time
    74         closed, total = 0, 0
    69         closed, total = 0, 0
    75         for session in self.current_sessions():
    70         for session in self.current_sessions():
    76             no_use_time = (time() - session.last_usage_time)
       
    77             total += 1
    71             total += 1
    78             if session.anonymous_session:
    72             try:
    79                 if no_use_time >= self.cleanup_anon_session_time:
    73                 last_usage_time = session.cnx.check()
       
    74             except BadConnectionId:
       
    75                 self.close_session(session)
       
    76                 closed += 1
       
    77             else:
       
    78                 no_use_time = (time() - last_usage_time)
       
    79                 if session.anonymous_session:
       
    80                     if no_use_time >= self.cleanup_anon_session_time:
       
    81                         self.close_session(session)
       
    82                         closed += 1
       
    83                 elif session_time is not None and no_use_time >= session_time:
    80                     self.close_session(session)
    84                     self.close_session(session)
    81                     closed += 1
    85                     closed += 1
    82             elif no_use_time >= self.cleanup_session_time:
       
    83                 self.close_session(session)
       
    84                 closed += 1
       
    85         return closed, total - closed
    86         return closed, total - closed
    86 
       
    87     def has_expired(self, session):
       
    88         """return True if the web session associated to the session is expired
       
    89         """
       
    90         return not (self.session_time is None or
       
    91                     time() < session.last_usage_time + self.session_time)
       
    92 
    87 
    93     def current_sessions(self):
    88     def current_sessions(self):
    94         """return currently open sessions"""
    89         """return currently open sessions"""
    95         raise NotImplementedError()
    90         raise NotImplementedError()
    96 
    91 
   211                 try:
   206                 try:
   212                     session = self.open_session(req)
   207                     session = self.open_session(req)
   213                 except AuthenticationError:
   208                 except AuthenticationError:
   214                     req.remove_cookie(cookie, self.SESSION_VAR)
   209                     req.remove_cookie(cookie, self.SESSION_VAR)
   215                     raise
   210                     raise
   216         # remember last usage time for web session tracking
       
   217         session.last_usage_time = time()
       
   218 
   211 
   219     def get_session(self, req, sessionid):
   212     def get_session(self, req, sessionid):
   220         return self.session_manager.get_session(req, sessionid)
   213         return self.session_manager.get_session(req, sessionid)
   221 
   214 
   222     def open_session(self, req):
   215     def open_session(self, req):
   223         session = self.session_manager.open_session(req)
   216         session = self.session_manager.open_session(req)
   224         cookie = req.get_cookie()
   217         cookie = req.get_cookie()
   225         cookie[self.SESSION_VAR] = session.sessionid
   218         cookie[self.SESSION_VAR] = session.sessionid
   226         req.set_cookie(cookie, self.SESSION_VAR, maxage=None)
   219         req.set_cookie(cookie, self.SESSION_VAR, maxage=None)
   227         # remember last usage time for web session tracking
       
   228         session.last_usage_time = time()
       
   229         if not session.anonymous_session:
   220         if not session.anonymous_session:
   230             self._postlogin(req)
   221             self._postlogin(req)
   231         return session
   222         return session
   232 
   223 
   233     def _update_last_login_time(self, req):
   224     def _update_last_login_time(self, req):