195 lines
7.3 KiB
Rust
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()),
|
|
}
|
|
}
|