484979ad53
Rust/Axum REST API (herbapi-api) with PostgreSQL, S3/Garage, OIDC auth. Dioxus 0.7 WASM frontend (herbapi-ui) with sidebar layout and botanical reference style. 9 SQL migrations covering families, species, cultivars, suppliers, companions, images, users, API tokens.
63 lines
1.8 KiB
Rust
63 lines
1.8 KiB
Rust
use axum::http::StatusCode;
|
|
use axum::response::{IntoResponse, Response};
|
|
use serde_json::json;
|
|
|
|
pub type Result<T> = std::result::Result<T, AppError>;
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum AppError {
|
|
#[error("Not found: {0}")]
|
|
NotFound(String),
|
|
|
|
#[error("Unauthorized: {0}")]
|
|
#[allow(dead_code)]
|
|
Unauthorized(String),
|
|
|
|
#[error("Bad request: {0}")]
|
|
BadRequest(String),
|
|
|
|
#[error("Forbidden")]
|
|
Forbidden,
|
|
|
|
#[error("Database error: {0}")]
|
|
Database(#[from] sqlx::Error),
|
|
|
|
#[error("S3 error: {0}")]
|
|
S3(String),
|
|
|
|
#[error("Internal error: {0}")]
|
|
Internal(String),
|
|
}
|
|
|
|
impl IntoResponse for AppError {
|
|
fn into_response(self) -> Response {
|
|
let (status, message) = match &self {
|
|
AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
|
|
AppError::Unauthorized(msg) => (StatusCode::UNAUTHORIZED, msg.clone()),
|
|
AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
|
|
AppError::Forbidden => (StatusCode::FORBIDDEN, "Forbidden".to_string()),
|
|
AppError::Database(e) => {
|
|
tracing::error!("Database error: {e}");
|
|
(
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
"Database error".to_string(),
|
|
)
|
|
}
|
|
AppError::S3(msg) => {
|
|
tracing::error!("S3 error: {msg}");
|
|
(StatusCode::INTERNAL_SERVER_ERROR, "Storage error".to_string())
|
|
}
|
|
AppError::Internal(msg) => {
|
|
tracing::error!("Internal error: {msg}");
|
|
(
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
"Internal error".to_string(),
|
|
)
|
|
}
|
|
};
|
|
|
|
let body = axum::Json(json!({ "error": message }));
|
|
(status, body).into_response()
|
|
}
|
|
}
|