Skip to content
Clone
eba4fd1
144 lines 5.1 KB Rust
use std::fmt;
#[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),
}
}
}
#[derive(Debug)]
pub struct AdminApiErrorPayload {
pub message: String,
}
#[derive(Debug)]
pub enum AdminApiError {
BadRequest(AdminApiErrorPayload),
Unauthorized(AdminApiErrorPayload),
Forbidden(AdminApiErrorPayload),
NotFound(AdminApiErrorPayload),
Conflict(AdminApiErrorPayload),
RateLimited(AdminApiErrorPayload),
Internal(AdminApiErrorPayload),
}
impl AdminApiError {
fn payload(message: impl Into<String>) -> AdminApiErrorPayload {
AdminApiErrorPayload {
message: message.into(),
}
}
pub fn bad_request(message: impl AsRef<str>) -> Self {
Self::BadRequest(Self::payload(message.as_ref()))
}
pub fn unauthorized() -> Self {
Self::Unauthorized(Self::payload("unauthorized"))
}
pub fn forbidden() -> Self {
Self::Forbidden(Self::payload("forbidden"))
}
pub fn not_found(message: &'static str) -> Self {
Self::NotFound(Self::payload(message))
}
pub fn conflict(message: impl AsRef<str>) -> Self {
Self::Conflict(Self::payload(message.as_ref()))
}
pub fn rate_limited(message: impl Into<String>) -> Self {
Self::RateLimited(Self::payload(message))
}
pub fn internal(message: impl fmt::Display) -> Self {
tracing::warn!(error = %message, "admin handler failed");
Self::Internal(Self::payload("internal server error"))
}
}
impl From<AdminError> for AdminApiError {
fn from(error: AdminError) -> Self {
match error {
AdminError::BadRequest(message) => Self::bad_request(message),
AdminError::InvalidCredentials => {
Self::Unauthorized(Self::payload("invalid username or password"))
}
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),
}
}
}