AdarshDRC commited on
Commit
318f9d2
·
verified ·
1 Parent(s): 607b376

Create api/danger.py

Browse files
Files changed (1) hide show
  1. src/api/danger.py +101 -0
src/api/danger.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import time
3
+
4
+ from fastapi import APIRouter, Form, HTTPException, Request, Depends
5
+
6
+ from src.core.config import DEFAULT_CLOUDINARY_URL, DEFAULT_PINECONE_KEY, IDX_FACES, IDX_OBJECTS
7
+ from src.core.security import get_verified_keys
8
+ from src.services.db_client import (
9
+ cld_delete_all_paginated, cld_remove_folder, cld_root_folders,
10
+ delete_and_recreate_indexes, pinecone_pool,
11
+ )
12
+ from src.core.logging import log, warn
13
+ from src.common.utils import get_ip, is_default_key
14
+
15
+ router = APIRouter()
16
+
17
+ @router.post("/api/reset-database")
18
+ async def reset_database(
19
+ request: Request,
20
+ user_id: str = Form(""),
21
+ keys: dict = Depends(get_verified_keys)
22
+ ):
23
+ ip = get_ip(request)
24
+ start = time.perf_counter()
25
+ log("WARNING", "danger.reset_database.attempt", user_id=user_id or "anonymous", ip=ip)
26
+
27
+ if is_default_key(keys["pinecone_key"], DEFAULT_PINECONE_KEY) or is_default_key(keys["cloudinary_url"], DEFAULT_CLOUDINARY_URL):
28
+ log("WARNING", "danger.reset_database.blocked", user_id=user_id or "anonymous", ip=ip)
29
+ raise HTTPException(403, "Reset is not allowed on the shared demo database.")
30
+
31
+ try:
32
+ deleted = await asyncio.to_thread(cld_delete_all_paginated, keys["cloudinary_creds"])
33
+ log("INFO", "danger.reset_database.cloudinary_wiped", deleted=deleted)
34
+ except Exception as e:
35
+ warn(f"Cloudinary wipe error: {e}")
36
+
37
+ try:
38
+ folders_res = await asyncio.to_thread(cld_root_folders, keys["cloudinary_creds"])
39
+ folder_tasks = [
40
+ asyncio.to_thread(cld_remove_folder, f["name"], keys["cloudinary_creds"])
41
+ for f in folders_res.get("folders", [])
42
+ ]
43
+ if folder_tasks:
44
+ await asyncio.gather(*folder_tasks, return_exceptions=True)
45
+ except Exception as e:
46
+ warn(f"Cloudinary folder cleanup error: {e}")
47
+
48
+ try:
49
+ pc = pinecone_pool.get(keys["pinecone_key"])
50
+ await asyncio.to_thread(delete_and_recreate_indexes, pc)
51
+ except Exception as e:
52
+ log("ERROR", "danger.reset_database.pinecone_error", user_id=user_id or "anonymous", ip=ip, error=str(e))
53
+ raise HTTPException(500, f"Pinecone reset error: {e}")
54
+
55
+ log("WARNING", "danger.reset_database.complete", user_id=user_id or "anonymous", ip=ip, duration_ms=round((time.perf_counter() - start) * 1000))
56
+ return {"message": "Database reset complete. All data wiped and indexes recreated."}
57
+
58
+ @router.post("/api/delete-account")
59
+ async def delete_account(
60
+ request: Request,
61
+ user_id: str = Form(""),
62
+ keys: dict = Depends(get_verified_keys)
63
+ ):
64
+ ip = get_ip(request)
65
+ start = time.perf_counter()
66
+ log("WARNING", "danger.delete_account.attempt", user_id=user_id or "anonymous", ip=ip)
67
+
68
+ if is_default_key(keys["pinecone_key"], DEFAULT_PINECONE_KEY) or is_default_key(keys["cloudinary_url"], DEFAULT_CLOUDINARY_URL):
69
+ log("WARNING", "danger.delete_account.blocked", user_id=user_id or "anonymous", ip=ip)
70
+ raise HTTPException(403, "Account deletion is not allowed on the shared demo database.")
71
+
72
+ try:
73
+ deleted = await asyncio.to_thread(cld_delete_all_paginated, keys["cloudinary_creds"])
74
+ log("INFO", "danger.delete_account.cloudinary_wiped", deleted=deleted)
75
+ except Exception as e:
76
+ warn(f"Account delete Cloudinary error: {e}")
77
+
78
+ try:
79
+ folders_res = await asyncio.to_thread(cld_root_folders, keys["cloudinary_creds"])
80
+ folder_tasks = [
81
+ asyncio.to_thread(cld_remove_folder, f["name"], keys["cloudinary_creds"])
82
+ for f in folders_res.get("folders", [])
83
+ ]
84
+ if folder_tasks:
85
+ await asyncio.gather(*folder_tasks, return_exceptions=True)
86
+ except Exception as e:
87
+ warn(f"Account delete folders error: {e}")
88
+
89
+ try:
90
+ pc = pinecone_pool.get(keys["pinecone_key"])
91
+ def _delete_indexes():
92
+ existing = {idx.name for idx in pc.list_indexes()}
93
+ for name in [IDX_OBJECTS, IDX_FACES]:
94
+ if name in existing:
95
+ pc.delete_index(name)
96
+ await asyncio.to_thread(_delete_indexes)
97
+ except Exception as e:
98
+ warn(f"Account delete Pinecone error: {e}")
99
+
100
+ log("WARNING", "danger.delete_account.complete", user_id=user_id or "anonymous", ip=ip, duration_ms=round((time.perf_counter() - start) * 1000))
101
+ return {"message": "Account data deleted. Sign out initiated."}