1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum SiemError {
5 #[error("Authentication failed: {0}")]
6 AuthError(String),
7
8 #[error("Connection failed: {0}")]
9 ConnectionError(String),
10
11 #[error("API error ({status}): {message}")]
12 ApiError { status: u16, message: String },
13
14 #[error("Not found: {0}")]
15 NotFound(String),
16
17 #[error("Invalid configuration: {0}")]
18 ConfigError(String),
19
20 #[error("Serialization error: {0}")]
21 SerializationError(String),
22
23 #[error("Provider error [{provider}]: {message}")]
24 ProviderError { provider: String, message: String },
25
26 #[error("{0}")]
27 Other(String),
28}
29
30pub type SiemResult<T> = Result<T, SiemError>;
31
32impl From<serde_json::Error> for SiemError {
33 fn from(err: serde_json::Error) -> Self {
34 SiemError::SerializationError(err.to_string())
35 }
36}
37
38#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
44pub struct SiemApiError {
45 pub error_type: String,
46 pub message: String,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub status: Option<u16>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub provider: Option<String>,
51}
52
53impl From<&SiemError> for SiemApiError {
54 fn from(err: &SiemError) -> Self {
55 match err {
56 SiemError::AuthError(msg) => SiemApiError {
57 error_type: "auth".to_string(),
58 message: msg.clone(),
59 status: Some(401),
60 provider: None,
61 },
62 SiemError::ConnectionError(msg) => SiemApiError {
63 error_type: "connection".to_string(),
64 message: msg.clone(),
65 status: None,
66 provider: None,
67 },
68 SiemError::ApiError { status, message } => SiemApiError {
69 error_type: "api".to_string(),
70 message: message.clone(),
71 status: Some(*status),
72 provider: None,
73 },
74 SiemError::NotFound(msg) => SiemApiError {
75 error_type: "not_found".to_string(),
76 message: msg.clone(),
77 status: Some(404),
78 provider: None,
79 },
80 SiemError::ConfigError(msg) => SiemApiError {
81 error_type: "config".to_string(),
82 message: msg.clone(),
83 status: None,
84 provider: None,
85 },
86 SiemError::SerializationError(msg) => SiemApiError {
87 error_type: "serialization".to_string(),
88 message: msg.clone(),
89 status: None,
90 provider: None,
91 },
92 SiemError::ProviderError { provider, message } => SiemApiError {
93 error_type: "provider".to_string(),
94 message: message.clone(),
95 status: None,
96 provider: Some(provider.clone()),
97 },
98 SiemError::Other(msg) => SiemApiError {
99 error_type: "other".to_string(),
100 message: msg.clone(),
101 status: None,
102 provider: None,
103 },
104 }
105 }
106}
107
108impl From<SiemApiError> for SiemError {
109 fn from(err: SiemApiError) -> Self {
110 match err.error_type.as_str() {
111 "auth" => SiemError::AuthError(err.message),
112 "connection" => SiemError::ConnectionError(err.message),
113 "api" => SiemError::ApiError {
114 status: err.status.unwrap_or(500),
115 message: err.message,
116 },
117 "not_found" => SiemError::NotFound(err.message),
118 "config" => SiemError::ConfigError(err.message),
119 "serialization" => SiemError::SerializationError(err.message),
120 "provider" => SiemError::ProviderError {
121 provider: err.provider.unwrap_or_default(),
122 message: err.message,
123 },
124 _ => SiemError::Other(err.message),
125 }
126 }
127}