106 lines
3.1 KiB
Rust
106 lines
3.1 KiB
Rust
use erp_core::error::AppError;
|
|
|
|
/// Auth module error types
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum AuthError {
|
|
#[error("用户名或密码错误")]
|
|
InvalidCredentials,
|
|
|
|
#[error("Token 已过期")]
|
|
TokenExpired,
|
|
|
|
#[error("Token 已被吊销")]
|
|
TokenRevoked,
|
|
|
|
#[error("用户已被{0}")]
|
|
UserDisabled(String),
|
|
|
|
#[error("密码哈希错误")]
|
|
HashError(String),
|
|
|
|
#[error("JWT 错误: {0}")]
|
|
JwtError(#[from] jsonwebtoken::errors::Error),
|
|
|
|
#[error("数据库错误: {0}")]
|
|
DbError(String),
|
|
|
|
#[error("{0}")]
|
|
Validation(String),
|
|
|
|
#[error("{0}")]
|
|
Forbidden(String),
|
|
|
|
#[error("版本冲突: 数据已被其他操作修改,请刷新后重试")]
|
|
VersionMismatch,
|
|
}
|
|
|
|
impl From<AuthError> for AppError {
|
|
fn from(err: AuthError) -> Self {
|
|
match err {
|
|
AuthError::InvalidCredentials => AppError::Unauthorized,
|
|
AuthError::TokenExpired => AppError::Unauthorized,
|
|
AuthError::TokenRevoked => AppError::Unauthorized,
|
|
AuthError::UserDisabled(s) => AppError::Forbidden(s),
|
|
AuthError::Validation(s) => AppError::Validation(s),
|
|
AuthError::Forbidden(s) => AppError::Forbidden(s),
|
|
AuthError::DbError(_) => AppError::Internal(err.to_string()),
|
|
AuthError::HashError(_) => AppError::Internal(err.to_string()),
|
|
AuthError::JwtError(_) => AppError::Unauthorized,
|
|
AuthError::VersionMismatch => AppError::VersionMismatch,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub type AuthResult<T> = Result<T, AuthError>;
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use erp_core::error::AppError;
|
|
|
|
#[test]
|
|
fn auth_error_invalid_credentials_maps_to_unauthorized() {
|
|
let app: AppError = AuthError::InvalidCredentials.into();
|
|
match app {
|
|
AppError::Unauthorized => {}
|
|
other => panic!("Expected Unauthorized, got {:?}", other),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn auth_error_token_expired_maps_to_unauthorized() {
|
|
let app: AppError = AuthError::TokenExpired.into();
|
|
match app {
|
|
AppError::Unauthorized => {}
|
|
other => panic!("Expected Unauthorized, got {:?}", other),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn auth_error_user_disabled_maps_to_forbidden() {
|
|
let app: AppError = AuthError::UserDisabled("已禁用".to_string()).into();
|
|
match app {
|
|
AppError::Forbidden(msg) => assert_eq!(msg, "已禁用"),
|
|
other => panic!("Expected Forbidden, got {:?}", other),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn auth_error_hash_error_maps_to_internal() {
|
|
let app: AppError = AuthError::HashError("argon2 failed".to_string()).into();
|
|
match app {
|
|
AppError::Internal(_) => {}
|
|
other => panic!("Expected Internal, got {:?}", other),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn auth_error_validation_maps_to_validation() {
|
|
let app: AppError = AuthError::Validation("用户名已存在".to_string()).into();
|
|
match app {
|
|
AppError::Validation(msg) => assert_eq!(msg, "用户名已存在"),
|
|
other => panic!("Expected Validation, got {:?}", other),
|
|
}
|
|
}
|
|
}
|