Phase 24: add password change page
- GET/POST /account/password with CSRF token and bcrypt re-hash - 'Password' link in sidebar next to Logout - change_password.html template Co-authored-by: Copilot <[email protected]>
This commit is contained in:
@@ -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("/")
|
||||
|
||||
Reference in New Issue
Block a user