Source code for pyramid_cubicweb.session

import warnings
import logging

from pyramid.compat import pickle
from pyramid.session import SignedCookieSessionFactory

from cubicweb import Binary


log = logging.getLogger(__name__)


def logerrors(logger):
    def wrap(fn):
        def newfn(*args, **kw):
            try:
                return fn(*args, **kw)
            except:
                logger.exception("Error in %s" % fn.__name__)
        return newfn
    return wrap


[docs]def CWSessionFactory( secret, cookie_name='session', max_age=None, path='/', domain=None, secure=False, httponly=False, set_on_exception=True, timeout=1200, reissue_time=120, hashalg='sha512', salt='pyramid.session.', serializer=None): """ A pyramid session factory that store session data in the CubicWeb database. Storage is done with the 'CWSession' entity, which is provided by the 'pyramid' cube. .. warning:: Although it provides a sane default behavior, this session storage has a serious overhead because it uses RQL to access the database. Using pure SQL would improve a bit (it is roughly twice faster), but it is still pretty slow and thus not an immediate priority. It is recommended to use faster session factory (pyramid_redis_sessions_ for example) if you need speed. .. _pyramid_redis_sessions: http://pyramid-redis-sessions.readthedocs.org/ en/latest/index.html """ SignedCookieSession = SignedCookieSessionFactory( secret, cookie_name=cookie_name, max_age=max_age, path=path, domain=domain, secure=secure, httponly=httponly, set_on_exception=set_on_exception, timeout=timeout, reissue_time=reissue_time, hashalg=hashalg, salt=salt, serializer=serializer) class CWSession(SignedCookieSession): def __init__(self, request): # _set_accessed will be called by the super __init__. # Setting _loaded to True inhibates it. self._loaded = True # the super __init__ will load a single value in the dictionnary, # the session id. super(CWSession, self).__init__(request) # Remove the session id from the dict self.sessioneid = self.pop('sessioneid', None) self.repo = request.registry['cubicweb.repository'] # We need to lazy-load only for existing sessions self._loaded = self.sessioneid is None @logerrors(log) def _set_accessed(self, value): self._accessed = value if self._loaded: return with self.repo.internal_cnx() as cnx: session = cnx.find('CWSession', eid=self.sessioneid).one() value = session.cwsessiondata if value: # Use directly dict.update to avoir _set_accessed to be # recursively called dict.update(self, pickle.load(value)) self._loaded = True def _get_accessed(self): return self._accessed accessed = property(_get_accessed, _set_accessed) @logerrors(log) def _set_cookie(self, response): # Save the value in the database data = Binary(pickle.dumps(dict(self))) sessioneid = self.sessioneid with self.repo.internal_cnx() as cnx: if not sessioneid: session = cnx.create_entity( 'CWSession', cwsessiondata=data) sessioneid = session.eid else: session = cnx.entity_from_eid(sessioneid) session.cw_set(cwsessiondata=data) cnx.commit() # Only if needed actually set the cookie if self.new or self.accessed - self.renewed > self._reissue_time: dict.clear(self) dict.__setitem__(self, 'sessioneid', sessioneid) return super(CWSession, self)._set_cookie(response) return True return CWSession
[docs]def includeme(config): """ Activate the CubicWeb session factory. Usually called via ``config.include('pyramid_cubicweb.auth')``. See also :ref:`defaults_module` """ secret = config.registry['cubicweb.config']['pyramid-session-secret'] if not secret: secret = 'notsosecret' warnings.warn(''' !! WARNING !! !! WARNING !! The session cookies are signed with a static secret key. To put your own secret key, edit your all-in-one.conf file and set the 'pyramid-session-secret' key. YOU SHOULD STOP THIS INSTANCE unless your really know what you are doing !! ''') session_factory = CWSessionFactory(secret) config.set_session_factory(session_factory)