"""Auth routes: login, current user, first-time admin setup. No self-registration.""" from __future__ import annotations from flask import Blueprint, jsonify, request from ..auth.users import AuthError from .helpers import ApiError, current_user, require_auth auth_bp = Blueprint("auth", __name__) def _store(): from flask import current_app return current_app.extensions["user_store"] def _login_body(data: dict) -> str: # Accept `username` (primary) or `email` (fallback), lower-cased. return (data.get("username") or data.get("email") or "").strip().lower() @auth_bp.post("/login") def login(): data = request.get_json(silent=True) or {} username = _login_body(data) password = data.get("password") or "" if not username or not password: raise ApiError("username and password are required") try: user = _store().verify(username, password) token = _store().issue_token(user) except AuthError as exc: raise ApiError(str(exc), 401) return jsonify({ "token": token, "user": _store().public_user(user), "must_setup": bool(user.get("must_setup")), }) @auth_bp.get("/me") @require_auth def me(): return jsonify({"user": _store().public_user(current_user())}) @auth_bp.post("/setup") @require_auth def setup(): """First-time admin setup: set email + change password, then clear must_setup.""" user = current_user() data = request.get_json(silent=True) or {} username = (data.get("username") or user.get("username") or user.get("id") or "").strip().lower() email = (data.get("email") or "").strip() new_password = data.get("password") or "" if not email or not new_password: raise ApiError("email and new password are required") try: updated = _store().complete_setup(username, email, new_password) except AuthError as exc: raise ApiError(str(exc), 400) return jsonify({ "ok": True, "user": _store().public_user(updated), "must_setup": False, }) @auth_bp.patch("/profile") @require_auth def profile(): """Self-service profile update: name (and optional email). Any authenticated user.""" user = current_user() data = request.get_json(silent=True) or {} username = user.get("username") or user.get("id") try: if "name" in data: _store().set_name(username, data.get("name")) if "email" in data: _store().set_email(username, data.get("email")) except AuthError as exc: raise ApiError(str(exc), 400) return jsonify({"user": _store().public_user(_store().get_user(username))})