pyramid_cubicweb/__init__.py
author Christophe de Vienne <christophe@unlish.com>
Tue, 15 Jul 2014 17:37:50 +0200
changeset 11487 04252e9ff549
parent 11485 3905c9f06d0e
child 11489 433fd3af7386
permissions -rw-r--r--
Skip core_handle, add a context manager to handle cubicweb errors The context manager is also used to catch errors in render_view. It handles the 'external' errors raised by cubicweb code. The more internal errors, the one that should occur only in url resolving and cubicweb controllers, are handled directly in CubicWebPyramidHandler. ValidationError is handled by CubicWebPyramidHandler for now, but should probably be handled by cw_to_pyramid Related to #4291173
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11487
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
     1
from contextlib import contextmanager
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
     2
from warnings import warn
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
     3
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
     4
import rql
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
     5
11480
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     6
from cubicweb.web.request import CubicWebRequestBase
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     7
from cubicweb.cwconfig import CubicWebConfiguration
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
     8
from cubicweb import repoapi
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
     9
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    10
import cubicweb
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    11
import cubicweb.web
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    12
11487
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    13
from pyramid import security, httpexceptions
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    14
from pyramid.httpexceptions import HTTPSeeOther
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    15
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    16
from pyramid_cubicweb import authplugin
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    17
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    18
import logging
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    19
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
    20
log = logging.getLogger(__name__)
11480
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    21
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    22
11487
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    23
@contextmanager
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    24
def cw_to_pyramid(request):
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    25
    """Wrap a call to the cubicweb API.
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    26
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    27
    All CW exceptions will be transformed into their pyramid equivalent.
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    28
    When needed, some CW reponse bits may be converted too (mainly headers)"""
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    29
    try:
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    30
        yield
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    31
    except cubicweb.web.Redirect as ex:
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    32
        assert 300 <= ex.status < 400
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    33
        raise httpexceptions.status_map[ex.status](ex.location)
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    34
    except cubicweb.web.StatusResponse as ex:
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    35
        warn('[3.16] StatusResponse is deprecated use req.status_out',
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    36
             DeprecationWarning, stacklevel=2)
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    37
        request.body = ex.content
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    38
        request.status_int = ex.status
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    39
    except cubicweb.web.Unauthorized as ex:
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    40
        raise httpexceptions.HTTPForbidden(
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    41
            request.cw_request._(
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    42
                'You\'re not authorized to access this page. '
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    43
                'If you think you should, please contact the site '
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    44
                'administrator.'))
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    45
    except cubicweb.web.Forbidden:
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    46
        raise httpexceptions.HTTPForbidden(
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    47
            request.cw_request._(
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    48
                'This action is forbidden. '
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    49
                'If you think it should be allowed, please contact the site '
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    50
                'administrator.'))
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    51
    except (rql.BadRQLQuery, cubicweb.web.RequestError) as ex:
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    52
        raise
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    53
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
    54
11480
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    55
class CubicWebPyramidRequest(CubicWebRequestBase):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    56
    def __init__(self, request):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    57
        self._request = request
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    58
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    59
        self.path = request.upath_info
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    60
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    61
        vreg = request.registry['cubicweb.appli'].vreg
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    62
        https = request.scheme == 'https'
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    63
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    64
        post = request.params
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    65
        headers_in = request.headers
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    66
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    67
        super(CubicWebPyramidRequest, self).__init__(vreg, https, post,
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    68
                                                     headers=headers_in)
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    69
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    70
    def is_secure(self):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    71
        return self._request.scheme == 'https'
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    72
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    73
    def relative_path(self, includeparams=True):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    74
        path = self._request.path[1:]
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    75
        if includeparams and self._request.query_string:
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    76
            return '%s?%s' % (path, self._request.query_string)
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    77
        return path
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    78
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    79
    def instance_uri(self):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    80
        return self._request.application_url
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    81
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    82
    def get_full_path(self):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    83
        path = self._request.path
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    84
        if self._request.query_string:
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    85
            return '%s?%s' % (path, self._request.query_string)
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    86
        return path
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    87
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    88
    def http_method(self):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    89
        return self._request.method
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    90
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    91
    def _set_status_out(self, value):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    92
        self._request.response.status_int = value
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    93
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    94
    def _get_status_out(self):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    95
        return self._request.response.status_int
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    96
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    97
    status_out = property(_get_status_out, _set_status_out)
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    98
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    99
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   100
def render_view(request, vid, **kwargs):
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   101
    vreg = request.registry['cubicweb.registry']
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   102
    # XXX The select() function could, know how to handle a pyramid
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   103
    # request, and feed it directly to the views that supports it.
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   104
    # On the other hand, we could refine the View concept and decide it works
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   105
    # with a cnx, and never with a WebRequest
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   106
11487
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
   107
    with cw_to_pyramid(request):
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
   108
        view = vreg['views'].select(vid, request.cw_request, **kwargs)
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
   109
        view.set_stream()
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
   110
        view.render()
04252e9ff549 Skip core_handle, add a context manager to handle cubicweb errors
Christophe de Vienne <christophe@unlish.com>
parents: 11485
diff changeset
   111
        return view._stream.getvalue()
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   112
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   113
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   114
def login(request):
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   115
    repo = request.registry['cubicweb.repository']
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   116
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   117
    response = request.response
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   118
    user_eid = None
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   119
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   120
    if '__login' in request.params:
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   121
        login = request.params['__login']
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   122
        password = request.params['__password']
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   123
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   124
        try:
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   125
            with repo.internal_cnx() as cnx:
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   126
                user = repo.authenticate_user(cnx, login, password=password)
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   127
                user_eid = user.eid
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   128
        except cubicweb.AuthenticationError:
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   129
            raise
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   130
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   131
    if user_eid is not None:
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   132
        headers = security.remember(request, user_eid)
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   133
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   134
        raise HTTPSeeOther(
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   135
            request.params.get('postlogin_path', '/'),
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   136
            headers=headers)
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   137
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   138
        response.headerlist.extend(headers)
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   139
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   140
    response.text = render_view(request, 'login')
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   141
    return response
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   142
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   143
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   144
def _cw_cnx(request):
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   145
    cnx = repoapi.ClientConnection(request.cw_session)
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   146
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   147
    def cleanup(request):
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   148
        if request.exception is not None:
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   149
            cnx.rollback()
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   150
        else:
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   151
            cnx.commit()
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   152
        cnx.__exit__(None, None, None)
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   153
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   154
    request.add_finished_callback(cleanup)
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   155
    cnx.__enter__()
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   156
    return cnx
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   157
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   158
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   159
def _cw_close_session(request):
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   160
    request.cw_session.close()
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   161
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   162
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   163
def _cw_session(request):
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   164
    """Obtains a cw session from a pyramid request"""
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   165
    repo = request.registry['cubicweb.repository']
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   166
    config = request.registry['cubicweb.config']
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   167
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   168
    if not request.authenticated_userid:
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   169
        login, password = config.anonymous_user()
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   170
        sessionid = repo.connect(login, password=password)
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   171
        session = repo._sessions[sessionid]
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   172
        request.add_finished_callback(_cw_close_session)
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   173
    else:
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   174
        session = request._cw_cached_session
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   175
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   176
    # XXX Ideally we store the cw session data in the pyramid session.
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   177
    # BUT some data in the cw session data dictionnary makes pyramid fail.
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   178
    #session.data = request.session
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   179
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   180
    return session
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   181
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   182
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   183
def _cw_request(request):
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   184
    req = CubicWebPyramidRequest(request)
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   185
    req.set_cnx(request.cw_cnx)
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   186
    return req
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   187
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   188
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   189
def get_principals(login, request):
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   190
    repo = request.registry['cubicweb.repository']
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   191
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   192
    try:
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   193
        sessionid = repo.connect(
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   194
            str(login), __pyramid_directauth=authplugin.EXT_TOKEN)
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   195
        session = repo._sessions[sessionid]
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   196
        request._cw_cached_session = session
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   197
        request.add_finished_callback(_cw_close_session)
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   198
    except:
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   199
        log.exception("Failed")
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   200
        raise
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   201
11485
3905c9f06d0e Use short-lived cubicweb sessions to let pyramid actually handle the web sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11484
diff changeset
   202
    return session.user.groups
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   203
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   204
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   205
from pyramid.authentication import SessionAuthenticationPolicy
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   206
from pyramid.authorization import ACLAuthorizationPolicy
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   207
from pyramid.session import SignedCookieSessionFactory
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   208
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   209
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   210
def hello_world(request):
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   211
    request.response.text = \
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   212
        u"<html><body>Hello %s</body></html>" % request.cw_cnx.user.login
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   213
    return request.response
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   214
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   215
11480
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   216
def includeme(config):
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   217
    appid = config.registry.settings['cubicweb.instance']
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   218
    cwconfig = CubicWebConfiguration.config_for(appid)
79ac26923432 Initial implementation
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   219
11482
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   220
    config.set_session_factory(
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   221
        SignedCookieSessionFactory(
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   222
            secret=config.registry.settings['session.secret']
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   223
        ))
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   224
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   225
    config.set_authentication_policy(
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   226
        SessionAuthenticationPolicy(callback=get_principals))
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   227
    config.set_authorization_policy(ACLAuthorizationPolicy())
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   228
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   229
    config.registry['cubicweb.config'] = cwconfig
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   230
    config.registry['cubicweb.repository'] = repo = cwconfig.repository()
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   231
    config.registry['cubicweb.registry'] = repo.vreg
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   232
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   233
    repo.system_source.add_authentifier(authplugin.DirectAuthentifier())
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   234
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   235
    config.add_request_method(
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   236
        _cw_session, name='cw_session', property=True, reify=True)
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   237
    config.add_request_method(
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   238
        _cw_cnx, name='cw_cnx', property=True, reify=True)
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   239
    config.add_request_method(
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   240
        _cw_request, name='cw_request', property=True, reify=True)
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   241
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   242
    config.add_route('login', '/login')
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   243
    config.add_view(login, route_name='login')
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   244
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   245
    config.add_route('hello', '/hello')
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   246
    config.add_view(hello_world, route_name='hello')
151b8a4b9f3f Integration pyramid and cubicweb authentication.
Christophe de Vienne <christophe@unlish.com>
parents: 11480
diff changeset
   247
11484
39768d122f97 Isolate the default handler and extend its role
Christophe de Vienne <christophe@unlish.com>
parents: 11482
diff changeset
   248
    config.include('pyramid_cubicweb.handler')