Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
# main.py
|
| 2 |
import asyncio
|
| 3 |
import os
|
| 4 |
import shutil
|
|
@@ -112,7 +111,13 @@ async def verify_keys(pinecone_key: str = Form(""), cloudinary_url: str = Form("
|
|
| 112 |
if tasks:
|
| 113 |
await asyncio.gather(*tasks)
|
| 114 |
except Exception as e:
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
return {"message": "Keys verified and indexes ready!"}
|
| 117 |
|
| 118 |
|
|
@@ -162,9 +167,16 @@ async def upload_new_images(files: List[UploadFile] = File(...), folder_name: st
|
|
| 162 |
if face_upserts: upsert_tasks.append(asyncio.to_thread(idx_face.upsert, vectors=face_upserts))
|
| 163 |
if object_upserts: upsert_tasks.append(asyncio.to_thread(idx_obj.upsert, vectors=object_upserts))
|
| 164 |
if upsert_tasks: await asyncio.gather(*upsert_tasks)
|
|
|
|
|
|
|
| 165 |
except Exception as e:
|
| 166 |
-
|
| 167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
finally:
|
| 169 |
if os.path.exists(tmp_path): os.remove(tmp_path)
|
| 170 |
|
|
@@ -465,13 +477,33 @@ async def reset_database(
|
|
| 465 |
if not creds.get("cloud_name"):
|
| 466 |
raise HTTPException(400, "Invalid Cloudinary URL.")
|
| 467 |
|
| 468 |
-
# Wipe all Cloudinary resources
|
| 469 |
try:
|
| 470 |
await asyncio.to_thread(
|
| 471 |
lambda: cloudinary.api.delete_all_resources(
|
| 472 |
api_key=creds["api_key"], api_secret=creds["api_secret"], cloud_name=creds["cloud_name"],
|
| 473 |
)
|
| 474 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 475 |
except Exception as e:
|
| 476 |
print(f"Cloudinary wipe warning: {e}")
|
| 477 |
|
|
@@ -509,7 +541,7 @@ async def delete_account(
|
|
| 509 |
if _is_default_key(user_pinecone_key, DEFAULT_PC_KEY) or _is_default_key(user_cloudinary_url, DEFAULT_CLD_URL):
|
| 510 |
raise HTTPException(403, "Account deletion is not allowed on the shared demo database.")
|
| 511 |
|
| 512 |
-
# Full wipe
|
| 513 |
creds = get_cloudinary_creds(user_cloudinary_url)
|
| 514 |
try:
|
| 515 |
await asyncio.to_thread(
|
|
@@ -517,6 +549,25 @@ async def delete_account(
|
|
| 517 |
api_key=creds["api_key"], api_secret=creds["api_secret"], cloud_name=creds["cloud_name"],
|
| 518 |
)
|
| 519 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 520 |
except Exception as e:
|
| 521 |
print(f"Account delete Cloudinary warning: {e}")
|
| 522 |
|
|
|
|
|
|
|
| 1 |
import asyncio
|
| 2 |
import os
|
| 3 |
import shutil
|
|
|
|
| 111 |
if tasks:
|
| 112 |
await asyncio.gather(*tasks)
|
| 113 |
except Exception as e:
|
| 114 |
+
err_str = str(e).lower()
|
| 115 |
+
if "401" in err_str or "unauthorized" in err_str or "invalid api key" in err_str:
|
| 116 |
+
raise HTTPException(400, "Invalid Pinecone API Key. Please check your key and try again.")
|
| 117 |
+
elif "403" in err_str or "forbidden" in err_str:
|
| 118 |
+
raise HTTPException(400, "Pinecone API Key does not have sufficient permissions.")
|
| 119 |
+
else:
|
| 120 |
+
raise HTTPException(400, f"Pinecone connection failed. Please check your API key.")
|
| 121 |
return {"message": "Keys verified and indexes ready!"}
|
| 122 |
|
| 123 |
|
|
|
|
| 167 |
if face_upserts: upsert_tasks.append(asyncio.to_thread(idx_face.upsert, vectors=face_upserts))
|
| 168 |
if object_upserts: upsert_tasks.append(asyncio.to_thread(idx_obj.upsert, vectors=object_upserts))
|
| 169 |
if upsert_tasks: await asyncio.gather(*upsert_tasks)
|
| 170 |
+
except HTTPException:
|
| 171 |
+
raise
|
| 172 |
except Exception as e:
|
| 173 |
+
err_str = str(e)
|
| 174 |
+
print(f"❌ Upload error: {err_str}")
|
| 175 |
+
if "not found" in err_str.lower() or "404" in err_str or "does not exist" in err_str.lower():
|
| 176 |
+
raise HTTPException(404, "Pinecone index not found. Please go to Settings and click 'Verify & Save' to recreate your indexes.")
|
| 177 |
+
elif "401" in err_str or "unauthorized" in err_str.lower():
|
| 178 |
+
raise HTTPException(401, "Invalid Pinecone API Key. Please check your key in Settings.")
|
| 179 |
+
raise HTTPException(500, f"Upload processing failed: {err_str}")
|
| 180 |
finally:
|
| 181 |
if os.path.exists(tmp_path): os.remove(tmp_path)
|
| 182 |
|
|
|
|
| 477 |
if not creds.get("cloud_name"):
|
| 478 |
raise HTTPException(400, "Invalid Cloudinary URL.")
|
| 479 |
|
| 480 |
+
# FIX #8: Wipe all Cloudinary resources AND delete folder objects
|
| 481 |
try:
|
| 482 |
await asyncio.to_thread(
|
| 483 |
lambda: cloudinary.api.delete_all_resources(
|
| 484 |
api_key=creds["api_key"], api_secret=creds["api_secret"], cloud_name=creds["cloud_name"],
|
| 485 |
)
|
| 486 |
)
|
| 487 |
+
# Now delete the folder objects themselves
|
| 488 |
+
try:
|
| 489 |
+
folders_resp = await asyncio.to_thread(
|
| 490 |
+
lambda: cloudinary.api.root_folders(
|
| 491 |
+
api_key=creds["api_key"], api_secret=creds["api_secret"], cloud_name=creds["cloud_name"]
|
| 492 |
+
)
|
| 493 |
+
)
|
| 494 |
+
folder_names = [f["path"] for f in folders_resp.get("folders", [])]
|
| 495 |
+
for folder_path in folder_names:
|
| 496 |
+
try:
|
| 497 |
+
await asyncio.to_thread(
|
| 498 |
+
lambda fp=folder_path: cloudinary.api.delete_folder(
|
| 499 |
+
fp,
|
| 500 |
+
api_key=creds["api_key"], api_secret=creds["api_secret"], cloud_name=creds["cloud_name"]
|
| 501 |
+
)
|
| 502 |
+
)
|
| 503 |
+
except Exception as fe:
|
| 504 |
+
print(f"Folder delete warning ({folder_path}): {fe}")
|
| 505 |
+
except Exception as fe:
|
| 506 |
+
print(f"Cloudinary folder list warning: {fe}")
|
| 507 |
except Exception as e:
|
| 508 |
print(f"Cloudinary wipe warning: {e}")
|
| 509 |
|
|
|
|
| 541 |
if _is_default_key(user_pinecone_key, DEFAULT_PC_KEY) or _is_default_key(user_cloudinary_url, DEFAULT_CLD_URL):
|
| 542 |
raise HTTPException(403, "Account deletion is not allowed on the shared demo database.")
|
| 543 |
|
| 544 |
+
# FIX #4: Full wipe — resources AND folder objects from Cloudinary
|
| 545 |
creds = get_cloudinary_creds(user_cloudinary_url)
|
| 546 |
try:
|
| 547 |
await asyncio.to_thread(
|
|
|
|
| 549 |
api_key=creds["api_key"], api_secret=creds["api_secret"], cloud_name=creds["cloud_name"],
|
| 550 |
)
|
| 551 |
)
|
| 552 |
+
# Delete folder objects
|
| 553 |
+
try:
|
| 554 |
+
folders_resp = await asyncio.to_thread(
|
| 555 |
+
lambda: cloudinary.api.root_folders(
|
| 556 |
+
api_key=creds["api_key"], api_secret=creds["api_secret"], cloud_name=creds["cloud_name"]
|
| 557 |
+
)
|
| 558 |
+
)
|
| 559 |
+
for f in folders_resp.get("folders", []):
|
| 560 |
+
try:
|
| 561 |
+
await asyncio.to_thread(
|
| 562 |
+
lambda fp=f["path"]: cloudinary.api.delete_folder(
|
| 563 |
+
fp,
|
| 564 |
+
api_key=creds["api_key"], api_secret=creds["api_secret"], cloud_name=creds["cloud_name"]
|
| 565 |
+
)
|
| 566 |
+
)
|
| 567 |
+
except Exception as fe:
|
| 568 |
+
print(f"Folder delete warning: {fe}")
|
| 569 |
+
except Exception as fe:
|
| 570 |
+
print(f"Cloudinary folder list warning: {fe}")
|
| 571 |
except Exception as e:
|
| 572 |
print(f"Account delete Cloudinary warning: {e}")
|
| 573 |
|