""" Account Routes — self-service actions on the caller's own account. Unlike routes/admin.py, these never take a target uid from the request — the uid always comes from the verified Firebase ID token, so a user can only ever act on their own account. """ from fastapi import APIRouter, Depends, HTTPException from firebase_admin import auth as fb_auth, firestore from auth import verify_firebase_token router = APIRouter() def delete_all_user_data(uid: str) -> None: """ Deletes every Firestore document owned by a user: each business's subcollections, the business docs themselves, xpHistory, and the user_data root doc. Shared by this self-delete route and routes/admin.py's delete_user so the cascade is defined once. """ db = firestore.client() user_ref = db.collection("user_data").document(uid) for biz in user_ref.collection("businesses").stream(): for sub in ["bff", "profile_output", "documents", "kanban", "milestones", "sessions", "team"]: for sdoc in biz.reference.collection(sub).stream(): sdoc.reference.delete() biz.reference.delete() for entry in user_ref.collection("xpHistory").stream(): entry.reference.delete() user_ref.delete() # Data keyed to the uid outside user_data: rate-limit violation logs and any # consultant booking records. for entry in db.collection("rate_limit_violations").where("uid", "==", uid).stream(): entry.reference.delete() for booking in db.collection_group("bookings").where("userId", "==", uid).stream(): booking.reference.delete() @router.delete("/me") def delete_own_account(user: dict = Depends(verify_firebase_token)): """ Deletes the caller's own account: all Firestore data (via the Admin SDK, which bypasses firestore.rules — user_data deletion is deliberately backend-only, see firestore.rules' own comment) and the Firebase Auth user record. The frontend re-authenticates the user with their password immediately before calling this, as an extra confirmation step. """ uid = user.get("uid") if not uid: raise HTTPException(status_code=401, detail="Unauthorized.") delete_all_user_data(uid) try: fb_auth.delete_user(uid) except fb_auth.UserNotFoundError: pass # already gone — not an error for a delete return {"success": True}