from flask import Blueprint, request, session, render_template, redirect, url_for, abort from werkzeug.security import generate_password_hash, check_password_hash from .users import Users from .exceptions import UsernameTakenError from .config import config bp = Blueprint("auth", __name__, url_prefix="/") users = Users(config.get("general", "db_path")) def show_error(action, message): return render_template( "auth.html", action=action, error=message, ) @bp.route("/", methods=["GET", "POST"]) def auth(action): if action not in ["login", "register"]: abort(404) if request.method == "GET": # display login/register page return render_template("auth.html", action=action) # validate login information username = request.form.get("username") password = request.form.get("password") if not all([username, password]): return show_error(action, "Please fill in both the username and password.") if action == "login": user = users.find(username) if user is None: return show_error("login", f"User {username} does not exist.") if not check_password_hash(user["password"], password): return show_error("login", "Incorrect password. Sorry.") elif action == "register": if not config.getboolean("general", "accept_new_users"): return show_error("register", "Sorry, but user registrations are closed.") try: users.register(username, generate_password_hash(password), "en-US") except UsernameTakenError as e: return show_error("register", e.message) else: abort(400) # give access session.clear() session["username"] = username return redirect(url_for("admin.index")) @bp.route("/logout") def logout(): session.pop("username", None) return redirect(url_for("auth.auth", action="login"))