use serde::Serialize;
pub type AppResult<T> = Result<T, AppError>;
#[derive(Debug, thiserror::Error)]
pub enum AppError {
#[error("bad request: {0}")]
BadRequest(String),
#[error("unauthorized")]
Unauthorized,
#[error("forbidden")]
Forbidden,
#[error("not found: {0}")]
NotFound(String),
#[error("conflict: {0}")]
Conflict(String),
#[error("too many requests")]
RateLimited,
#[error("internal: {0}")]
Internal(String),
}
impl AppError {
#[must_use]
pub fn status(&self) -> u16 {
match self {
Self::BadRequest(_) => 400,
Self::Unauthorized => 401,
Self::Forbidden => 403,
Self::NotFound(_) => 404,
Self::Conflict(_) => 409,
Self::RateLimited => 429,
Self::Internal(_) => 500,
}
}
#[must_use]
pub fn to_json(&self) -> serde_json::Value {
let (error, description) = match self {
Self::BadRequest(msg) => ("invalid_request", msg.clone()),
Self::Unauthorized => ("invalid_token", "The access token is invalid".into()),
Self::Forbidden => ("access_denied", "You do not have permission".into()),
Self::NotFound(msg) => ("not_found", msg.clone()),
Self::Conflict(msg) => ("conflict", msg.clone()),
Self::RateLimited => ("rate_limited", "Too many requests".into()),
Self::Internal(msg) => ("internal_error", msg.clone()),
};
serde_json::json!({
"error": error,
"error_description": description,
"ErrorModel": {
"Message": description,
"Object": "error"
}
})
}
}
#[derive(Debug, Serialize)]
pub struct ValidationError {
pub message: String,
pub object: String,
}
impl ValidationError {
#[must_use]
pub fn new(message: impl Into<String>, object: impl Into<String>) -> Self {
Self { message: message.into(), object: object.into() }
}
}