1use axum::{
2 Json,
3 http::StatusCode,
4 response::{IntoResponse, Response},
5};
6use serde_json::json;
7use thiserror::Error;
8use torii::ToriiError;
9
10#[derive(Debug, Error)]
11pub enum AuthError {
12 #[error("Authentication failed: {0}")]
13 AuthenticationFailed(String),
14
15 #[error("Invalid credentials")]
16 InvalidCredentials,
17
18 #[error("User not found")]
19 UserNotFound,
20
21 #[error("Session not found")]
22 SessionNotFound,
23
24 #[error("Invalid session token")]
25 InvalidSession,
26
27 #[error("Email already registered")]
28 EmailAlreadyRegistered,
29
30 #[error("Invalid request: {0}")]
31 BadRequest(String),
32
33 #[error("Internal server error: {0}")]
34 InternalError(String),
35
36 #[error("Unauthorized")]
37 Unauthorized,
38
39 #[error("Feature not enabled: {0}")]
40 FeatureNotEnabled(String),
41}
42
43impl From<ToriiError> for AuthError {
44 fn from(err: ToriiError) -> Self {
45 match err {
46 ToriiError::AuthError(msg) => {
47 if msg.contains("already exists") || msg.contains("already registered") {
48 AuthError::EmailAlreadyRegistered
49 } else if msg.contains("Invalid") || msg.contains("incorrect") {
50 AuthError::InvalidCredentials
51 } else {
52 AuthError::AuthenticationFailed(msg)
53 }
54 }
55 ToriiError::StorageError(msg) => {
56 if msg.contains("not found") {
57 if msg.contains("User") {
58 AuthError::UserNotFound
59 } else if msg.contains("Session") {
60 AuthError::SessionNotFound
61 } else {
62 AuthError::InternalError(msg)
63 }
64 } else {
65 AuthError::InternalError(msg)
66 }
67 }
68 }
69 }
70}
71
72impl IntoResponse for AuthError {
73 fn into_response(self) -> Response {
74 let (status, error_message) = match self {
75 AuthError::AuthenticationFailed(ref msg) => (StatusCode::UNAUTHORIZED, msg.as_str()),
76 AuthError::InvalidCredentials => (StatusCode::UNAUTHORIZED, "Invalid credentials"),
77 AuthError::UserNotFound => (StatusCode::NOT_FOUND, "User not found"),
78 AuthError::SessionNotFound => (StatusCode::NOT_FOUND, "Session not found"),
79 AuthError::InvalidSession => (StatusCode::UNAUTHORIZED, "Invalid session"),
80 AuthError::EmailAlreadyRegistered => (StatusCode::CONFLICT, "Email already registered"),
81 AuthError::BadRequest(ref msg) => (StatusCode::BAD_REQUEST, msg.as_str()),
82 AuthError::InternalError(ref msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg.as_str()),
83 AuthError::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized"),
84 AuthError::FeatureNotEnabled(ref feature) => {
85 (StatusCode::NOT_IMPLEMENTED, feature.as_str())
86 }
87 };
88
89 let body = Json(json!({
90 "error": error_message,
91 "code": status.as_u16()
92 }));
93
94 (status, body).into_response()
95 }
96}
97
98pub type Result<T> = std::result::Result<T, AuthError>;