1use axum::Json;
2use axum::http::StatusCode;
3use axum::response::{IntoResponse, Response};
4use color_eyre::eyre::Error;
5use serde_json::json;
6pub type ApiResult<T> = Result<T, ApiError>;
7
8#[derive(Debug)]
9pub enum ApiError {
10 Unauthorized,
11 Forbidden,
12 NotFound(String),
13 BadRequest(String),
14 InternalError(String),
15 VaultError(String),
16 ValidationError(String),
17}
18
19impl IntoResponse for ApiError {
20 fn into_response(self) -> Response {
21 let (status, code, message) = match self {
22 ApiError::Unauthorized => (
23 StatusCode::UNAUTHORIZED,
24 "UNAUTHORIZED",
25 String::from("Authentication required"),
26 ),
27 ApiError::Forbidden => (StatusCode::FORBIDDEN, "FORBIDDEN", String::from("Access denied")),
28 ApiError::NotFound(msg) => (StatusCode::NOT_FOUND, "NOT_FOUND", msg),
29 ApiError::BadRequest(msg) => (StatusCode::BAD_REQUEST, "BAD_REQUEST", msg),
30 ApiError::InternalError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, "INTERNAL_ERROR", msg),
31 ApiError::VaultError(msg) => (StatusCode::BAD_REQUEST, "VAULT_ERROR", msg),
32 ApiError::ValidationError(msg) => (StatusCode::UNPROCESSABLE_ENTITY, "VALIDATION_ERROR", msg),
33 };
34
35 let body = Json(json!({
36 "error": {
37 "code": code,
38 "message": message.as_str()
39 }
40 }));
41
42 (status, body).into_response()
43 }
44}
45
46impl From<Error> for ApiError {
47 fn from(err: Error) -> Self {
48 ApiError::InternalError(err.to_string())
49 }
50}