File size: 5,149 Bytes
34a66f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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