759ae5e
use std::fmt;
pub use export::is_unique_violation;
#[derive(Debug)]
pub enum SpaceError {
BadRequest(String),
Unauthorized,
Forbidden,
JoinNotAllowed(String),
JoinRequirementNotMet(String),
JoinRequestCooldown(String),
NotFound,
Conflict(String),
RateLimited(String),
Internal(String),
}
impl fmt::Display for SpaceError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::BadRequest(message) => write!(f, "{message}"),
Self::Unauthorized => write!(f, "unauthorized"),
Self::Forbidden => write!(f, "forbidden"),
Self::JoinNotAllowed(message) => write!(f, "{message}"),
Self::JoinRequirementNotMet(message) => write!(f, "{message}"),
Self::JoinRequestCooldown(message) => write!(f, "{message}"),
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 SpaceError {}
impl From<kenauth::KenAuthError> for SpaceError {
fn from(error: kenauth::KenAuthError) -> Self {
match error {
kenauth::KenAuthError::NotFound => Self::NotFound,
kenauth::KenAuthError::Unauthenticated => Self::Unauthorized,
kenauth::KenAuthError::Unavailable(message) => {
Self::Internal(format!("kenoauth unavailable: {message}"))
}
kenauth::KenAuthError::Rejected(message) => {
let lower = message.to_lowercase();
if lower.contains("already") || lower.contains("taken") {
Self::Conflict(message)
} else if lower.contains("forbidden") || lower.contains("permission") {
Self::Forbidden
} else {
Self::BadRequest(message)
}
}
kenauth::KenAuthError::Config(message)
| kenauth::KenAuthError::Internal(message) => Self::Internal(message),
}
}
}
export::db_error_conversions!(SpaceError);
export::storage_error_conversion!(SpaceError);
export::export_error_conversion!(SpaceError);
export::json_payload_conversion!(SpaceError);
export::api_error! {
log: "space",
pub enum ApiError {
BadRequest(400, "request failed validation"),
Unauthorized(401, "authentication required"),
Forbidden(403, "operation not allowed"),
NotFound(404, "resource not found"),
Conflict(409, "resource conflict"),
TooManyRequests(429, "rate limit exceeded"),
Internal(500, "internal server error"),
}
}
impl From<SpaceError> for ApiError {
fn from(error: SpaceError) -> Self {
match error {
SpaceError::BadRequest(msg) => Self::bad_request(msg),
SpaceError::Unauthorized => Self::unauthorized(),
SpaceError::Forbidden => Self::forbidden(),
SpaceError::JoinNotAllowed(msg) => Self::forbidden_with_code("join_not_allowed", msg),
SpaceError::JoinRequirementNotMet(msg) => {
Self::forbidden_with_code("join_requirement_not_met", msg)
}
SpaceError::JoinRequestCooldown(msg) => {
Self::forbidden_with_code("join_request_cooldown", msg)
}
SpaceError::NotFound => Self::not_found("space resource not found"),
SpaceError::Conflict(msg) => Self::conflict(msg),
SpaceError::RateLimited(msg) => Self::rate_limited(msg),
SpaceError::Internal(message) => Self::internal(message),
}
}
}