system-prompts-and-models-o.../salesflow-saas/backend/app/middleware/internal_api.py
2026-04-04 18:04:21 +03:00

65 lines
2.2 KiB
Python

"""Optional bearer token for /api/v1 when DEALIX_INTERNAL_API_TOKEN is set (production hardening)."""
from __future__ import annotations
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import JSONResponse
from app.config import get_settings
def _exempt_path(path: str) -> bool:
if path in ("/api/v1/health", "/api/v1/ready"):
return True
if path.startswith("/api/v1/webhooks"):
return True
if path.startswith("/api/v1/marketing"):
return True
if path.startswith("/api/v1/strategy"):
return True
if path.startswith("/api/v1/value-proposition"):
return True
if path.startswith("/api/v1/customer-onboarding"):
return True
# Public demo GETs only; /sales-os/quota, /tasks-inbox, PUT /quota require token when set
if path in (
"/api/v1/sales-os/commission-ledger",
"/api/v1/sales-os/rep-onboarding",
"/api/v1/sales-os/overview",
"/api/v1/operations/snapshot",
):
return True
# مسارات المسوقين العامة (تسجيل، لوحة، برنامج) دون كشف بيانات فردية حساسة
if path == "/api/v1/affiliates/program" or path == "/api/v1/affiliates/register":
return True
if path.startswith("/api/v1/affiliates/leaderboard"):
return True
return False
class InternalApiTokenMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
if request.method == "OPTIONS":
return await call_next(request)
settings = get_settings()
token = (settings.DEALIX_INTERNAL_API_TOKEN or "").strip()
if not token:
return await call_next(request)
path = request.url.path
if not path.startswith("/api/v1"):
return await call_next(request)
if _exempt_path(path):
return await call_next(request)
auth = request.headers.get("authorization") or ""
expected = f"Bearer {token}"
if auth != expected:
return JSONResponse(
status_code=401,
content={"detail": "Invalid or missing Authorization bearer token"},
)
return await call_next(request)