""" Eccezioni applicative custom per PecFlow. """ from fastapi import HTTPException, status # ─── Autenticazione ─────────────────────────────────────────────────────────── class InvalidCredentialsError(HTTPException): def __init__(self) -> None: super().__init__( status_code=status.HTTP_401_UNAUTHORIZED, detail="Credenziali non valide", headers={"WWW-Authenticate": "Bearer"}, ) class TokenExpiredError(HTTPException): def __init__(self) -> None: super().__init__( status_code=status.HTTP_401_UNAUTHORIZED, detail="Token scaduto", headers={"WWW-Authenticate": "Bearer"}, ) class TokenInvalidError(HTTPException): def __init__(self) -> None: super().__init__( status_code=status.HTTP_401_UNAUTHORIZED, detail="Token non valido", headers={"WWW-Authenticate": "Bearer"}, ) class AccountLockedError(HTTPException): def __init__(self, locked_until: str = "") -> None: detail = "Account temporaneamente bloccato per troppi tentativi falliti" if locked_until: detail += f" fino a {locked_until}" super().__init__( status_code=status.HTTP_423_LOCKED, detail=detail, ) class AccountDisabledError(HTTPException): def __init__(self) -> None: super().__init__( status_code=status.HTTP_403_FORBIDDEN, detail="Account disabilitato", ) class TOTPRequiredError(HTTPException): def __init__(self) -> None: super().__init__( status_code=status.HTTP_403_FORBIDDEN, detail="Autenticazione a due fattori richiesta", ) class TOTPInvalidError(HTTPException): def __init__(self) -> None: super().__init__( status_code=status.HTTP_400_BAD_REQUEST, detail="Codice TOTP non valido o scaduto", ) # ─── Autorizzazione ─────────────────────────────────────────────────────────── class ForbiddenError(HTTPException): def __init__(self, detail: str = "Accesso non autorizzato") -> None: super().__init__( status_code=status.HTTP_403_FORBIDDEN, detail=detail, ) class PermissionDeniedError(HTTPException): def __init__(self, resource: str = "risorsa") -> None: super().__init__( status_code=status.HTTP_403_FORBIDDEN, detail=f"Permessi insufficienti per accedere a questa {resource}", ) # ─── Risorse ────────────────────────────────────────────────────────────────── class NotFoundError(HTTPException): def __init__(self, resource: str = "risorsa") -> None: super().__init__( status_code=status.HTTP_404_NOT_FOUND, detail=f"{resource.capitalize()} non trovata", ) class ConflictError(HTTPException): def __init__(self, detail: str = "Conflitto: risorsa già esistente") -> None: super().__init__( status_code=status.HTTP_409_CONFLICT, detail=detail, ) class TenantLimitExceededError(HTTPException): def __init__(self, resource: str, limit: int) -> None: super().__init__( status_code=status.HTTP_402_PAYMENT_REQUIRED, detail=f"Limite del piano raggiunto: massimo {limit} {resource} per questo tenant", ) # ─── Validazione ────────────────────────────────────────────────────────────── class ValidationError(HTTPException): def __init__(self, detail: str) -> None: super().__init__( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=detail, )