cubicweb/pyramid/login.py
author Philippe Pepiot <ph@itsalwaysdns.eu>
Tue, 31 Mar 2020 19:15:03 +0200
changeset 12957 0c973204033a
parent 11967 83739be20fab
permissions -rw-r--r--
[server] prevent returning closed cursor to the database pool In since c8c6ad8 init_repository use repo.internal_cnx() instead of repo.system_source.get_connection() so it use the pool and we should not close cursors from the pool before returning it back. Otherwise we may have "connection already closed" error. This bug only trigger when connection-pool-size = 1. Since we are moving to use a dynamic pooler we need to get this fixed. This does not occur with sqlite since the connection wrapper instantiate new cursor everytime, but this occur with other databases.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11967
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     1
# copyright 2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     2
# copyright 2014-2016 UNLISH S.A.S. (Montpellier, FRANCE), all rights reserved.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     3
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     4
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     5
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     6
# This file is part of CubicWeb.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     7
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     8
# CubicWeb is free software: you can redistribute it and/or modify it under the
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
     9
# terms of the GNU Lesser General Public License as published by the Free
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    10
# Software Foundation, either version 2.1 of the License, or (at your option)
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    11
# any later version.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    12
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    13
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    14
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    15
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    16
# details.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    17
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    18
# You should have received a copy of the GNU Lesser General Public License along
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    19
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11924
diff changeset
    20
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    21
""" Provide login views that reproduce a classical CubicWeb behavior"""
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    22
from pyramid import security
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    23
from pyramid.httpexceptions import HTTPSeeOther
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    24
from pyramid.view import view_config
11562
a49f08423f02 [auth] Use a second authtkt policy for 'rememberme'
Christophe de Vienne <christophe@unlish.com>
parents: 11537
diff changeset
    25
from pyramid.settings import asbool
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    26
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    27
import cubicweb
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    28
11631
faf279e33298 Merge with pyramid-cubicweb
Yann Voté <yann.vote@logilab.fr>
parents: 11628
diff changeset
    29
from cubicweb.pyramid.core import render_view
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    30
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    31
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    32
@view_config(route_name='login')
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    33
def login_form(request):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    34
    """ Default view for the 'login' route.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    35
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    36
    Display the 'login' CubicWeb view, which is should be a login form"""
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    37
    request.response.text = render_view(request, 'login')
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    38
    return request.response
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    39
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    40
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    41
@view_config(route_name='login', request_param=('__login', '__password'))
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    42
def login_password_login(request):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    43
    """ Handle GET/POST of __login/__password on the 'login' route.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    44
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    45
    The authentication itself is delegated to the CubicWeb repository.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    46
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    47
    Request parameters:
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    48
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    49
    :param __login: The user login (or email if :confval:`allow-email-login` is
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    50
                    on.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    51
    :param __password: The user password
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    52
    :param __setauthcookie: (optional) If defined and equal to '1', set the
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    53
                            authentication cookie maxage to 1 week.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    54
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    55
                            If not, the authentication cookie is a session
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    56
                            cookie.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    57
    """
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    58
    repo = request.registry['cubicweb.repository']
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    59
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    60
    user_eid = None
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    61
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    62
    login = request.params['__login']
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    63
    password = request.params['__password']
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    64
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    65
    try:
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    66
        with repo.internal_cnx() as cnx:
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    67
            user = repo.authenticate_user(cnx, login, password=password)
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    68
            user_eid = user.eid
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    69
    except cubicweb.AuthenticationError:
11816
6392f34fcdad [pyramid] Fix login error message language
Florent Cayré <florent.cayre@logilab.fr>
parents: 11631
diff changeset
    70
        if repo.vreg.config.get('language-mode') != '':
6392f34fcdad [pyramid] Fix login error message language
Florent Cayré <florent.cayre@logilab.fr>
parents: 11631
diff changeset
    71
            lang = request.cw_request.negotiated_language()
6392f34fcdad [pyramid] Fix login error message language
Florent Cayré <florent.cayre@logilab.fr>
parents: 11631
diff changeset
    72
            if lang is not None:
6392f34fcdad [pyramid] Fix login error message language
Florent Cayré <florent.cayre@logilab.fr>
parents: 11631
diff changeset
    73
                request.cw_request.set_language(lang)
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    74
        request.cw_request.set_message(request.cw_request._(
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    75
            "Authentication failed. Please check your credentials."))
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    76
        request.cw_request.post = dict(request.params)
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    77
        del request.cw_request.post['__password']
11628
0f12ee84f30a Test and fix status code and content of the login form on authentication error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11609
diff changeset
    78
        request.response.status_code = 403
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    79
        return login_form(request)
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    80
11562
a49f08423f02 [auth] Use a second authtkt policy for 'rememberme'
Christophe de Vienne <christophe@unlish.com>
parents: 11537
diff changeset
    81
    headers = security.remember(
a49f08423f02 [auth] Use a second authtkt policy for 'rememberme'
Christophe de Vienne <christophe@unlish.com>
parents: 11537
diff changeset
    82
        request, user_eid,
a49f08423f02 [auth] Use a second authtkt policy for 'rememberme'
Christophe de Vienne <christophe@unlish.com>
parents: 11537
diff changeset
    83
        persistent=asbool(request.params.get('__setauthcookie', False)))
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    84
11609
cc1d4b66ca26 [login] fix the redirect url after login (closes #11689118)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11562
diff changeset
    85
    new_path = request.params.get('postlogin_path', '')
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    86
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    87
    if new_path == 'login':
11609
cc1d4b66ca26 [login] fix the redirect url after login (closes #11689118)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11562
diff changeset
    88
        new_path = ''
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    89
11609
cc1d4b66ca26 [login] fix the redirect url after login (closes #11689118)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11562
diff changeset
    90
    url = request.cw_request.build_url(new_path)
cc1d4b66ca26 [login] fix the redirect url after login (closes #11689118)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11562
diff changeset
    91
    raise HTTPSeeOther(url, headers=headers)
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    92
11494
79ce84750c18 If the postlogin_path is 'login', redirect to '/' instead
Christophe de Vienne <christophe@unlish.com>
parents: 11493
diff changeset
    93
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    94
@view_config(route_name='login', effective_principals=security.Authenticated)
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    95
def login_already_loggedin(request):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    96
    """ 'login' route view for Authenticated users.
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    97
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
    98
    Simply redirect the user to '/'."""
11497
855219da7c70 Use a predicate based view selection for handling /login
Christophe de Vienne <christophe@unlish.com>
parents: 11494
diff changeset
    99
    raise HTTPSeeOther('/')
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   100
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   101
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   102
def includeme(config):
11537
caf268942436 Initial documentation.
Christophe de Vienne <christophe@unlish.com>
parents: 11527
diff changeset
   103
    """ Create the 'login' route ('/login') and load this module views"""
11924
4c949c28ce59 [pyramid] fix login route with language-mode = url-prefix
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 11816
diff changeset
   104
    cwconfig = config.registry['cubicweb.config']
11493
00e5cb9771c5 Put the login view in a separate module.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   105
    config.add_route('login', '/login')
11924
4c949c28ce59 [pyramid] fix login route with language-mode = url-prefix
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 11816
diff changeset
   106
    if cwconfig.get('language-mode') == 'url-prefix':
4c949c28ce59 [pyramid] fix login route with language-mode = url-prefix
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 11816
diff changeset
   107
        config.add_route('login-lang', '/{lang}/login')
4c949c28ce59 [pyramid] fix login route with language-mode = url-prefix
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 11816
diff changeset
   108
        config.add_view(login_already_loggedin, route_name='login-lang',
4c949c28ce59 [pyramid] fix login route with language-mode = url-prefix
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 11816
diff changeset
   109
                        effective_principals=security.Authenticated)
4c949c28ce59 [pyramid] fix login route with language-mode = url-prefix
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 11816
diff changeset
   110
        config.add_view(login_form, route_name='login-lang')
4c949c28ce59 [pyramid] fix login route with language-mode = url-prefix
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 11816
diff changeset
   111
        config.add_view(login_password_login, route_name='login-lang',
4c949c28ce59 [pyramid] fix login route with language-mode = url-prefix
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 11816
diff changeset
   112
                        request_param=('__login', '__password'))
11631
faf279e33298 Merge with pyramid-cubicweb
Yann Voté <yann.vote@logilab.fr>
parents: 11628
diff changeset
   113
    config.scan('cubicweb.pyramid.login')