Files
Genarrative/server-rs/crates/module-auth/src/errors.rs
高物 5831703156
Some checks failed
CI / verify (push) Has been cancelled
1
2026-05-02 20:43:41 +08:00

195 lines
7.3 KiB
Rust

//! 认证领域错误。
//!
//! 领域错误保持可测试、可映射,不能直接依赖 Axum、cookie 或平台 provider 错误模型。
use std::{error::Error, fmt};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PasswordEntryError {
InvalidPhoneNumber,
InvalidPasswordLength,
InvalidDisplayName,
InvalidAvatarDataUrl,
EmptyProfileUpdate,
InvalidPublicUserCode,
InvalidCredentials,
UserNotFound,
Store(String),
PasswordHash(String),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PhoneAuthError {
InvalidPhoneNumber,
InvalidVerifyCode,
VerifyCodeNotFound,
VerifyCodeExpired,
SendCoolingDown { retry_after_seconds: u64 },
VerifyAttemptsExceeded,
UserNotFound,
UserStateMismatch,
Store(String),
PasswordHash(String),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum WechatAuthError {
MissingProfile,
StateNotFound,
StateExpired,
StateConsumed,
UserNotFound,
MissingWechatIdentity,
Store(String),
PasswordHash(String),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RefreshSessionError {
MissingToken,
SessionNotFound,
SessionExpired,
UserNotFound,
Store(String),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LogoutError {
UserNotFound,
Store(String),
}
impl fmt::Display for PasswordEntryError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidPhoneNumber => f.write_str("手机号格式不正确"),
Self::InvalidPasswordLength => f.write_str("密码长度需要在 6 到 128 位之间"),
Self::InvalidDisplayName => f.write_str("昵称格式不正确"),
Self::InvalidAvatarDataUrl => f.write_str("头像图片格式不正确"),
Self::EmptyProfileUpdate => f.write_str("请至少修改昵称或头像"),
Self::InvalidPublicUserCode => f.write_str("百梦号格式不正确"),
Self::InvalidCredentials => f.write_str("手机号或密码错误"),
Self::UserNotFound => f.write_str("用户不存在"),
Self::Store(message) | Self::PasswordHash(message) => f.write_str(message),
}
}
}
impl Error for PasswordEntryError {}
impl fmt::Display for PhoneAuthError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidPhoneNumber => f.write_str("手机号格式不正确"),
Self::InvalidVerifyCode => f.write_str("验证码错误"),
Self::VerifyCodeNotFound => f.write_str("验证码不存在或已失效"),
Self::VerifyCodeExpired => f.write_str("验证码已过期"),
Self::SendCoolingDown { .. } => f.write_str("验证码发送过于频繁,请稍后再试"),
Self::VerifyAttemptsExceeded => f.write_str("验证码错误次数过多,请重新获取验证码"),
Self::UserNotFound => f.write_str("用户不存在"),
Self::UserStateMismatch => f.write_str("当前账号状态不允许执行该操作"),
Self::Store(message) | Self::PasswordHash(message) => f.write_str(message),
}
}
}
impl Error for PhoneAuthError {}
impl fmt::Display for WechatAuthError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MissingProfile => f.write_str("缺少微信身份信息"),
Self::StateNotFound => f.write_str("微信登录状态已失效,请重新发起登录"),
Self::StateExpired => f.write_str("微信登录状态已过期,请重新发起登录"),
Self::StateConsumed => f.write_str("微信登录状态已被消费,请重新发起登录"),
Self::UserNotFound => f.write_str("用户不存在"),
Self::MissingWechatIdentity => f.write_str("当前账号缺少微信身份"),
Self::Store(message) | Self::PasswordHash(message) => f.write_str(message),
}
}
}
impl Error for WechatAuthError {}
impl fmt::Display for RefreshSessionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MissingToken => f.write_str("缺少刷新会话"),
Self::SessionNotFound | Self::SessionExpired | Self::UserNotFound => {
f.write_str("当前登录态已失效,请重新登录")
}
Self::Store(message) => f.write_str(message),
}
}
}
impl Error for RefreshSessionError {}
impl fmt::Display for LogoutError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::UserNotFound => f.write_str("当前登录态已失效,请重新登录"),
Self::Store(message) => f.write_str(message),
}
}
}
impl Error for LogoutError {}
pub(crate) fn map_password_store_error(error: PasswordEntryError) -> RefreshSessionError {
match error {
PasswordEntryError::Store(message) => RefreshSessionError::Store(message),
PasswordEntryError::InvalidPhoneNumber
| PasswordEntryError::InvalidPasswordLength
| PasswordEntryError::InvalidDisplayName
| PasswordEntryError::InvalidAvatarDataUrl
| PasswordEntryError::EmptyProfileUpdate
| PasswordEntryError::InvalidPublicUserCode
| PasswordEntryError::InvalidCredentials
| PasswordEntryError::UserNotFound
| PasswordEntryError::PasswordHash(_) => {
RefreshSessionError::Store("用户仓储读取失败".to_string())
}
}
}
pub(crate) fn map_password_error_to_phone_error(error: PasswordEntryError) -> PhoneAuthError {
match error {
PasswordEntryError::Store(message) => PhoneAuthError::Store(message),
PasswordEntryError::PasswordHash(message) => PhoneAuthError::PasswordHash(message),
PasswordEntryError::InvalidPhoneNumber
| PasswordEntryError::InvalidPasswordLength
| PasswordEntryError::InvalidDisplayName
| PasswordEntryError::InvalidAvatarDataUrl
| PasswordEntryError::EmptyProfileUpdate
| PasswordEntryError::InvalidPublicUserCode
| PasswordEntryError::InvalidCredentials
| PasswordEntryError::UserNotFound => PhoneAuthError::Store("用户仓储读取失败".to_string()),
}
}
pub(crate) fn map_password_error_to_logout_error(error: PasswordEntryError) -> LogoutError {
match error {
PasswordEntryError::Store(message) => LogoutError::Store(message),
PasswordEntryError::InvalidPhoneNumber
| PasswordEntryError::InvalidPasswordLength
| PasswordEntryError::InvalidDisplayName
| PasswordEntryError::InvalidAvatarDataUrl
| PasswordEntryError::EmptyProfileUpdate
| PasswordEntryError::InvalidPublicUserCode
| PasswordEntryError::InvalidCredentials
| PasswordEntryError::UserNotFound
| PasswordEntryError::PasswordHash(_) => LogoutError::Store("用户仓储读取失败".to_string()),
}
}
pub(crate) fn map_refresh_error_to_logout_error(error: RefreshSessionError) -> LogoutError {
match error {
RefreshSessionError::Store(message) => LogoutError::Store(message),
RefreshSessionError::MissingToken
| RefreshSessionError::SessionNotFound
| RefreshSessionError::SessionExpired
| RefreshSessionError::UserNotFound => LogoutError::Store("会话吊销失败".to_string()),
}
}