from __future__ import annotations from typing import Any, Dict from django.conf import settings from django.core.signing import TimestampSigner, BadSignature, SignatureExpired, dumps, loads DEFAULT_TTL = int(getattr(settings, "SHARE_TTL_SECONDS", 7 * 24 * 3600)) def _base_url(request=None) -> str: if request: forwarded_proto = request.META.get("HTTP_X_FORWARDED_PROTO") scheme = (forwarded_proto.split(",")[0].strip() if forwarded_proto else None) or ( "https" if request.is_secure() else "http" ) host = request.get_host() or settings.BASE_URL.replace("https://", "").replace("http://", "") return f"{scheme}://{host}" return settings.BASE_URL def mint_sites_share_url(search_id: str, request=None, ttl: int | None = None) -> str: payload = {"k": "sites", "sid": search_id} token = dumps(payload) # signed + timestamped base = _base_url(request) return f"{base}/share/sites/{search_id}/{token}" def mint_sami_share_url(run_id: str, meta: Dict[str, Any], request=None, ttl: int | None = None) -> str: # meta can include: indicator, beta, r2, n payload = {"k": "sami", "rid": run_id, **{k: v for k, v in meta.items() if k in ("indicator","beta","r2","n")}} token = dumps(payload) base = _base_url(request) return f"{base}/share/sami/{run_id}/{token}" def verify_token(token: str, max_age: int | None = None) -> Dict[str, Any]: try: return loads(token, max_age=max_age or DEFAULT_TTL) except SignatureExpired as e: raise except BadSignature as e: raise