acbf7ea
use std::fmt;
#[derive(Debug)]
pub enum AuthError {
BadRequest(String),
InvalidCredentials,
Unauthorized,
Forbidden,
NotFound,
Conflict(String),
RateLimited,
Internal(String),
TwoFactorExpired,
TwoFactorCodeInvalid,
RecoveryCodeInvalid,
VerificationCodeExpired,
VerificationCodeInvalid,
ResetTokenInvalid,
}
impl fmt::Display for AuthError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::BadRequest(message) => write!(f, "{message}"),
Self::InvalidCredentials => write!(f, "invalid credentials"),
Self::Unauthorized => write!(f, "unauthorized"),
Self::Forbidden => write!(f, "forbidden"),
Self::NotFound => write!(f, "not found"),
Self::Conflict(message) => write!(f, "{message}"),
Self::RateLimited => write!(f, "rate limit exceeded"),
Self::Internal(message) => write!(f, "{message}"),
Self::TwoFactorExpired => write!(f, "two-factor challenge expired"),
Self::TwoFactorCodeInvalid => write!(f, "invalid two-factor code"),
Self::RecoveryCodeInvalid => write!(f, "invalid or used recovery code"),
Self::VerificationCodeExpired => write!(f, "verification code expired"),
Self::VerificationCodeInvalid => write!(f, "invalid verification code"),
Self::ResetTokenInvalid => write!(f, "invalid or expired reset token"),
}
}
}
impl std::error::Error for AuthError {}
export::db_error_conversions!(AuthError);
export::redis_error_conversion!(AuthError);
export::export_error_conversion!(AuthError);
export::json_payload_conversion!(AuthError);
export::api_error! {
log: "auth",
pub enum ApiError {
BadRequest(400, "request failed validation"),
InvalidCredentials(400, "credentials rejected"),
Unauthorized(401, "authentication required"),
Forbidden(403, "operation not allowed"),
NotFound(404, "resource not found"),
Conflict(409, "resource conflict"),
RateLimited(429, "rate limit exceeded"),
Internal(500, "internal server error"),
}
}
impl From<AuthError> for ApiError {
fn from(error: AuthError) -> Self {
match error {
AuthError::BadRequest(msg) => Self::bad_request(msg),
AuthError::InvalidCredentials => {
Self::build(400, Self::payload(400, "invalid credentials"))
}
AuthError::Unauthorized => Self::unauthorized(),
AuthError::Forbidden => Self::forbidden(),
AuthError::NotFound => Self::not_found("auth resource not found"),
AuthError::Conflict(msg) => Self::conflict(msg),
AuthError::RateLimited => Self::rate_limited_exceeded(),
AuthError::TwoFactorExpired => Self::build(
400,
Self::payload(400, "two-factor challenge expired")
.with_error_code("two_factor_expired"),
),
AuthError::TwoFactorCodeInvalid => Self::build(
400,
Self::payload(400, "invalid two-factor code")
.with_error_code("two_factor_code_invalid"),
),
AuthError::RecoveryCodeInvalid => Self::build(
400,
Self::payload(400, "invalid or used recovery code")
.with_error_code("recovery_code_invalid"),
),
AuthError::VerificationCodeExpired => Self::build(
400,
Self::payload(400, "verification code expired")
.with_error_code("verification_code_expired"),
),
AuthError::VerificationCodeInvalid => Self::build(
400,
Self::payload(400, "invalid verification code")
.with_error_code("verification_code_invalid"),
),
AuthError::ResetTokenInvalid => Self::build(
400,
Self::payload(400, "invalid or expired reset token")
.with_error_code("reset_token_invalid"),
),
AuthError::Internal(message) => Self::internal(message),
}
}
}