~homeworkprod/byceps

ref: 533662eefb314d54b168e5a46bc07c88b5f88be4 byceps/byceps/blueprints/admin/authentication/login/views.py -rw-r--r-- 2.9 KiB
533662ee — Jochen Kupperschmidt Use Flask v2.0's `delete`/`get`/`patch`/`post` route shortcuts 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
"""
byceps.blueprints.admin.authentication.login.views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2006-2021 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

from flask import abort, g, redirect, request
from flask_babel import gettext

from .....services.authentication.exceptions import AuthenticationFailed
from .....services.authentication import service as authentication_service
from .....services.authentication.session import service as session_service
from .....signals import auth as auth_signals
from .....typing import UserID
from .....util.authorization import get_permissions_for_user
from .....util.framework.blueprint import create_blueprint
from .....util.framework.flash import flash_notice, flash_success
from .....util.framework.templating import templated
from .....util import user_session
from .....util.views import respond_no_content

from ....admin.core.authorization import AdminPermission

from .forms import LoginForm


blueprint = create_blueprint('authentication.login_admin', __name__)


@blueprint.get('/login')
@templated
def login_form():
    """Show login form."""
    if g.user.authenticated:
        flash_notice(
            gettext(
                'You are already logged in as "%(screen_name)s".',
                screen_name=g.user.screen_name,
            )
        )
        return redirect('/')

    form = LoginForm()

    return {'form': form}


@blueprint.post('/login')
@respond_no_content
def login():
    """Allow the user to authenticate with e-mail address and password."""
    if g.user.authenticated:
        return

    form = LoginForm(request.form)

    screen_name = form.screen_name.data.strip()
    password = form.password.data
    permanent = form.permanent.data
    if not all([screen_name, password]):
        abort(403)

    try:
        user = authentication_service.authenticate(screen_name, password)
    except AuthenticationFailed:
        abort(403)

    _require_admin_access_permission(user.id)

    # Authorization succeeded.

    auth_token, event = session_service.log_in_user(
        user.id, request.remote_addr
    )
    user_session.start(user.id, auth_token, permanent=permanent)

    flash_success(
        gettext(
            'Successfully logged in as %(screen_name)s.',
            screen_name=user.screen_name,
        )
    )

    auth_signals.user_logged_in.send(None, event=event)


def _require_admin_access_permission(user_id: UserID) -> None:
    permissions = get_permissions_for_user(user_id)
    if AdminPermission.access not in permissions:
        # The user lacks the admin access permission which is required
        # to enter the admin area.
        abort(403)


@blueprint.post('/logout')
@respond_no_content
def logout():
    """Log out user by deleting the corresponding cookie."""
    user_session.end()
    flash_success(gettext('Successfully logged out.'))