1use thiserror::Error;
2
3#[derive(Error, Debug)]
5pub enum AuthError {
6 #[error("Configuration error: {0}")]
7 Config(String),
8
9 #[error("Database error: {0}")]
10 Database(#[from] DatabaseError),
11
12 #[error("Serialization error: {0}")]
13 Serialization(#[from] serde_json::Error),
14
15 #[error("Invalid credentials")]
16 InvalidCredentials,
17
18 #[error("User not found")]
19 UserNotFound,
20
21 #[error("Session not found or expired")]
22 SessionNotFound,
23
24 #[error("Plugin error: {plugin} - {message}")]
25 Plugin { plugin: String, message: String },
26
27 #[error("Invalid request: {0}")]
28 InvalidRequest(String),
29
30 #[error("Internal server error: {0}")]
31 Internal(String),
32
33 #[error("Authentication required")]
34 Unauthenticated,
35
36 #[error("Insufficient permissions")]
37 Unauthorized,
38
39 #[error("Password hashing error: {0}")]
40 PasswordHash(String),
41
42 #[error("JWT error: {0}")]
43 Jwt(#[from] jsonwebtoken::errors::Error),
44}
45
46#[derive(Error, Debug)]
47pub enum DatabaseError {
48 #[error("Connection error: {0}")]
49 Connection(String),
50
51 #[error("Query error: {0}")]
52 Query(String),
53
54 #[error("Migration error: {0}")]
55 Migration(String),
56
57 #[error("Constraint violation: {0}")]
58 Constraint(String),
59
60 #[error("Transaction error: {0}")]
61 Transaction(String),
62}
63
64#[cfg(feature = "sqlx-postgres")]
65impl From<sqlx::Error> for DatabaseError {
66 fn from(err: sqlx::Error) -> Self {
67 match err {
68 sqlx::Error::Database(db_err) => {
69 if db_err.is_unique_violation() {
70 DatabaseError::Constraint(db_err.to_string())
71 } else {
72 DatabaseError::Query(db_err.to_string())
73 }
74 }
75 sqlx::Error::PoolClosed => DatabaseError::Connection("Pool closed".to_string()),
76 sqlx::Error::PoolTimedOut => DatabaseError::Connection("Pool timed out".to_string()),
77 _ => DatabaseError::Query(err.to_string()),
78 }
79 }
80}
81
82#[cfg(feature = "sqlx-postgres")]
83impl From<sqlx::Error> for AuthError {
84 fn from(err: sqlx::Error) -> Self {
85 AuthError::Database(DatabaseError::from(err))
86 }
87}
88
89pub type AuthResult<T> = Result<T, AuthError>;
90
91impl AuthError {
92 pub fn plugin(plugin: &str, message: impl Into<String>) -> Self {
93 Self::Plugin {
94 plugin: plugin.to_string(),
95 message: message.into(),
96 }
97 }
98
99 pub fn config(message: impl Into<String>) -> Self {
100 Self::Config(message.into())
101 }
102
103 pub fn internal(message: impl Into<String>) -> Self {
104 Self::Internal(message.into())
105 }
106}