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("版本冲突: 数据已被其他操作修改,请刷新后重试")] VersionMismatch, } impl From 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::DbError(_) => AppError::Internal(err.to_string()), AuthError::HashError(_) => AppError::Internal(err.to_string()), AuthError::JwtError(_) => AppError::Unauthorized, AuthError::VersionMismatch => AppError::VersionMismatch, } } } pub type AuthResult = Result; #[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), } } }