mod app_routes;
mod describe;
pub mod format;
#[cfg(feature = "with-db")]
mod health;
pub mod middleware;
mod ping;
mod routes;
pub use app_routes::{AppRoutes, ListRoutes};
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
Json,
};
pub use routes::Routes;
use serde::Serialize;
use crate::{errors::Error, Result};
pub fn unauthorized<T>(msg: &str) -> Result<T> {
Err(Error::Unauthorized(msg.to_string()))
}
pub fn not_found<T>() -> Result<T> {
Err(Error::NotFound)
}
#[derive(Debug, Serialize)]
pub struct ErrorDetail {
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
impl ErrorDetail {
#[must_use]
pub fn new(error: &str, description: &str) -> Self {
Self {
error: Some(error.to_string()),
description: Some(description.to_string()),
}
}
#[must_use]
pub fn with_reason(error: &str) -> Self {
Self {
error: Some(error.to_string()),
description: None,
}
}
}
impl IntoResponse for Error {
fn into_response(self) -> Response {
let (code, res) = match self {
Self::NotFound => (
StatusCode::NOT_FOUND,
ErrorDetail::new("not_found", "Resource was not found"),
),
Self::Unauthorized(err) => {
tracing::warn!(err);
(
StatusCode::UNAUTHORIZED,
ErrorDetail::new(
"unauthorized",
"You do not have permission to access this resource",
),
)
}
Self::CustomError(status_code, data) => (status_code, data),
err => {
tracing::warn!("{}", format!("{:?}", err));
(
StatusCode::BAD_REQUEST,
ErrorDetail::with_reason("Bad Request"),
)
}
};
(code, Json(res)).into_response()
}
}