feat: password change + split account/household settings UI
- New /change-password route: validates current password, enforces min 4 chars, requires confirmation match - update_password() helper in models.py - Dashboard UI split into two collapsible sections: 👤 Account Settings (password, ntfy, delete account) 🏠 Household Settings (admin only: public link, timezone, delete household) - 14 new i18n keys with fr/de translations - Restored accidentally dropped 'Delete My Account' key
This commit is contained in:
@@ -12,7 +12,7 @@ from flask import (
|
||||
flash,
|
||||
)
|
||||
|
||||
from werkzeug.security import check_password_hash
|
||||
from werkzeug.security import check_password_hash, generate_password_hash
|
||||
|
||||
from models import (
|
||||
get_dashboard_data,
|
||||
@@ -33,6 +33,7 @@ from models import (
|
||||
get_household_by_public_token,
|
||||
generate_public_token,
|
||||
set_public_enabled,
|
||||
update_password,
|
||||
)
|
||||
from i18n import t
|
||||
from ntfy import send_test_notification, send_meal_reminder
|
||||
@@ -191,6 +192,33 @@ def delete_account():
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
|
||||
@meals_bp.route("/change-password", methods=["POST"])
|
||||
@login_required
|
||||
def change_password():
|
||||
"""Change the logged-in user's password."""
|
||||
current = request.form.get("current_password", "")
|
||||
new = request.form.get("new_password", "")
|
||||
confirm = request.form.get("confirm_password", "")
|
||||
|
||||
user = get_user_by_id(session["user_id"])
|
||||
|
||||
if not check_password_hash(user["password_hash"], current):
|
||||
flash(t("Current password is incorrect."), "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
if len(new) < 4:
|
||||
flash(t("New password must be at least 4 characters."), "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
if new != confirm:
|
||||
flash(t("New passwords do not match."), "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
update_password(session["user_id"], generate_password_hash(new))
|
||||
flash(t("Password changed successfully."), "success")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
|
||||
@meals_bp.route("/admin/remove-user/<int:user_id>", methods=["POST"])
|
||||
@login_required
|
||||
def admin_remove_user(user_id):
|
||||
|
||||
Reference in New Issue
Block a user