-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbp_auth.py
executable file
·114 lines (85 loc) · 3.24 KB
/
bp_auth.py
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
103
104
105
106
107
108
109
110
111
112
113
114
from enum import Enum
from functools import wraps
from flask import Blueprint, current_app, flash, redirect, render_template, session, url_for
from sqlalchemy import select
from werkzeug.security import check_password_hash
from configs import CONSTS
from db import get_user_by_username
from forms import LoginForm
from limiter import limiter
from models import User, UserRole, db
bp_auth = Blueprint("bp_auth", __name__, template_folder="templates")
class AuthActions(Enum):
is_logged_in = 1
log_in = 2
log_out = 3
get_user_id = 4
is_admin = 5
def auth(action: AuthActions, user_id=None):
with current_app.app_context():
if action == AuthActions.is_logged_in:
return "user_id" in session
if action == AuthActions.log_in and user_id:
session["user_id"] = user_id
return
if action == AuthActions.log_out:
session.clear()
return
if action == AuthActions.get_user_id:
return session.get("user_id", None)
if action == AuthActions.is_admin:
user_id = auth(AuthActions.get_user_id)
if user_id:
user_id = db.session.scalar(select(User.id).where(User.id == user_id).where(User.role == UserRole.admin.value))
if user_id:
return True
return False
raise ValueError(action, user_id)
def login_required(fn):
@wraps(fn)
def decorated_function(*args, **kwargs):
if not auth(AuthActions.is_logged_in):
flash("Login required", "danger")
return redirect(url_for("bp_auth.login"))
return fn(*args, **kwargs)
return decorated_function
def logout_required(fn):
@wraps(fn)
def decorated_function(*args, **kwargs):
if auth(AuthActions.is_logged_in):
flash("Logout required", "danger")
return redirect(url_for("bp_auth.logout"))
return fn(*args, **kwargs)
return decorated_function
def admin_required(fn):
@wraps(fn)
def decorated_function(*args, **kwargs):
if not auth(AuthActions.is_admin):
flash("Permission required", "danger")
return redirect(url_for("index"))
return fn(*args, **kwargs)
return decorated_function
@bp_auth.route("/login", methods=["GET", "POST"])
@limiter.limit("5/minute", methods=["POST"])
@limiter.limit("30/day", methods=["POST"])
def login():
form = LoginForm()
if form.validate_on_submit():
username = form.username.data
password_candidate = form.password.data
user = get_user_by_username(username)
if user:
if check_password_hash(user.password, password_candidate):
auth(AuthActions.log_in, user_id=user.id)
flash("Login successful.", "success")
return redirect(url_for("bp_hurl.hurl_list"))
flash("Incorrect username or password.", "danger")
return render_template(
"login.html", form=form, CONSTS=CONSTS, logged_in=auth(AuthActions.is_logged_in), is_admin=auth(AuthActions.is_admin)
)
@bp_auth.route("/logout", methods=["GET"])
@login_required
def logout():
auth(AuthActions.log_out)
flash("Logout successful.", "success")
return redirect(url_for("bp_auth.login"))