Skip to content
Clone
11f67b5
128 lines 4.7 KB Rust
use std::fmt;
use axum::response::{IntoResponse, Response};
use export::rest::AppResponseData;
use export::rest::NoData;
#[derive(Debug)]
pub enum AdminError {
BadRequest(String),
InvalidCredentials,
Unauthorized,
Forbidden,
NotFound,
Conflict(String),
RateLimited(String),
Internal(String),
}
impl fmt::Display for AdminError {
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(message) => write!(f, "{message}"),
Self::Internal(message) => write!(f, "{message}"),
}
}
}
impl std::error::Error for AdminError {}
export::db_error_conversions!(AdminError);
export::storage_error_conversion!(AdminError);
export::redis_error_conversion!(AdminError);
export::export_error_conversion!(AdminError);
export::json_payload_conversion!(AdminError);
impl From<auth::errors::AuthError> for AdminError {
fn from(error: auth::errors::AuthError) -> Self {
match error {
auth::errors::AuthError::BadRequest(message) => Self::BadRequest(message),
auth::errors::AuthError::InvalidCredentials => Self::InvalidCredentials,
auth::errors::AuthError::Unauthorized => Self::Unauthorized,
auth::errors::AuthError::Forbidden => Self::Forbidden,
auth::errors::AuthError::NotFound => Self::NotFound,
auth::errors::AuthError::Conflict(message) => Self::Conflict(message),
auth::errors::AuthError::RateLimited => {
Self::RateLimited("rate limit exceeded".to_string())
}
auth::errors::AuthError::PowFailed => {
Self::BadRequest("proof of work failed".to_string())
}
auth::errors::AuthError::TwoFactorExpired => {
Self::BadRequest("two-factor challenge expired".to_string())
}
auth::errors::AuthError::TwoFactorCodeInvalid => {
Self::BadRequest("invalid two-factor code".to_string())
}
auth::errors::AuthError::RecoveryCodeInvalid => {
Self::BadRequest("invalid or used recovery code".to_string())
}
auth::errors::AuthError::VerificationCodeExpired => {
Self::BadRequest("verification code expired".to_string())
}
auth::errors::AuthError::VerificationCodeInvalid => {
Self::BadRequest("invalid verification code".to_string())
}
auth::errors::AuthError::ResetTokenInvalid => {
Self::BadRequest("invalid or expired reset token".to_string())
}
auth::errors::AuthError::Internal(message) => Self::Internal(message),
}
}
}
export::api_error! {
log: "admin",
pub enum AdminApiError {
BadRequest(400, "request failed validation"),
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 AdminApiError {
pub fn invalid_credentials() -> Self {
Self::build(
401,
AppResponseData::<NoData>::err(401, "invalid username or password")
.with_error_code("invalid_credentials"),
)
}
pub fn password_change_required() -> Self {
Self::build(
403,
AppResponseData::<NoData>::err(403, "password change required")
.with_error_code("password_change_required"),
)
}
}
pub fn password_change_required_response() -> Response {
AdminApiError::password_change_required().into_response()
}
impl From<AdminError> for AdminApiError {
fn from(error: AdminError) -> Self {
match error {
AdminError::BadRequest(message) => Self::bad_request(message),
AdminError::InvalidCredentials => Self::invalid_credentials(),
AdminError::Unauthorized => Self::unauthorized(),
AdminError::Forbidden => Self::forbidden(),
AdminError::NotFound => Self::not_found("admin resource not found"),
AdminError::Conflict(message) => Self::conflict(message),
AdminError::RateLimited(message) => Self::rate_limited(message),
AdminError::Internal(message) => Self::internal(message),
}
}
}