pyramid_cubicweb/core.py
author Christophe de Vienne <christophe@unlish.com>
Sat, 03 Jan 2015 22:06:03 +0100
changeset 11537 caf268942436
parent 11536 6618408c0629
child 11552 d92a608c1a16
permissions -rw-r--r--
Initial documentation. Closes #4849313
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     1
from contextlib import contextmanager
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     2
from warnings import warn
11508
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
     3
from cgi import FieldStorage
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     4
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     5
import rql
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     6
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     7
from cubicweb.web.request import CubicWebRequestBase
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     8
from cubicweb import repoapi
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     9
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    10
import cubicweb
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    11
import cubicweb.web
11512
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
    12
from cubicweb.server.session import Session
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    13
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents: 11492
diff changeset
    14
from pyramid import httpexceptions
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    15
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    16
from pyramid_cubicweb import authplugin
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    17
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    18
import logging
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    19
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    20
log = logging.getLogger(__name__)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    21
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    22
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    23
@contextmanager
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    24
def cw_to_pyramid(request):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
    25
    """ Context manager to wrap a call to the cubicweb API.
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    26
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    27
    All CW exceptions will be transformed into their pyramid equivalent.
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    28
    When needed, some CW reponse bits may be converted too (mainly headers)"""
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    29
    try:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    30
        yield
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    31
    except cubicweb.web.Redirect as ex:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    32
        assert 300 <= ex.status < 400
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    33
        raise httpexceptions.status_map[ex.status](ex.location)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    34
    except cubicweb.web.StatusResponse as ex:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    35
        warn('[3.16] StatusResponse is deprecated use req.status_out',
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    36
             DeprecationWarning, stacklevel=2)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    37
        request.body = ex.content
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    38
        request.status_int = ex.status
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    39
    except cubicweb.web.Unauthorized as ex:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    40
        raise httpexceptions.HTTPForbidden(
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    41
            request.cw_request._(
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    42
                'You\'re not authorized to access this page. '
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    43
                'If you think you should, please contact the site '
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    44
                'administrator.'))
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    45
    except cubicweb.web.Forbidden:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    46
        raise httpexceptions.HTTPForbidden(
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    47
            request.cw_request._(
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    48
                'This action is forbidden. '
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    49
                'If you think it should be allowed, please contact the site '
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    50
                'administrator.'))
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    51
    except (rql.BadRQLQuery, cubicweb.web.RequestError) as ex:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    52
        raise
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    53
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    54
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    55
class CubicWebPyramidRequest(CubicWebRequestBase):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
    56
    """ A CubicWeb request that only wraps a pyramid request.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
    57
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
    58
    :param request: A pyramid request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
    59
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
    60
    """
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    61
    def __init__(self, request):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    62
        self._request = request
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    63
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    64
        self.path = request.upath_info
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    65
11498
a8aaff87c1fc Use registry['cubicweb.registry'] instead of registry['cubicweb.appli'].vreg because the application may not be present.
Christophe de Vienne <christophe@unlish.com>
parents: 11493
diff changeset
    66
        vreg = request.registry['cubicweb.registry']
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    67
        https = request.scheme == 'https'
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    68
11504
8701caf9edf0 Correctly pass the multiple parameters to the cubicweb request
Christophe de Vienne <christophe@unlish.com>
parents: 11502
diff changeset
    69
        post = request.params.mixed()
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    70
        headers_in = request.headers
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    71
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    72
        super(CubicWebPyramidRequest, self).__init__(vreg, https, post,
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    73
                                                     headers=headers_in)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    74
11508
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    75
        self.content = request.body_file_seekable
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    76
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    77
    def setup_params(self, params):
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    78
        self.form = {}
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    79
        for param, val in params.iteritems():
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    80
            if param in self.no_script_form_params and val:
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    81
                val = self.no_script_form_param(param, val)
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    82
            if isinstance(val, FieldStorage) and val.file:
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    83
                val = (val.filename, val.file)
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    84
            if param == '_cwmsgid':
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    85
                self.set_message_id(val)
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    86
            elif param == '__message':
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    87
                warn('[3.13] __message in request parameter is deprecated '
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    88
                     '(may only be given to .build_url). Seeing this message '
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    89
                     'usualy means your application hold some <form> where '
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    90
                     'you should replace use of __message hidden input by '
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    91
                     'form.set_message, so new _cwmsgid mechanism is properly '
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    92
                     'used',
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    93
                     DeprecationWarning)
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    94
                self.set_message(val)
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    95
            else:
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    96
                self.form[param] = val
ef8b9021b47b Fix POST handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11504
diff changeset
    97
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    98
    def is_secure(self):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    99
        return self._request.scheme == 'https'
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   100
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   101
    def relative_path(self, includeparams=True):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   102
        path = self._request.path[1:]
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   103
        if includeparams and self._request.query_string:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   104
            return '%s?%s' % (path, self._request.query_string)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   105
        return path
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   106
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   107
    def instance_uri(self):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   108
        return self._request.application_url
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   109
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   110
    def get_full_path(self):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   111
        path = self._request.path
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   112
        if self._request.query_string:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   113
            return '%s?%s' % (path, self._request.query_string)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   114
        return path
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   115
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   116
    def http_method(self):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   117
        return self._request.method
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   118
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   119
    def _set_status_out(self, value):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   120
        self._request.response.status_int = value
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   121
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   122
    def _get_status_out(self):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   123
        return self._request.response.status_int
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   124
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   125
    status_out = property(_get_status_out, _set_status_out)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   126
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   127
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   128
def render_view(request, vid, **kwargs):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   129
    """ Helper function to render a CubicWeb view.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   130
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   131
    :param request: A pyramid request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   132
    :param vid: A CubicWeb view id
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   133
    :param **kwargs: Keyword arguments to select and instanciate the view
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   134
    :returns: The rendered view content
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   135
    """
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   136
    vreg = request.registry['cubicweb.registry']
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   137
    # XXX The select() function could, know how to handle a pyramid
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   138
    # request, and feed it directly to the views that supports it.
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   139
    # On the other hand, we could refine the View concept and decide it works
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   140
    # with a cnx, and never with a WebRequest
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   141
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   142
    with cw_to_pyramid(request):
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   143
        view = vreg['views'].select(vid, request.cw_request, **kwargs)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   144
        view.set_stream()
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   145
        view.render()
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   146
        return view._stream.getvalue()
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   147
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   148
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   149
def _cw_cnx(request):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   150
    """ Obtains a cw session from a pyramid request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   151
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   152
    The connection will be commited or rolled-back in a request finish
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   153
    callback (this is temporary, we should make use of the transaction manager
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   154
    in a later version).
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   155
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   156
    Not meant for direct use, use ``request.cw_cnx`` instead.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   157
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   158
    :param request: A pyramid request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   159
    :returns type: :class:`cubicweb.server.session.Connection`
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   160
    """
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   161
    cnx = repoapi.ClientConnection(request.cw_session)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   162
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   163
    def cleanup(request):
11524
54c83bfda277 Don't rollback if exception is HTTPSuccessful or HTTPRedirection
Christophe de Vienne <christophe@unlish.com>
parents: 11513
diff changeset
   164
        if (request.exception is not None and not isinstance(
54c83bfda277 Don't rollback if exception is HTTPSuccessful or HTTPRedirection
Christophe de Vienne <christophe@unlish.com>
parents: 11513
diff changeset
   165
            request.exception, (
54c83bfda277 Don't rollback if exception is HTTPSuccessful or HTTPRedirection
Christophe de Vienne <christophe@unlish.com>
parents: 11513
diff changeset
   166
                httpexceptions.HTTPSuccessful,
54c83bfda277 Don't rollback if exception is HTTPSuccessful or HTTPRedirection
Christophe de Vienne <christophe@unlish.com>
parents: 11513
diff changeset
   167
                httpexceptions.HTTPRedirection))):
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   168
            cnx.rollback()
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   169
        else:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   170
            cnx.commit()
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   171
        cnx.__exit__(None, None, None)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   172
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   173
    request.add_finished_callback(cleanup)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   174
    cnx.__enter__()
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   175
    return cnx
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   176
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   177
11513
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   178
def repo_connect(repo, eid):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   179
    """A lightweight version of
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   180
    :meth:`cubicweb.server.repository.Repository.connect` that does not keep
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   181
    track of opened sessions, removing the need of closing them"""
11512
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   182
    with repo.internal_cnx() as cnx:
11513
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   183
        user = repo._build_user(cnx, eid=eid)
11512
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   184
    session = Session(user, repo, None)
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   185
    user._cw = user.cw_rset.req = session
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   186
    user.cw_clear_relation_cache()
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   187
    # Calling the hooks should be done only once, disabling it completely for
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   188
    # now
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   189
    #with session.new_cnx() as cnx:
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   190
        #repo.hm.call_hooks('session_open', cnx)
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   191
        #cnx.commit()
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   192
    # repo._sessions[session.sessionid] = session
bb548010b390 Use lightweight sessions
Christophe de Vienne <christophe@unlish.com>
parents: 11508
diff changeset
   193
    return session
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   194
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   195
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   196
def _cw_session(request):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   197
    """Obtains a cw session from a pyramid request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   198
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   199
    :param request: A pyramid request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   200
    :returns type: :class:`cubicweb.server.session.Session`
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   201
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   202
    Not meant for direct use, use ``request.cw_session`` instead.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   203
    """
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   204
    repo = request.registry['cubicweb.repository']
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   205
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   206
    if not request.authenticated_userid:
11513
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   207
        session = repo_connect(
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   208
            repo, eid=request.registry['cubicweb.anonymous_eid'])
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   209
    else:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   210
        session = request._cw_cached_session
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   211
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   212
    # XXX Ideally we store the cw session data in the pyramid session.
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   213
    # BUT some data in the cw session data dictionnary makes pyramid fail.
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   214
    session.data = request.session
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   215
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   216
    return session
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   217
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   218
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   219
def _cw_request(request):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   220
    """ Obtains a CubicWeb request wrapper for the pyramid request.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   221
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   222
    :param request: A pyramid request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   223
    :return: A CubicWeb request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   224
    :returns type: :class:`CubicWebPyramidRequest`
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   225
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   226
    Not meant for direct use, use ``request.cw_request`` instead.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   227
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   228
    """
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   229
    req = CubicWebPyramidRequest(request)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   230
    req.set_cnx(request.cw_cnx)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   231
    return req
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   232
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   233
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   234
def get_principals(login, request):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   235
    """ Returns the group names of the authenticated user.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   236
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   237
    This function is meant to be used as an authentication policy callback.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   238
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   239
    It also pre-open the cubicweb session and put it in
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   240
    request._cw_cached_session for later usage by :func:`_cw_session`.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   241
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   242
    .. note::
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   243
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   244
        It the default authentication policy is not used, make sure this
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   245
        function gets called by the active authentication policy.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   246
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   247
    :param login: A cubicweb user eid
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   248
    :param request: A pyramid request
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   249
    :returns: A list of group names
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   250
    """
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   251
    repo = request.registry['cubicweb.repository']
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   252
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   253
    try:
11513
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   254
        session = repo_connect(repo, eid=login)
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   255
        request._cw_cached_session = session
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   256
    except:
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   257
        log.exception("Failed")
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   258
        raise
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   259
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   260
    return session.user.groups
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   261
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   262
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   263
def includeme(config):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   264
    """ Enables the core features of Pyramid CubicWeb.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   265
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   266
    Automatically called by the 'pyramid' command, or via
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   267
    ``config.include('pyramid_cubicweb.code')``. In the later case,
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   268
    the following registry entries must be defined first:
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   269
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   270
    'cubicweb.config'
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   271
        A cubicweb 'config' instance.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   272
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   273
    'cubicweb.repository'
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   274
        The correponding cubicweb repository.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   275
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   276
    'cubicweb.registry'
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   277
        The vreg.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11536
diff changeset
   278
    """
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   279
    repo = config.registry['cubicweb.repository']
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   280
11513
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   281
    with repo.internal_cnx() as cnx:
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   282
        login = config.registry['cubicweb.config'].anonymous_user()[0]
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   283
        config.registry['cubicweb.anonymous_eid'] = cnx.find(
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   284
            'CWUser', login=login).one().eid
0170f8a55620 Optimise repo_connect by skipping authenticate_user
Christophe de Vienne <christophe@unlish.com>
parents: 11512
diff changeset
   285
11492
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   286
    repo.system_source.add_authentifier(authplugin.DirectAuthentifier())
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   287
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   288
    config.add_request_method(
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   289
        _cw_session, name='cw_session', property=True, reify=True)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   290
    config.add_request_method(
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   291
        _cw_cnx, name='cw_cnx', property=True, reify=True)
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   292
    config.add_request_method(
b0b8942cdb80 Separate into 4 modules
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   293
        _cw_request, name='cw_request', property=True, reify=True)
11502
e4682c567e86 If any cube has a 'includeme' attribute, call config.include on it
Christophe de Vienne <christophe@unlish.com>
parents: 11500
diff changeset
   294
e4682c567e86 If any cube has a 'includeme' attribute, call config.include on it
Christophe de Vienne <christophe@unlish.com>
parents: 11500
diff changeset
   295
    cwcfg = config.registry['cubicweb.config']
e4682c567e86 If any cube has a 'includeme' attribute, call config.include on it
Christophe de Vienne <christophe@unlish.com>
parents: 11500
diff changeset
   296
    for cube in cwcfg.cubes():
e4682c567e86 If any cube has a 'includeme' attribute, call config.include on it
Christophe de Vienne <christophe@unlish.com>
parents: 11500
diff changeset
   297
        pkgname = 'cubes.' + cube
e4682c567e86 If any cube has a 'includeme' attribute, call config.include on it
Christophe de Vienne <christophe@unlish.com>
parents: 11500
diff changeset
   298
        mod = __import__(pkgname)
e4682c567e86 If any cube has a 'includeme' attribute, call config.include on it
Christophe de Vienne <christophe@unlish.com>
parents: 11500
diff changeset
   299
        mod = getattr(mod, cube)
e4682c567e86 If any cube has a 'includeme' attribute, call config.include on it
Christophe de Vienne <christophe@unlish.com>
parents: 11500
diff changeset
   300
        if hasattr(mod, 'includeme'):
e4682c567e86 If any cube has a 'includeme' attribute, call config.include on it
Christophe de Vienne <christophe@unlish.com>
parents: 11500
diff changeset
   301
            config.include('cubes.' + cube)