enigma_node_registry/
error.rs1use actix_web::http::StatusCode;
2use actix_web::{HttpResponse, ResponseError};
3use serde::Serialize;
4use serde_json::Value;
5use thiserror::Error;
6
7pub type RegistryResult<T> = Result<T, RegistryError>;
8
9#[derive(Debug, Serialize)]
10pub struct ErrorResponse {
11 pub error: ErrorBody,
12}
13
14#[derive(Debug, Serialize)]
15pub struct ErrorBody {
16 pub code: String,
17 pub message: String,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub details: Option<Value>,
20}
21
22#[derive(Debug, Error)]
23pub enum RegistryError {
24 #[error("invalid input: {0}")]
25 InvalidInput(String),
26 #[error("conflict")]
27 Conflict,
28 #[error("not found")]
29 NotFound,
30 #[error("rate limited")]
31 RateLimited,
32 #[error("pow required")]
33 PowRequired,
34 #[error("unauthorized")]
35 Unauthorized,
36 #[error("config error: {0}")]
37 Config(String),
38 #[error("feature disabled: {0}")]
39 FeatureDisabled(String),
40 #[error("internal error")]
41 Internal,
42}
43
44impl RegistryError {
45 pub fn with_details(self, details: Value) -> Self {
46 match self {
47 RegistryError::InvalidInput(msg) => {
48 RegistryError::InvalidInput(format!("{}: {}", msg, details))
49 }
50 RegistryError::Config(msg) => RegistryError::Config(format!("{}: {}", msg, details)),
51 other => other,
52 }
53 }
54}
55
56impl ResponseError for RegistryError {
57 fn status_code(&self) -> StatusCode {
58 match self {
59 RegistryError::InvalidInput(_) => StatusCode::BAD_REQUEST,
60 RegistryError::Conflict => StatusCode::CONFLICT,
61 RegistryError::NotFound => StatusCode::NOT_FOUND,
62 RegistryError::RateLimited => StatusCode::TOO_MANY_REQUESTS,
63 RegistryError::PowRequired => StatusCode::BAD_REQUEST,
64 RegistryError::Unauthorized => StatusCode::UNAUTHORIZED,
65 RegistryError::Config(_) => StatusCode::BAD_REQUEST,
66 RegistryError::FeatureDisabled(_) => StatusCode::BAD_REQUEST,
67 RegistryError::Internal => StatusCode::INTERNAL_SERVER_ERROR,
68 }
69 }
70
71 fn error_response(&self) -> HttpResponse {
72 let code = match self {
73 RegistryError::InvalidInput(_) => "INVALID_INPUT",
74 RegistryError::Conflict => "CONFLICT",
75 RegistryError::NotFound => "NOT_FOUND",
76 RegistryError::RateLimited => "RATE_LIMITED",
77 RegistryError::PowRequired => "POW_REQUIRED",
78 RegistryError::Unauthorized => "UNAUTHORIZED",
79 RegistryError::Config(_) => "CONFIG",
80 RegistryError::FeatureDisabled(_) => "FEATURE_DISABLED",
81 RegistryError::Internal => "INTERNAL",
82 };
83 let message = self.to_string();
84 let body = ErrorResponse {
85 error: ErrorBody {
86 code: code.to_string(),
87 message,
88 details: None,
89 },
90 };
91 HttpResponse::build(self.status_code()).json(body)
92 }
93}
94
95impl From<serde_json::Error> for RegistryError {
96 fn from(err: serde_json::Error) -> Self {
97 RegistryError::InvalidInput(err.to_string())
98 }
99}
100
101impl From<std::io::Error> for RegistryError {
102 fn from(err: std::io::Error) -> Self {
103 RegistryError::Config(err.to_string())
104 }
105}
106
107#[cfg(feature = "persistence")]
108impl From<sled::Error> for RegistryError {
109 fn from(err: sled::Error) -> Self {
110 RegistryError::Internal.with_details(serde_json::json!({ "error": err.to_string() }))
111 }
112}