PDF-accessibility-saas/backend/app/services/checker.py
Vadym Samoilenko fc6f4a12e6 Phase 2+3: FastAPI backend + multi-tenancy schema
Backend (replaces PHP api.php + auth.php):
- FastAPI app with routers: jobs, auth, billing
- Supabase JWT authentication in deps.py
- Celery + Redis job queue (process_pdf_task)
- MinIO S3-compatible storage service
- PDF checker wrapper (delegates to enterprise_pdf_checker.py)
- Stripe billing: checkout, portal, webhook handler

Multi-tenancy (Phase 3):
- Alembic migration 001: workspaces, workspace_members, jobs, usage_events
- Row-Level Security on all tenant tables via app.workspace_id session var
- Monthly quota enforcement per workspace (402 on exceeded)
- Plan tiers: free(5) / pro(100) / business(unlimited)

Config:
- pydantic-settings based config.py (no hardcoded values)
- docker-compose.yml rewritten: postgres, redis, minio, api, celery

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:46:05 +01:00

34 lines
1.1 KiB
Python

"""Wrapper around enterprise_pdf_checker.py — runs in Celery worker."""
import sys
import os
import tempfile
import structlog
from pathlib import Path
# enterprise_pdf_checker.py lives at repo root (parent of backend/)
REPO_ROOT = Path(__file__).parents[3]
if str(REPO_ROOT) not in sys.path:
sys.path.insert(0, str(REPO_ROOT))
from enterprise_pdf_checker import EnterprisePDFChecker # noqa: E402
logger = structlog.get_logger()
def run_check(pdf_bytes: bytes, filename: str) -> dict:
"""Run WCAG accessibility check on PDF bytes. Returns result dict."""
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp:
tmp.write(pdf_bytes)
tmp_path = tmp.name
try:
checker = EnterprisePDFChecker(tmp_path)
result = checker.check_all()
result["filename"] = filename
logger.info("check_complete", filename=filename, score=result.get("accessibility_score"))
return result
except Exception as exc:
logger.error("check_failed", filename=filename, error=str(exc))
raise
finally:
os.unlink(tmp_path)