~fluix/tilde

ref: 5eafb87dcb66444a197f18e647160b174916aad8 tilde/auth/views.py -rw-r--r-- 3.2 KiB
5eafb87dSteven Guikal Add auth check command for ergo IRC server 9 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
103
104
105
106
107
# SPDX-FileCopyrightText: 2021 Steven Guikal <void@fluix.one>
#
# SPDX-License-Identifier: AGPL-3.0-only

import json

from flask import (
    Blueprint,
    current_app,
    flash,
    redirect,
    render_template,
    request,
    session,
    url_for,
)
from flask_login import login_required, login_user, logout_user
from sqlalchemy.exc import IntegrityError

from .forms import LoginForm, RegistrationForm
from .models import Status, User

auth = Blueprint("auth", __name__, template_folder="templates")
db = current_app.config["db"]


@auth.route("/")
@login_required
def account():
    return render_template("account.html")


@auth.route("/logout", methods=["POST"])
@login_required
def logout():
    logout_user()
    flash("Logged out successfully.")
    return redirect(url_for("flatpages.index"))


@auth.route("/login", methods=["GET", "POST"])
def login():
    form = LoginForm(request.form)
    if request.method == "POST" and form.validate():
        user = User.query.filter_by(username=form.username.data).first()

        if not user or not user.check_password(form.password.data):
            form.username.errors.append("Username or password is incorrect.")
            return render_template("login.html", form=form)

        # TODO: Move these on to the Enum itself
        status_errors = {
            Status.PENDING: "User is pending verification.",
            Status.DELETED: "User is deleted.",
            Status.BANNED: "User is banned.",
        }
        if status_error := status_errors.get(user.status):
            form.username.errors.append(status_error)
        if form.errors:
            return render_template("login.html", form=form)

        login_user(user)
        flash(f"Login successful. Welcome ~{user.username}!")
        return redirect(session.get("next", url_for("flatpages.index")))
    return render_template("login.html", form=form)


@auth.route("/register", methods=["GET", "POST"])
def register():
    form = RegistrationForm(request.form)
    if request.method == "POST" and form.validate():
        user = User(
            username=form.username.data,
            email=form.email.data,
            bio=form.bio.data,
        )
        user.set_password(form.password1.data)
        db.session.add(user)
        try:
            db.session.commit()
        except IntegrityError as e:
            db.session.rollback()
            form.username.errors.append("Username taken.")
            return render_template("register.html", form=form)

        flash("Account registration sent in. Please await a reply.")
        return redirect(url_for("flatpages.index"))
    return render_template("register.html", form=form)


@auth.cli.command("ergo")
def ergo():
    data = json.loads(input())
    status_errors = {
        Status.PENDING: "User is pending verification.",
        Status.DELETED: "User is deleted.",
        Status.BANNED: "User is banned.",
    }
    out = {"success": True}

    user = User.query.filter_by(username=data.get("accountName", "")).first()
    if not user or not user.check_password(data.get("passphrase")):
        out = {"success": False, "error": "Username or password is incorrect."}
    elif status_error := status_errors.get(user.status):
        out = {"success": False, "error": status_error}

    print(json.dumps(out))