04/30 Web Checker web app ver. 1.0
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""
|
||||
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)
|
||||
Reference in New Issue
Block a user