1use thiserror::Error;
6
7pub type SaTokenResult<T> = Result<T, SaTokenError>;
8
9#[derive(Debug, Error)]
10pub enum SaTokenError {
11 #[error("Token not found or expired")]
13 TokenNotFound,
14
15 #[error("Token is invalid: {0}")]
16 InvalidToken(String),
17
18 #[error("Token has expired")]
19 TokenExpired,
20
21 #[error("User not logged in")]
23 NotLogin,
24
25 #[error("Token is inactive")]
26 TokenInactive,
27
28 #[error("Permission denied")]
30 PermissionDenied,
31
32 #[error("Permission denied: missing permission '{0}'")]
33 PermissionDeniedDetail(String),
34
35 #[error("Role denied: missing role '{0}'")]
36 RoleDenied(String),
37
38 #[error("Account is banned until {0}")]
40 AccountBanned(String),
41
42 #[error("Account is kicked out")]
43 AccountKickedOut,
44
45 #[error("Session not found")]
47 SessionNotFound,
48
49 #[error("Nonce has been used, possible replay attack detected")]
51 NonceAlreadyUsed,
52
53 #[error("Invalid nonce format")]
54 InvalidNonceFormat,
55
56 #[error("Nonce timestamp is invalid or expired")]
57 InvalidNonceTimestamp,
58
59 #[error("Refresh token not found or expired")]
61 RefreshTokenNotFound,
62
63 #[error("Invalid refresh token data")]
64 RefreshTokenInvalidData,
65
66 #[error("Missing login_id in refresh token")]
67 RefreshTokenMissingLoginId,
68
69 #[error("Invalid expire time format in refresh token")]
70 RefreshTokenInvalidExpireTime,
71
72 #[error("Token is empty")]
74 TokenEmpty,
75
76 #[error("Token is too short")]
77 TokenTooShort,
78
79 #[error("Login ID is not a valid number")]
80 LoginIdNotNumber,
81
82 #[error("OAuth2 client not found")]
84 OAuth2ClientNotFound,
85
86 #[error("Invalid client credentials")]
87 OAuth2InvalidCredentials,
88
89 #[error("Client ID mismatch")]
90 OAuth2ClientIdMismatch,
91
92 #[error("Redirect URI mismatch")]
93 OAuth2RedirectUriMismatch,
94
95 #[error("Authorization code not found or expired")]
96 OAuth2CodeNotFound,
97
98 #[error("Access token not found or expired")]
99 OAuth2AccessTokenNotFound,
100
101 #[error("Refresh token not found or expired")]
102 OAuth2RefreshTokenNotFound,
103
104 #[error("Invalid refresh token data")]
105 OAuth2InvalidRefreshToken,
106
107 #[error("Invalid scope data")]
108 OAuth2InvalidScope,
109
110 #[error("SSO ticket not found or invalid")]
112 InvalidTicket,
113
114 #[error("SSO ticket has expired")]
115 TicketExpired,
116
117 #[error("Service URL mismatch")]
118 ServiceMismatch,
119
120 #[error("SSO session not found")]
121 SsoSessionNotFound,
122
123 #[error("Storage error: {0}")]
125 StorageError(String),
126
127 #[error("Configuration error: {0}")]
128 ConfigError(String),
129
130 #[error("Serialization error: {0}")]
131 SerializationError(#[from] serde_json::Error),
132
133 #[error("Internal error: {0}")]
134 InternalError(String),
135}
136
137impl SaTokenError {
138 pub fn message(&self) -> String {
150 self.to_string()
151 }
152
153 pub fn is_auth_error(&self) -> bool {
157 matches!(
158 self,
159 Self::NotLogin
160 | Self::TokenNotFound
161 | Self::TokenExpired
162 | Self::TokenInactive
163 | Self::InvalidToken(_)
164 )
165 }
166
167 pub fn is_authz_error(&self) -> bool {
171 matches!(
172 self,
173 Self::PermissionDenied
174 | Self::PermissionDeniedDetail(_)
175 | Self::RoleDenied(_)
176 )
177 }
178}
179
180pub mod messages {
194 pub const INVALID_CREDENTIALS: &str = "Invalid username or password";
196
197 pub const LOGIN_FAILED: &str = "Login failed";
199
200 pub const AUTH_ERROR: &str = "Authentication error";
202
203 pub const PERMISSION_REQUIRED: &str = "Permission required";
205
206 pub const ROLE_REQUIRED: &str = "Role required";
208}