"""User routes — list, me, update, delete, timezone.""" from fastapi import APIRouter, HTTPException, Depends from database import db from auth.jwt_auth import current_user, require, _audit from models import UserUpdateReq router = APIRouter() # ── Users ───────────────────────────────────────────────────────────────────── @router.get("/api/users") async def list_users(u=Depends(require("admin"))): with db() as c: rows = c.execute("SELECT id,first_name,last_name,username,email,role,mfa_enabled,timezone,is_active,created_at,last_login,auth_provider FROM users").fetchall() return [dict(r) for r in rows] @router.get("/api/users/me") async def me(u=Depends(current_user)): fields = ("id","first_name","last_name","username","email","role","mfa_enabled","timezone","auth_provider","must_change_password") r = {k: u.get(k, "local" if k == "auth_provider" else None) for k in fields} r["must_change_password"] = bool(r.get("must_change_password", 0)) return r @router.put("/api/users/{uid}") async def update_user(uid: str, req: UserUpdateReq, adm=Depends(require("admin"))): sets, vals = [], [] if req.email is not None: sets.append("email=?"); vals.append(req.email) if req.role is not None: if req.role not in ("admin","user","viewer"): raise HTTPException(400, "Role inválida") sets.append("role=?"); vals.append(req.role) if req.is_active is not None: sets.append("is_active=?"); vals.append(int(req.is_active)) if req.timezone is not None: sets.append("timezone=?"); vals.append(req.timezone) if sets: vals.append(uid) with db() as c: c.execute(f"UPDATE users SET {','.join(sets)} WHERE id=?", vals) _audit(adm["id"], adm["username"], "update_user", uid) return {"ok": True} @router.delete("/api/users/{uid}") async def del_user(uid: str, adm=Depends(require("admin"))): if uid == adm["id"]: raise HTTPException(400, "Não pode desativar a si mesmo") with db() as c: c.execute("UPDATE users SET is_active=0 WHERE id=?", (uid,)) _audit(adm["id"], adm["username"], "deactivate_user", uid) return {"ok": True} @router.put("/api/users/me/timezone") async def set_user_timezone(body: dict, u=Depends(current_user)): """Set the current user's timezone.""" tz = body.get("timezone", "").strip() if not tz: raise HTTPException(400, "timezone is required") try: import zoneinfo zoneinfo.ZoneInfo(tz) except Exception: raise HTTPException(400, f"Invalid timezone: {tz}") with db() as c: c.execute("UPDATE users SET timezone=? WHERE id=?", (tz, u["id"])) _audit(u["id"], u["username"], "set_timezone", tz) return {"ok": True, "timezone": tz} @router.get("/api/users/me/timezone") async def get_user_timezone(u=Depends(current_user)): """Get the current user's timezone.""" return {"timezone": u.get("timezone", "America/Sao_Paulo")}