Sharma7's picture
Rebrand to PolicyEye, add CONTRIBUTING.md, deployment prep for HF Spaces + Vercel
2289c6d
Raw
History Blame Contribute Delete
3.81 kB
"""
Supabase Storage utility for PolicyEye.
Handles uploading and downloading policy PDFs to/from Supabase Storage.
This replaces local disk storage with cloud-hosted, CDN-served file storage.
Bucket: policy-pdfs (public, created via Supabase dashboard)
Bucket: grievance-reports (private, for generated PDF reports)
"""
import os
import logging
import uuid
from datetime import datetime
logger = logging.getLogger(__name__)
SUPABASE_URL = os.getenv("SUPABASE_URL", "")
SUPABASE_KEY = os.getenv("SUPABASE_KEY", "")
BUCKET_NAME = "policy-pdfs"
def _get_client():
"""Lazy-init Supabase client."""
from supabase import create_client
if not SUPABASE_URL or not SUPABASE_KEY:
raise RuntimeError(
"SUPABASE_URL and SUPABASE_KEY must be set in .env"
)
return create_client(SUPABASE_URL, SUPABASE_KEY)
def upload_pdf(pdf_bytes: bytes, original_filename: str, bucket_name: str = BUCKET_NAME) -> dict:
"""
Upload a PDF to Supabase Storage.
Args:
pdf_bytes: Raw PDF content
original_filename: Original name of the uploaded file
bucket_name: Supabase bucket name (default: policy-pdfs)
Returns:
{
"storage_path": str, # Path within the bucket
"public_url": str, # CDN-served public URL
"size_kb": float,
}
"""
client = _get_client()
# Generate a unique filename to avoid collisions
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
safe_name = original_filename.replace(" ", "_").lower()
storage_path = f"{timestamp}_{uuid.uuid4().hex[:8]}_{safe_name}"
# Upload to Supabase Storage
client.storage.from_(bucket_name).upload(
path=storage_path,
file=pdf_bytes,
file_options={"content-type": "application/pdf"},
)
# Get public URL
public_url = client.storage.from_(bucket_name).get_public_url(storage_path)
size_kb = len(pdf_bytes) / 1024
logger.info(
f"[Storage] Uploaded {safe_name} to Supabase "
f"({size_kb:.1f}KB) → {storage_path}"
)
return {
"storage_path": storage_path,
"public_url": public_url,
"size_kb": round(size_kb, 1),
}
def download_pdf(storage_path: str, bucket_name: str = BUCKET_NAME) -> bytes:
"""
Download a PDF from Supabase Storage.
Args:
storage_path: Path within the bucket (from upload_pdf return value)
bucket_name: Supabase bucket name
Returns:
Raw PDF bytes
"""
client = _get_client()
data = client.storage.from_(bucket_name).download(storage_path)
logger.info(f"[Storage] Downloaded {storage_path} from {bucket_name} ({len(data)/1024:.1f}KB)")
return data
def delete_pdf(storage_path: str, bucket_name: str = BUCKET_NAME) -> bool:
"""Delete a PDF from Supabase Storage."""
try:
client = _get_client()
client.storage.from_(bucket_name).remove([storage_path])
logger.info(f"[Storage] Deleted {storage_path} from {bucket_name}")
return True
except Exception as e:
logger.error(f"[Storage] Delete failed for {storage_path} in {bucket_name}: {e}")
return False
def upload_report(local_filepath: str) -> dict:
"""
Upload a generated report PDF from local disk to Supabase.
Args:
local_filepath: Path to the local PDF file
Returns:
dict with storage_path and public_url (same format as upload_pdf)
"""
if not os.path.exists(local_filepath):
raise FileNotFoundError(f"Report not found: {local_filepath}")
filename = os.path.basename(local_filepath)
with open(local_filepath, "rb") as f:
pdf_bytes = f.read()
return upload_pdf(pdf_bytes, filename, bucket_name="grievance-reports")