diff -r 6ba31f0c7d5a -r b0b8942cdb80 pyramid_cubicweb/__init__.py --- a/pyramid_cubicweb/__init__.py Tue Jul 22 23:46:09 2014 +0200 +++ b/pyramid_cubicweb/__init__.py Thu Jul 31 17:48:32 2014 +0200 @@ -1,248 +0,0 @@ -from contextlib import contextmanager -from warnings import warn - -import rql - -from cubicweb.web.request import CubicWebRequestBase -from cubicweb.cwconfig import CubicWebConfiguration -from cubicweb import repoapi - -import cubicweb -import cubicweb.web - -from pyramid import security, httpexceptions -from pyramid.httpexceptions import HTTPSeeOther - -from pyramid_cubicweb import authplugin - -import logging - -log = logging.getLogger(__name__) - - -@contextmanager -def cw_to_pyramid(request): - """Wrap a call to the cubicweb API. - - All CW exceptions will be transformed into their pyramid equivalent. - When needed, some CW reponse bits may be converted too (mainly headers)""" - try: - yield - except cubicweb.web.Redirect as ex: - assert 300 <= ex.status < 400 - raise httpexceptions.status_map[ex.status](ex.location) - except cubicweb.web.StatusResponse as ex: - warn('[3.16] StatusResponse is deprecated use req.status_out', - DeprecationWarning, stacklevel=2) - request.body = ex.content - request.status_int = ex.status - except cubicweb.web.Unauthorized as ex: - raise httpexceptions.HTTPForbidden( - request.cw_request._( - 'You\'re not authorized to access this page. ' - 'If you think you should, please contact the site ' - 'administrator.')) - except cubicweb.web.Forbidden: - raise httpexceptions.HTTPForbidden( - request.cw_request._( - 'This action is forbidden. ' - 'If you think it should be allowed, please contact the site ' - 'administrator.')) - except (rql.BadRQLQuery, cubicweb.web.RequestError) as ex: - raise - - -class CubicWebPyramidRequest(CubicWebRequestBase): - def __init__(self, request): - self._request = request - - self.path = request.upath_info - - vreg = request.registry['cubicweb.appli'].vreg - https = request.scheme == 'https' - - post = request.params - headers_in = request.headers - - super(CubicWebPyramidRequest, self).__init__(vreg, https, post, - headers=headers_in) - - def is_secure(self): - return self._request.scheme == 'https' - - def relative_path(self, includeparams=True): - path = self._request.path[1:] - if includeparams and self._request.query_string: - return '%s?%s' % (path, self._request.query_string) - return path - - def instance_uri(self): - return self._request.application_url - - def get_full_path(self): - path = self._request.path - if self._request.query_string: - return '%s?%s' % (path, self._request.query_string) - return path - - def http_method(self): - return self._request.method - - def _set_status_out(self, value): - self._request.response.status_int = value - - def _get_status_out(self): - return self._request.response.status_int - - status_out = property(_get_status_out, _set_status_out) - - -def render_view(request, vid, **kwargs): - vreg = request.registry['cubicweb.registry'] - # XXX The select() function could, know how to handle a pyramid - # request, and feed it directly to the views that supports it. - # On the other hand, we could refine the View concept and decide it works - # with a cnx, and never with a WebRequest - - with cw_to_pyramid(request): - view = vreg['views'].select(vid, request.cw_request, **kwargs) - view.set_stream() - view.render() - return view._stream.getvalue() - - -def login(request): - repo = request.registry['cubicweb.repository'] - - response = request.response - user_eid = None - - if '__login' in request.params: - login = request.params['__login'] - password = request.params['__password'] - - try: - with repo.internal_cnx() as cnx: - user = repo.authenticate_user(cnx, login, password=password) - user_eid = user.eid - except cubicweb.AuthenticationError: - raise - - if user_eid is not None: - headers = security.remember(request, user_eid) - - raise HTTPSeeOther( - request.params.get('postlogin_path', '/'), - headers=headers) - - response.headerlist.extend(headers) - - response.text = render_view(request, 'login') - return response - - -def _cw_cnx(request): - cnx = repoapi.ClientConnection(request.cw_session) - - def cleanup(request): - if request.exception is not None: - cnx.rollback() - else: - cnx.commit() - cnx.__exit__(None, None, None) - - request.add_finished_callback(cleanup) - cnx.__enter__() - 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'] - - 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 - - # 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 session - - -def _cw_request(request): - req = CubicWebPyramidRequest(request) - req.set_cnx(request.cw_cnx) - return req - - -def get_principals(login, request): - repo = request.registry['cubicweb.repository'] - - 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 - - return session.user.groups - - -from pyramid.authentication import SessionAuthenticationPolicy -from pyramid.authorization import ACLAuthorizationPolicy -from pyramid.session import SignedCookieSessionFactory - - -def hello_world(request): - request.response.text = \ - u"Hello %s" % request.cw_cnx.user.login - return request.response - - -def includeme(config): - appid = config.registry.settings['cubicweb.instance'] - cwconfig = CubicWebConfiguration.config_for(appid) - - config.set_session_factory( - SignedCookieSessionFactory( - secret=config.registry.settings['session.secret'] - )) - - config.set_authentication_policy( - SessionAuthenticationPolicy(callback=get_principals)) - config.set_authorization_policy(ACLAuthorizationPolicy()) - - config.registry['cubicweb.config'] = cwconfig - config.registry['cubicweb.repository'] = repo = cwconfig.repository() - config.registry['cubicweb.registry'] = repo.vreg - - repo.system_source.add_authentifier(authplugin.DirectAuthentifier()) - - config.add_request_method( - _cw_session, name='cw_session', property=True, reify=True) - config.add_request_method( - _cw_cnx, name='cw_cnx', property=True, reify=True) - config.add_request_method( - _cw_request, name='cw_request', property=True, reify=True) - - config.add_route('login', '/login') - config.add_view(login, route_name='login') - - config.add_route('hello', '/hello') - config.add_view(hello_world, route_name='hello') - - config.include('pyramid_cubicweb.handler')