| use axum::http::StatusCode; |
| use axum::response::{IntoResponse, Response}; |
| use axum::Json; |
| use serde_json::json; |
| use tracing::error; |
|
|
| #[derive(Debug, thiserror::Error)] |
| pub enum AppError { |
| #[error("Not found: {0}")] |
| NotFound(String), |
|
|
| #[error("Unauthorized: {0}")] |
| Unauthorized(String), |
|
|
| #[error("Bad request: {0}")] |
| BadRequest(String), |
|
|
| #[error("Forbidden: {0}")] |
| Forbidden(String), |
|
|
| #[error("Conflict: {0}")] |
| Conflict(String), |
|
|
| #[error("{0}")] |
| Validation(String), |
|
|
| #[error("Internal error")] |
| Internal, |
|
|
| #[error(transparent)] |
| Database(#[from] sqlx::Error), |
|
|
| #[error(transparent)] |
| Jwt(#[from] jsonwebtoken::errors::Error), |
|
|
| #[error(transparent)] |
| Io(#[from] std::io::Error), |
|
|
| #[error("Argon2 error")] |
| #[allow(dead_code)] |
| Argon, |
|
|
| #[error(transparent)] |
| Reqwest(#[from] reqwest::Error), |
| } |
|
|
| impl IntoResponse for AppError { |
| fn into_response(self) -> Response { |
| error!("AppError: {self:?}"); |
| let (status, message) = match &self { |
| AppError::NotFound(m) => (StatusCode::NOT_FOUND, m.clone()), |
| AppError::Unauthorized(m) => (StatusCode::UNAUTHORIZED, m.clone()), |
| AppError::BadRequest(m) => (StatusCode::BAD_REQUEST, m.clone()), |
| AppError::Forbidden(m) => (StatusCode::FORBIDDEN, m.clone()), |
| AppError::Conflict(m) => (StatusCode::CONFLICT, m.clone()), |
| AppError::Validation(m) => (StatusCode::UNPROCESSABLE_ENTITY, m.clone()), |
| AppError::Internal => (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".into()), |
| AppError::Database(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".into()), |
| AppError::Jwt(_) => (StatusCode::UNAUTHORIZED, "Invalid token".into()), |
| AppError::Io(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".into()), |
| AppError::Argon => (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".into()), |
| AppError::Reqwest(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".into()), |
| }; |
|
|
| (status, Json(json!({ "error": message }))).into_response() |
| } |
| } |
|
|
| pub type Result<T> = std::result::Result<T, AppError>; |
|
|