Skip to main content

sa_token_core/
error.rs

1// Author: 金书记
2//
3//! Error type definitions | 错误类型定义
4
5use thiserror::Error;
6
7pub type SaTokenResult<T> = Result<T, SaTokenError>;
8
9#[derive(Debug, Error)]
10pub enum SaTokenError {
11    // ============ Basic Token Errors | 基础 Token 错误 ============
12    #[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    // ============ Authentication Errors | 认证错误 ============
22    #[error("User not logged in")]
23    NotLogin,
24    
25    #[error("Token is inactive")]
26    TokenInactive,
27    
28    // ============ Authorization Errors | 授权错误 ============
29    #[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    // ============ Account Status Errors | 账户状态错误 ============
39    #[error("Account is banned until {0}")]
40    AccountBanned(String),
41    
42    #[error("Account is kicked out")]
43    AccountKickedOut,
44
45    #[error("Account login has been replaced on another device")]
46    AccountReplaced,
47
48    #[error("Secondary authentication required for service '{0}'")]
49    NotSafe(String),
50
51    #[error("Account is disabled for service '{service}' at level {level}")]
52    DisableService { service: String, level: i32 },
53    
54    // ============ Session Errors | Session 错误 ============
55    #[error("Session not found")]
56    SessionNotFound,
57    
58    // ============ Nonce Errors | Nonce 错误 ============
59    #[error("Nonce has been used, possible replay attack detected")]
60    NonceAlreadyUsed,
61    
62    #[error("Invalid nonce format")]
63    InvalidNonceFormat,
64    
65    #[error("Nonce timestamp is invalid or expired")]
66    InvalidNonceTimestamp,
67    
68    // ============ Refresh Token Errors | 刷新令牌错误 ============
69    #[error("Refresh token not found or expired")]
70    RefreshTokenNotFound,
71    
72    #[error("Invalid refresh token data")]
73    RefreshTokenInvalidData,
74    
75    #[error("Missing login_id in refresh token")]
76    RefreshTokenMissingLoginId,
77    
78    #[error("Invalid expire time format in refresh token")]
79    RefreshTokenInvalidExpireTime,
80    
81    // ============ Token Validation Errors | Token 验证错误 ============
82    #[error("Token is empty")]
83    TokenEmpty,
84    
85    #[error("Token is too short")]
86    TokenTooShort,
87    
88    #[error("Login ID is not a valid number")]
89    LoginIdNotNumber,
90    
91    // ============ OAuth2 Errors | OAuth2 错误 ============
92    #[error("OAuth2 client not found")]
93    OAuth2ClientNotFound,
94    
95    #[error("Invalid client credentials")]
96    OAuth2InvalidCredentials,
97    
98    #[error("Client ID mismatch")]
99    OAuth2ClientIdMismatch,
100    
101    #[error("Redirect URI mismatch")]
102    OAuth2RedirectUriMismatch,
103    
104    #[error("Authorization code not found or expired")]
105    OAuth2CodeNotFound,
106    
107    #[error("Access token not found or expired")]
108    OAuth2AccessTokenNotFound,
109    
110    #[error("Refresh token not found or expired")]
111    OAuth2RefreshTokenNotFound,
112    
113    #[error("Invalid refresh token data")]
114    OAuth2InvalidRefreshToken,
115    
116    #[error("Invalid scope data")]
117    OAuth2InvalidScope,
118    
119    // ============ SSO Errors | SSO 单点登录错误 ============
120    #[error("SSO ticket not found or invalid")]
121    InvalidTicket,
122    
123    #[error("SSO ticket has expired")]
124    TicketExpired,
125    
126    #[error("Service URL mismatch")]
127    ServiceMismatch,
128    
129    #[error("SSO session not found")]
130    SsoSessionNotFound,
131    
132    // ============ System Errors | 系统错误 ============
133    #[error("Storage error: {0}")]
134    StorageError(String),
135    
136    #[error("Configuration error: {0}")]
137    ConfigError(String),
138    
139    #[error("Serialization error: {0}")]
140    SerializationError(#[from] serde_json::Error),
141    
142    #[error("Internal error: {0}")]
143    InternalError(String),
144}
145
146impl SaTokenError {
147    /// Get the error message as a string
148    /// 
149    /// This method returns the English error message for the error.
150    /// The error messages are defined using the `#[error(...)]` attribute.
151    /// 
152    /// # Examples
153    /// 
154    /// ```rust,ignore
155    /// let err = SaTokenError::NotLogin;
156    /// assert_eq!(err.message(), "User not logged in");
157    /// ```
158    pub fn message(&self) -> String {
159        self.to_string()
160    }
161    
162    /// Check if the error is an authentication error
163    /// 
164    /// Returns `true` for errors related to authentication (login/token validity)
165    pub fn is_auth_error(&self) -> bool {
166        matches!(
167            self,
168            Self::NotLogin 
169            | Self::TokenNotFound 
170            | Self::TokenExpired 
171            | Self::TokenInactive 
172            | Self::InvalidToken(_)
173            | Self::AccountKickedOut
174            | Self::AccountReplaced
175        )
176    }
177    
178    /// Check if the error is an authorization error
179    /// 
180    /// Returns `true` for errors related to permissions or roles
181    pub fn is_authz_error(&self) -> bool {
182        matches!(
183            self,
184            Self::PermissionDenied 
185            | Self::PermissionDeniedDetail(_) 
186            | Self::RoleDenied(_)
187        )
188    }
189}
190
191/// Application-level error messages
192/// 
193/// These constants provide standard error messages for application-specific errors
194/// that are not part of SaTokenError.
195/// 
196/// # Examples
197/// 
198/// ```rust,ignore
199/// use sa_token_core::error::messages;
200/// 
201/// let err_msg = messages::INVALID_CREDENTIALS;
202/// return Err(ApiError::Unauthorized(err_msg.to_string()));
203/// ```
204pub mod messages {
205    /// Invalid username or password
206    pub const INVALID_CREDENTIALS: &str = "Invalid username or password";
207    
208    /// Login failed
209    pub const LOGIN_FAILED: &str = "Login failed";
210    
211    /// Authentication error
212    pub const AUTH_ERROR: &str = "Authentication error";
213    
214    /// Permission required
215    pub const PERMISSION_REQUIRED: &str = "Permission required";
216    
217    /// Role required
218    pub const ROLE_REQUIRED: &str = "Role required";
219}