Initial HerbAPI implementation
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.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user