import functools from flask import Blueprint, flash, g, redirect, render_template, request, session, url_for from werkzeug.security import check_password_hash, generate_password_hash from .database import get_database blueprint = Blueprint("auth", __name__, url_prefix="/auth") @blueprint.route("/register", methods=("GET", "POST")) def register(): if request.method == "POST": username = request.form["username"] password = request.form["password"] db = get_database() error = None if not username: error = "username_required" elif not password: error = "password_required" if error is None: try: db.execute( "INSERT INTO user (username, password) VALUES (?, ?)", (username, generate_password_hash(password)), ) db.commit() except db.IntegrityError: error = f"User {username} is already registered." else: return redirect(url_for("auth.login")) flash(error) return render_template("auth/register.html") @blueprint.route("/login", methods=("GET", "POST")) def login(): if request.method == "POST": username = request.form["username"] password = request.form["password"] db = get_database() error = None user = db.execute( "SELECT * FROM user WHERE username = ?", (username,) ).fetchone() if user is None: error = "incorrect_username" elif not check_password_hash(user["password"], password): error = "incorrect_password" if error is None: session.clear() session["user_id"] = user["id"] return redirect(url_for("index")) flash(error) return render_template("auth/login.html") @blueprint.before_app_request def load_logged_in_user(): user_id = session.get("user_id") if user_id is None: g.user = None else: g.user = get_database().execute( "SELECT * FROM user WHERE id = ?", (user_id,) ).fetchone() @blueprint.route("/logout") def logout(): session.clear() return redirect(url_for("index")) def login_required(view): @functools.wraps(view) def wrapped_view(**kwargs): if g.user is None: return redirect(url_for("auth.login")) return view(**kwargs) return wrapped_view