"""Erreurs metier du domaine partage. Elles sont converties en reponses HTTP propres par les handlers de `app.main` : aucune trace technique n'est exposee au client. """ from __future__ import annotations class ShareError(Exception): """Erreur metier generique.""" status_code = 400 message = "Requete invalide." def __init__(self, message: str | None = None) -> None: super().__init__(message or self.message) if message: self.message = message # En-tetes additionnels de la reponse (Retry-After, par exemple). self.headers: dict[str, str] = {} class ShareNotFoundError(ShareError): status_code = 404 message = "Ce partage n'existe pas ou a ete supprime." class ShareForbiddenError(ShareError): status_code = 403 message = "Jeton de gestion invalide." class SharePayloadTooLargeError(ShareError): status_code = 413 message = "La carte depasse la taille maximale autorisee." class ShareExpiredError(ShareError): """Le partage a existe mais sa date d'expiration est passee. Statut distinct du 404 : c'est ce qui permet a la page publique d'afficher "Ce partage a expire" plutot qu'un message d'absence. Rien d'autre n'est revele : ni le titre, ni le contenu, ni la date de creation. """ status_code = 410 message = "Ce partage a expire." class SharingDisabledError(ShareError): status_code = 503 message = "Le partage est desactive sur cette instance." class ShareCapacityError(ShareError): status_code = 503 message = "Cette instance a atteint sa capacite maximale de partages." class PermanentShareNotAllowedError(ShareError): status_code = 400 message = "Cette instance n'autorise pas les partages sans expiration." class RateLimitedError(ShareError): status_code = 429 message = "Trop de requetes. Reessayez dans un instant." def __init__(self, retry_after: int, message: str | None = None) -> None: super().__init__(message) self.retry_after = retry_after self.headers["Retry-After"] = str(retry_after)