warden-worker/src/error.rs
2025-12-06 17:52:31 +00:00

80 lines
2.7 KiB
Rust

use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::Json;
use serde_json::{json, Value};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("Worker error: {0}")]
Worker(#[from] worker::Error),
#[error("Database query failed")]
Database,
#[error("Not found: {0}")]
NotFound(String),
#[error("Invalid request: {0}")]
BadRequest(String),
#[error("Unauthorized: {0}")]
Unauthorized(String),
#[error("Too many requests: {0}")]
TooManyRequests(String),
#[error("Cryptography error: {0}")]
Crypto(String),
#[error(transparent)]
JsonWebToken(#[from] jsonwebtoken::errors::Error),
#[error("Internal server error")]
Internal,
#[error("Two factor authentication required")]
TwoFactorRequired(Value),
}
impl IntoResponse for AppError {
fn into_response(self) -> Response {
match self {
AppError::TwoFactorRequired(json_body) => {
// Return 400 Bad Request with the 2FA required JSON response as expected by clients
(StatusCode::BAD_REQUEST, Json(json_body)).into_response()
}
other => {
let (status, error_message) = match other {
AppError::Worker(e) => (
StatusCode::INTERNAL_SERVER_ERROR,
format!("Worker error: {}", e),
),
AppError::Database => (
StatusCode::INTERNAL_SERVER_ERROR,
"Database error".to_string(),
),
AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg),
AppError::Unauthorized(msg) => (StatusCode::UNAUTHORIZED, msg),
AppError::TooManyRequests(msg) => (StatusCode::TOO_MANY_REQUESTS, msg),
AppError::Crypto(msg) => (
StatusCode::INTERNAL_SERVER_ERROR,
format!("Crypto error: {}", msg),
),
AppError::JsonWebToken(_) => {
(StatusCode::UNAUTHORIZED, "Invalid token".to_string())
}
AppError::Internal => (
StatusCode::INTERNAL_SERVER_ERROR,
"Internal server error".to_string(),
),
AppError::TwoFactorRequired(_) => unreachable!(),
};
let body = Json(json!({ "error": error_message }));
(status, body).into_response()
}
}
}
}