diff --git a/server/app.py b/server/app.py index a27c995..f9711c5 100644 --- a/server/app.py +++ b/server/app.py @@ -354,6 +354,45 @@ def logout(): return redirect(url_for("login_page")) +@app.get("/account/password") +@require_login +def change_password_page(): + csrf_token = secrets.token_hex(16) + session["csrf_token"] = csrf_token + return render_template("change_password.html", csrf_token=csrf_token) + + +@app.post("/account/password") +@require_login +def change_password(): + token = request.form.get("csrf_token", "") + if not token or token != session.pop("csrf_token", None): + flash("Invalid request. Please try again.", "error") + return redirect(url_for("change_password_page")) + + current = request.form.get("current_password", "") + new_pw = request.form.get("new_password", "") + confirm = request.form.get("confirm_password", "") + + user_row = db.get_user_by_id(current_user.id) + if not user_row or not check_password(current, user_row["password_hash"]): + flash("Current password is incorrect.", "error") + return redirect(url_for("change_password_page")) + if len(new_pw) < 8: + flash("New password must be at least 8 characters.", "error") + return redirect(url_for("change_password_page")) + if new_pw != confirm: + flash("Passwords do not match.", "error") + return redirect(url_for("change_password_page")) + + from modules.user_auth import hash_password + with db.get_cursor(commit=True) as cur: + cur.execute("UPDATE users SET password_hash = %s WHERE id = %s", + (hash_password(new_pw), current_user.id)) + flash("Password updated successfully.", "success") + return redirect(url_for("change_password_page")) + + # ── Portal UI pages ──────────────────────────────────────────────────────── @app.get("/") diff --git a/server/templates/base.html b/server/templates/base.html index 03c11d6..30c99fd 100644 --- a/server/templates/base.html +++ b/server/templates/base.html @@ -45,6 +45,8 @@
{{ current_user.username }}  ·  + Password +  ·  Logout
+ Cancel + + + + + + +{% endblock %}