Files
WebChecker--Web-app-/routes/auth.py
T

89 lines
3.2 KiB
Python

"""
routes/auth.py — Authentication routes: login, logout, change-password.
"""
import logging
from flask import Blueprint, render_template, request, session, redirect, url_for, flash
from models import authenticate, check_login_allowed, change_password, log_action
from utils.decorators import login_required
logger = logging.getLogger("routes.auth")
auth_bp = Blueprint("auth", __name__)
@auth_bp.route("/login", methods=["GET", "POST"])
def login():
if "user" in session:
return redirect(url_for("index"))
error = None
if request.method == "POST":
username = request.form.get("username", "").strip()
password = request.form.get("password", "")
ip = request.remote_addr
allowed, seconds_remaining = check_login_allowed(username)
if not allowed:
mins = seconds_remaining // 60
secs = seconds_remaining % 60
error = f"Account locked. Try again in {mins}m {secs}s."
logger.warning(f"Login blocked for '{username}' — still locked ({seconds_remaining}s remaining).")
else:
user = authenticate(username, password)
if user:
session.permanent = True
# Store a safe subset — never store the password hash in session
session["user"] = {
"id": user["id"],
"username": user["username"],
"full_name": user.get("full_name") or user["username"],
"role": user["role"],
"email": user.get("email", ""),
}
logger.info(f"User '{username}' logged in from {ip}.")
flash(f"You have been signed in. Welcome, {session['user']['full_name']}!", "success")
if user["role"] == "admin":
return redirect(url_for("admin_dashboard.dashboard"))
return redirect(url_for("user_dashboard.my_shifts"))
else:
error = "Invalid username or password."
return render_template("login.html", error=error)
@auth_bp.route("/logout")
@login_required
def logout():
user = session.get("user", {})
if user:
log_action(user["id"], "LOGOUT", "users", user["id"],
f"User '{user['username']}' logged out.")
logger.info(f"User '{user['username']}' logged out.")
session.clear()
flash("You have been signed out.", "info")
return redirect(url_for("auth.login"))
@auth_bp.route("/change-password", methods=["GET", "POST"])
@login_required
def change_password_view():
user = session["user"]
success = None
error = None
if request.method == "POST":
old_pw = request.form.get("old_password", "")
new_pw = request.form.get("new_password", "")
confirm = request.form.get("confirm_password", "")
if new_pw != confirm:
error = "New password and confirmation do not match."
else:
ok, msg = change_password(user["id"], old_pw, new_pw)
if ok:
success = msg
else:
error = msg
return render_template("change_password.html", success=success, error=error)