123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- # (c) Nelen & Schuurmans
- import logging
- from typing import List
- from typing import Optional
- from typing import Union
- from fastapi.encoders import jsonable_encoder
- from fastapi.requests import Request
- from fastapi.responses import JSONResponse
- from starlette import status
- from clean_python import BadRequest
- from clean_python import Conflict
- from clean_python import DoesNotExist
- from clean_python import PermissionDenied
- from clean_python import Unauthorized
- from clean_python import ValueObject
- logger = logging.getLogger(__name__)
- __all__ = [
- "ValidationErrorResponse",
- "DefaultErrorResponse",
- "not_found_handler",
- "conflict_handler",
- "validation_error_handler",
- "permission_denied_handler",
- "unauthorized_handler",
- ]
- class ValidationErrorEntry(ValueObject):
- loc: List[Union[str, int]]
- msg: str
- type: str
- class ValidationErrorResponse(ValueObject):
- message: str
- detail: List[ValidationErrorEntry]
- class DefaultErrorResponse(ValueObject):
- message: str
- detail: Optional[str]
- async def not_found_handler(request: Request, exc: DoesNotExist) -> JSONResponse:
- return JSONResponse(
- status_code=status.HTTP_404_NOT_FOUND,
- content={
- "message": f"Could not find {exc.name}{' with id=' + str(exc.id) if exc.id else ''}"
- },
- )
- async def conflict_handler(request: Request, exc: Conflict) -> JSONResponse:
- return JSONResponse(
- status_code=status.HTTP_409_CONFLICT,
- content={
- "message": "Conflict",
- "detail": jsonable_encoder(exc.args[0] if exc.args else None),
- },
- )
- async def validation_error_handler(request: Request, exc: BadRequest) -> JSONResponse:
- return JSONResponse(
- status_code=status.HTTP_400_BAD_REQUEST,
- content=ValidationErrorResponse(
- message="Validation error", detail=exc.errors() # type: ignore
- ).model_dump(mode="json"),
- )
- async def unauthorized_handler(request: Request, exc: Unauthorized) -> JSONResponse:
- if exc.args:
- logger.info(f"unauthorized: {exc}")
- return JSONResponse(
- status_code=status.HTTP_401_UNAUTHORIZED,
- content={"message": "Unauthorized", "detail": None},
- headers={"WWW-Authenticate": "Bearer"},
- )
- async def permission_denied_handler(
- request: Request, exc: PermissionDenied
- ) -> JSONResponse:
- return JSONResponse(
- status_code=status.HTTP_403_FORBIDDEN,
- content={
- "message": "Permission denied",
- "detail": jsonable_encoder(exc.args[0] if exc.args else None),
- },
- )
|