1use axum::{
2 http::StatusCode,
3 response::{IntoResponse, Json, Response},
4};
5use serde_json::json;
6
7use authx_core::error::AuthError;
8
9pub struct AuthErrorResponse(pub AuthError);
12
13impl From<AuthError> for AuthErrorResponse {
14 fn from(e: AuthError) -> Self {
15 Self(e)
16 }
17}
18
19impl IntoResponse for AuthErrorResponse {
20 fn into_response(self) -> Response {
21 let err = &self.0;
22 let (status, code) = match err {
23 AuthError::InvalidCredentials => (StatusCode::UNAUTHORIZED, "invalid_credentials"),
24 AuthError::UserNotFound => (StatusCode::NOT_FOUND, "user_not_found"),
25 AuthError::SessionNotFound => (StatusCode::UNAUTHORIZED, "session_not_found"),
26 AuthError::EmailTaken => (StatusCode::CONFLICT, "email_taken"),
27 AuthError::EmailNotVerified => (StatusCode::FORBIDDEN, "email_not_verified"),
28 AuthError::InvalidToken => (StatusCode::UNAUTHORIZED, "invalid_token"),
29 AuthError::AccountLocked => (StatusCode::TOO_MANY_REQUESTS, "account_locked"),
30 AuthError::WeakPassword => (StatusCode::UNPROCESSABLE_ENTITY, "weak_password"),
31 AuthError::Forbidden(_) => (StatusCode::FORBIDDEN, "forbidden"),
32 AuthError::HashError(_)
33 | AuthError::EncryptionError(_)
34 | AuthError::Internal(_)
35 | AuthError::Storage(_) => (StatusCode::INTERNAL_SERVER_ERROR, "internal_error"),
36 };
37
38 tracing::warn!(status = status.as_u16(), error = code, detail = %err);
39 (
40 status,
41 Json(json!({ "error": code, "message": err.to_string() })),
42 )
43 .into_response()
44 }
45}