from typing import Any, Dict, List, Optional from fastapi import APIRouter, Header, HTTPException import requests from app.core.config import ( SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, SUPABASE_TIMEOUT_SECONDS, PROFILE_SELECT_FIELDS, CORE_TABLES, supabase_configured, is_staff_role, LOGGER, ) from app.security.auth import require_authenticated_user, require_developer_user, _supabase_headers, _normalize_spaces router = APIRouter(tags=["admin"]) def _run_weekly_refresh_non_core() -> Dict[str, Any]: core_set = {t.lower() for t in CORE_TABLES} try: table_response = requests.get( f"{SUPABASE_URL}/rest/v1/rpc/", timeout=SUPABASE_TIMEOUT_SECONDS, ) except requests.RequestException: table_response = requests.get( f"{SUPABASE_URL}/rest/v1/", headers=_supabase_headers(api_key=SUPABASE_SERVICE_ROLE_KEY, bearer=SUPABASE_SERVICE_ROLE_KEY), timeout=SUPABASE_TIMEOUT_SECONDS, ) deleted: List[str] = [] skipped: List[str] = [] try: response = requests.get( f"{SUPABASE_URL}/rest/v1/", headers=_supabase_headers(api_key=SUPABASE_SERVICE_ROLE_KEY, bearer=SUPABASE_SERVICE_ROLE_KEY), timeout=SUPABASE_TIMEOUT_SECONDS, ) if response.status_code == 200: tables_data = response.json() if isinstance(tables_data, dict): all_tables = [k for k in tables_data.keys() if not k.startswith("_")] elif isinstance(tables_data, list): all_tables = [t for t in tables_data if isinstance(t, str) and not t.startswith("_")] else: all_tables = [] for table_name in all_tables: table_lower = table_name.lower() if table_lower in core_set: skipped.append(table_name) continue try: del_response = requests.delete( f"{SUPABASE_URL}/rest/v1/{table_name}", params={"select": "id"}, headers=_supabase_headers(api_key=SUPABASE_SERVICE_ROLE_KEY, bearer=SUPABASE_SERVICE_ROLE_KEY), timeout=SUPABASE_TIMEOUT_SECONDS, ) if del_response.status_code in {200, 204}: deleted.append(table_name) else: skipped.append(table_name) except requests.RequestException: skipped.append(table_name) except Exception as exc: LOGGER.warning("Weekly refresh encountered an error: %s", exc) return {"deleted_tables": deleted, "skipped_tables": skipped, "core_tables_protected": sorted(CORE_TABLES)} @router.get("/users") def get_all_users( authorization: Optional[str] = Header(default=None), ) -> Dict[str, Any]: if not supabase_configured(): raise HTTPException(status_code=503, detail="Supabase is not configured.") request_user = require_authenticated_user(authorization) if request_user is None: raise HTTPException(status_code=401, detail="Authentication is required.") requester_role = (request_user.get("role") or "").strip().lower() if not is_staff_role(requester_role): raise HTTPException(status_code=403, detail="Admin/Security role required to view users.") try: response = requests.get( f"{SUPABASE_URL}/rest/v1/profiles", params={"select": PROFILE_SELECT_FIELDS}, headers=_supabase_headers(api_key=SUPABASE_SERVICE_ROLE_KEY, bearer=SUPABASE_SERVICE_ROLE_KEY), timeout=SUPABASE_TIMEOUT_SECONDS, ) if response.status_code != 200: raise HTTPException(status_code=502, detail="Failed to fetch users from database.") users = response.json() if isinstance(users, dict) and "error" in users: users = [] return {"status": "ok", "users": users} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post("/admin/maintenance/weekly-refresh") def admin_weekly_refresh( authorization: Optional[str] = Header(default=None), ) -> Dict[str, Any]: request_user = require_authenticated_user(authorization) if request_user is None: raise HTTPException(status_code=401, detail="Authentication is required.") requester_id = str(request_user.get("id") or "").strip() requester_role = (request_user.get("role") or "").strip().lower() if not is_staff_role(requester_role): raise HTTPException(status_code=403, detail="Only admin/security can run weekly refresh.") try: refresh_result = _run_weekly_refresh_non_core() return { "status": "ok", "requested_by": requester_id, "requested_by_role": requester_role, "core_tables_protected": sorted(CORE_TABLES), "refresh": refresh_result, } except Exception as exc: raise HTTPException(status_code=502, detail=f"Weekly refresh failed: {exc}") from exc