Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Add edge cases Tests for error module #631

Merged
merged 7 commits into from
Jun 30, 2024
Prev Previous commit
Next Next commit
♻️ Refactor error handling and exception messages
  • Loading branch information
yezz123 committed Jun 30, 2024
commit 668398c25c0378a6cefe4b13adb053753ffb4496
64 changes: 36 additions & 28 deletions authx/_internal/_error.py
Original file line number Diff line number Diff line change
@@ -9,25 +9,24 @@
class _ErrorHandler:
"""Base Handler for FastAPI handling AuthX exceptions"""

MSG_DEFAULT = "AuthX Error"
MSG_TOKEN_ERROR = "Token Error"
MSG_MISSING_TOKEN_ERROR = "Missing JWT in request"
MSG_MISSING_CSRF_ERROR = "Missing CSRF double submit token in request"
MSG_TOKEN_TYPE_ERROR = "Bad token type"
MSG_REVOKED_TOKEN_ERROR = "Invalid token"
MSG_TOKEN_REQUIRED_ERROR = "Token required"
MSG_FRESH_TOKEN_REQUIRED_ERROR = "Fresh token required"
MSG_ACCESS_TOKEN_REQUIRED_ERROR = "Access token required"
MSG_REFRESH_TOKEN_REQUIRED_ERROR = "Refresh token required"
MSG_CSRF_ERROR = "CSRF double submit does not match"
MSG_DECODE_JWT_ERROR = "Invalid Token"
MSG_TokenError = "Token Error"
MSG_MissingTokenError = "Missing JWT in request"
MSG_MissingCSRFTokenError = "Missing CSRF double submit token in request"
MSG_TokenTypeError = "Bad token type"
MSG_RevokedTokenError = "Invalid token"
MSG_TokenRequiredError = "Token required"
MSG_FreshTokenRequiredError = "Fresh token required"
MSG_AccessTokenRequiredError = "Access token required"
MSG_RefreshTokenRequiredError = "Refresh token required"
MSG_CSRFError = "CSRF double submit does not match"
MSG_JWTDecodeError = "Invalid Token"

async def _error_handler(
self,
request: Request,
exc: exceptions.AuthXException,
status_code: int,
message: str,
message: Optional[str],
) -> JSONResponse:
"""Generate the async function to be decorated by `FastAPI.exception_handler` decorator

@@ -40,10 +39,15 @@ async def _error_handler(
Returns:
JSONResponse: The JSON response.
"""
if message is None:
default_message = str(exc)
attr_name = f"MSG_{exc.__class__.__name__}"
message = getattr(self, attr_name, default_message)

return JSONResponse(
status_code=status_code,
content={
"message": message or str(exc),
"message": message,
"error_type": exc.__class__.__name__,
},
)
@@ -55,11 +59,15 @@ def _set_app_exception_handler(
status_code: int,
message: Optional[str],
) -> None:
app.exception_handler(exception)(
lambda request, exc=exception: self._error_handler(
request, exc, status_code, message or self.MSG_DEFAULT
)
)
async def exception_handler_wrapper(
request: Request, exc: exceptions.AuthXException
):
return await self._error_handler(request, exc, status_code, message)

# Add the exception handler to the FastAPI application
# The exception handler will be called when the specified exception is raised, and the status code and message will be returned
# The exception handler will return a JSONResponse with the specified status code and message
app.exception_handler(exception)(exception_handler_wrapper)

def handle_errors(self, app: FastAPI) -> None:
"""Add the `FastAPI.exception_handlers` relative to AuthX exceptions
@@ -74,53 +82,53 @@ def handle_errors(self, app: FastAPI) -> None:
app,
exception=exceptions.MissingTokenError,
status_code=401,
message=self.MSG_MISSING_TOKEN_ERROR,
message=self.MSG_TokenError,
)
self._set_app_exception_handler(
app,
exception=exceptions.MissingCSRFTokenError,
status_code=401,
message=self.MSG_MISSING_CSRF_ERROR,
message=self.MSG_MissingCSRFTokenError,
)
self._set_app_exception_handler(
app,
exception=exceptions.TokenTypeError,
status_code=401,
message=self.MSG_TOKEN_TYPE_ERROR,
message=self.MSG_TokenTypeError,
)
self._set_app_exception_handler(
app,
exception=exceptions.RevokedTokenError,
status_code=401,
message=self.MSG_REVOKED_TOKEN_ERROR,
message=self.MSG_RevokedTokenError,
)
self._set_app_exception_handler(
app,
exception=exceptions.TokenRequiredError,
status_code=401,
message=self.MSG_TOKEN_REQUIRED_ERROR,
message=self.MSG_TokenRequiredError,
)
self._set_app_exception_handler(
app,
exception=exceptions.FreshTokenRequiredError,
status_code=401,
message=self.MSG_FRESH_TOKEN_REQUIRED_ERROR,
message=self.MSG_FreshTokenRequiredError,
)
self._set_app_exception_handler(
app,
exception=exceptions.AccessTokenRequiredError,
status_code=401,
message=self.MSG_ACCESS_TOKEN_REQUIRED_ERROR,
message=self.MSG_AccessTokenRequiredError,
)
self._set_app_exception_handler(
app,
exception=exceptions.RefreshTokenRequiredError,
status_code=401,
message=self.MSG_REFRESH_TOKEN_REQUIRED_ERROR,
message=self.MSG_RefreshTokenRequiredError,
)
self._set_app_exception_handler(
app,
exception=exceptions.CSRFError,
status_code=401,
message=self.MSG_CSRF_ERROR,
message=self.MSG_CSRFError,
)