Files
agentbox-test/auth.py
T
2026-08-01 06:00:29 +00:00

118 lines
4.3 KiB
Python

"""Authentication blueprint — login, register, logout."""
from flask import Blueprint, request, render_template, redirect, url_for, session, flash
from werkzeug.security import generate_password_hash, check_password_hash
from models import (
get_user_by_username,
create_user,
create_household,
get_household_by_name,
get_household_by_id,
get_all_households,
count_household_users,
)
from i18n import t
auth_bp = Blueprint("auth", __name__)
@auth_bp.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form.get("username", "").strip()
password = request.form.get("password", "")
if not username or not password:
flash(t("Username and password are required."), "error")
return render_template("login.html")
user = get_user_by_username(username)
if user is None or not check_password_hash(user["password_hash"], password):
flash(t("Invalid username or password."), "error")
return render_template("login.html")
household_id = user["household_id"]
household = get_household_by_id(household_id) if household_id else None
session.clear()
session["user_id"] = user["id"]
session["username"] = user["username"]
session["is_admin"] = bool(user["is_admin"])
session["household_id"] = household_id
session["household_name"] = household["name"] if household else "Unknown"
return redirect(url_for("meals.dashboard"))
return render_template("login.html")
@auth_bp.route("/register", methods=["GET", "POST"])
def register():
households = get_all_households()
if request.method == "POST":
username = request.form.get("username", "").strip()
password = request.form.get("password", "")
confirm = request.form.get("confirm", "")
household_action = request.form.get("household_action", "join") # "join" or "create"
household_id = request.form.get("household_id", "").strip()
new_household_name = request.form.get("new_household_name", "").strip()
errors = []
if not username or len(username) < 2:
errors.append(t("Username must be at least 2 characters."))
if not password or len(password) < 4:
errors.append(t("Password must be at least 4 characters."))
if password != confirm:
errors.append(t("Passwords do not match."))
if get_user_by_username(username):
errors.append(t("Username already taken."))
target_household_id = None
if household_action == "create":
if not new_household_name:
errors.append(t("Household name is required."))
elif get_household_by_name(new_household_name):
errors.append(t("A household with that name already exists."))
else:
household = create_household(new_household_name)
target_household_id = household["id"]
is_admin = True # First user in a new household is admin
else:
if not household_id:
errors.append(t("Please select a household."))
else:
hh = get_household_by_id(int(household_id))
if hh is None:
errors.append(t("Selected household does not exist."))
else:
target_household_id = hh["id"]
is_admin = False
if errors:
for e in errors:
flash(e, "error")
return render_template("register.html", households=households)
password_hash = generate_password_hash(password)
user = create_user(username, password_hash, target_household_id, is_admin=is_admin)
session.clear()
session["user_id"] = user["id"]
session["username"] = user["username"]
session["is_admin"] = bool(user["is_admin"])
session["household_id"] = user["household_id"]
session["household_name"] = get_household_by_id(target_household_id)["name"]
flash(t("Account created! Welcome to your household."), "success")
return redirect(url_for("meals.dashboard"))
return render_template("register.html", households=households)
@auth_bp.route("/logout")
def logout():
session.clear()
return redirect(url_for("auth.login"))