Add account deletion, admin user removal, household deletion, grayed-out other-user chips (47 tests)
This commit is contained in:
@@ -12,7 +12,17 @@ from flask import (
|
||||
flash,
|
||||
)
|
||||
|
||||
from models import get_dashboard_data, upsert_response, ensure_meal_periods
|
||||
from werkzeug.security import check_password_hash
|
||||
|
||||
from models import (
|
||||
get_dashboard_data,
|
||||
upsert_response,
|
||||
ensure_meal_periods,
|
||||
get_user_by_id,
|
||||
delete_user,
|
||||
delete_household,
|
||||
count_household_users,
|
||||
)
|
||||
|
||||
meals_bp = Blueprint("meals", __name__)
|
||||
|
||||
@@ -64,6 +74,8 @@ def dashboard():
|
||||
today=date.today(),
|
||||
prev_date=today - timedelta(days=1),
|
||||
next_date=today + timedelta(days=1),
|
||||
current_user_id=session["user_id"],
|
||||
is_admin=session["is_admin"],
|
||||
)
|
||||
|
||||
|
||||
@@ -119,5 +131,82 @@ def history():
|
||||
today=date.today(),
|
||||
prev_date=target_date - timedelta(days=1),
|
||||
next_date=target_date + timedelta(days=1),
|
||||
current_user_id=session["user_id"],
|
||||
is_admin=session["is_admin"],
|
||||
history_mode=True,
|
||||
)
|
||||
|
||||
|
||||
# ── Account / household management ────────────────────────────────────────────
|
||||
|
||||
@meals_bp.route("/delete-account", methods=["POST"])
|
||||
@login_required
|
||||
def delete_account():
|
||||
"""Delete the currently logged-in user's own account."""
|
||||
password = request.form.get("password", "")
|
||||
user = get_user_by_id(session["user_id"])
|
||||
|
||||
if not check_password_hash(user["password_hash"], password):
|
||||
flash("Incorrect password. Account not deleted.", "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
household_id = session["household_id"]
|
||||
is_admin = session["is_admin"]
|
||||
user_count = count_household_users(household_id)
|
||||
|
||||
# If admin is the last user, delete the household too
|
||||
if is_admin and user_count == 1:
|
||||
delete_household(household_id)
|
||||
flash("Your account and household have been deleted.", "success")
|
||||
else:
|
||||
delete_user(session["user_id"])
|
||||
flash("Your account has been deleted.", "success")
|
||||
|
||||
# Clear auth keys but keep the session so flash survives the redirect
|
||||
for key in ("user_id", "username", "is_admin", "household_id", "household_name"):
|
||||
session.pop(key, None)
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
|
||||
@meals_bp.route("/admin/remove-user/<int:user_id>", methods=["POST"])
|
||||
@login_required
|
||||
def admin_remove_user(user_id):
|
||||
"""Admin removes a user from the household."""
|
||||
if not session["is_admin"]:
|
||||
flash("Only admins can remove users.", "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
user = get_user_by_id(user_id)
|
||||
if user is None or user["household_id"] != session["household_id"]:
|
||||
flash("User not found in your household.", "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
if user["is_admin"]:
|
||||
flash("Cannot remove the admin. Transfer admin role first or delete the household.", "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
delete_user(user_id)
|
||||
flash(f"User '{user['username']}' has been removed.", "success")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
|
||||
@meals_bp.route("/admin/delete-household", methods=["POST"])
|
||||
@login_required
|
||||
def admin_delete_household():
|
||||
"""Admin deletes the entire household."""
|
||||
if not session["is_admin"]:
|
||||
flash("Only admins can delete the household.", "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
password = request.form.get("password", "")
|
||||
user = get_user_by_id(session["user_id"])
|
||||
|
||||
if not check_password_hash(user["password_hash"], password):
|
||||
flash("Incorrect password. Household not deleted.", "error")
|
||||
return redirect(url_for("meals.dashboard"))
|
||||
|
||||
delete_household(session["household_id"])
|
||||
flash("Household and all members have been deleted.", "success")
|
||||
for key in ("user_id", "username", "is_admin", "household_id", "household_name"):
|
||||
session.pop(key, None)
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
Reference in New Issue
Block a user