gbserver/gb-core/src/errors.rs

116 lines
2.8 KiB
Rust
Raw Normal View History

2024-12-22 20:56:52 -03:00
use thiserror::Error;
2024-12-23 00:54:50 -03:00
use axum::{
response::{IntoResponse, Response},
http::StatusCode,
Json,
};
use serde_json::json;
2024-12-22 20:56:52 -03:00
#[derive(Error, Debug)]
2024-12-23 00:20:59 -03:00
pub enum ErrorKind {
2024-12-22 20:56:52 -03:00
#[error("Database error: {0}")]
2024-12-23 00:20:59 -03:00
Database(String),
2024-12-22 20:56:52 -03:00
#[error("Redis error: {0}")]
2024-12-23 00:20:59 -03:00
Redis(String),
2024-12-22 20:56:52 -03:00
#[error("Kafka error: {0}")]
Kafka(String),
2024-12-23 00:20:59 -03:00
2024-12-22 20:56:52 -03:00
#[error("Invalid input: {0}")]
InvalidInput(String),
2024-12-23 00:20:59 -03:00
2024-12-22 20:56:52 -03:00
#[error("Not found: {0}")]
NotFound(String),
2024-12-23 00:20:59 -03:00
#[error("Authentication error: {0}")]
Authentication(String),
#[error("Authorization error: {0}")]
Authorization(String),
#[error("Internal error: {0}")]
Internal(String),
#[error("External service error: {0}")]
ExternalService(String),
2024-12-22 20:56:52 -03:00
2024-12-23 00:20:59 -03:00
#[error("WebSocket error: {0}")]
WebSocket(String),
2024-12-22 20:56:52 -03:00
2024-12-23 00:20:59 -03:00
#[error("Messaging error: {0}")]
Messaging(String),
}
2024-12-22 20:56:52 -03:00
2024-12-23 00:20:59 -03:00
#[derive(Debug)]
pub struct Error {
pub kind: ErrorKind,
pub message: String,
2024-12-22 20:56:52 -03:00
}
2024-12-23 00:20:59 -03:00
impl Error {
pub fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
Self {
kind,
message: message.into(),
}
}
pub fn internal<T: std::fmt::Display>(msg: T) -> Self {
Self::new(ErrorKind::Internal(msg.to_string()), msg.to_string())
}
2024-12-22 20:56:52 -03:00
2024-12-23 00:20:59 -03:00
pub fn redis<T: std::fmt::Display>(msg: T) -> Self {
Self::new(ErrorKind::Redis(msg.to_string()), msg.to_string())
}
2024-12-22 20:56:52 -03:00
2024-12-23 00:20:59 -03:00
pub fn kafka<T: std::fmt::Display>(msg: T) -> Self {
Self::new(ErrorKind::Kafka(msg.to_string()), msg.to_string())
}
2024-12-22 20:56:52 -03:00
2024-12-23 00:20:59 -03:00
pub fn database<T: std::fmt::Display>(msg: T) -> Self {
Self::new(ErrorKind::Database(msg.to_string()), msg.to_string())
}
2024-12-22 20:56:52 -03:00
2024-12-23 00:20:59 -03:00
pub fn websocket<T: std::fmt::Display>(msg: T) -> Self {
Self::new(ErrorKind::WebSocket(msg.to_string()), msg.to_string())
2024-12-22 20:56:52 -03:00
}
}
2024-12-23 00:20:59 -03:00
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.kind, self.message)
}
}
impl std::error::Error for Error {}
2024-12-23 00:54:50 -03:00
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub enum AuthError {
InvalidToken,
MissingToken,
InvalidCredentials,
Internal(String),
}
impl IntoResponse for Error {
fn into_response(self) -> Response {
let status = match self.kind {
ErrorKind::NotFound(_) => StatusCode::NOT_FOUND,
ErrorKind::Authentication(_) => StatusCode::UNAUTHORIZED,
ErrorKind::Authorization(_) => StatusCode::FORBIDDEN,
ErrorKind::InvalidInput(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR,
};
let body = Json(json!({
"error": self.message,
"kind": format!("{:?}", self.kind)
}));
(status, body).into_response()
}
}