1use reqwest::header::InvalidHeaderValue;
2use serde_urlencoded::ser::Error as UrlEncodedError;
3use thiserror::Error;
4use url::ParseError;
5
6use crate::{license::License, license_file::LicenseFileDataset, machine_file::MachineFileDataset};
7
8#[derive(Error, Debug)]
9pub enum Error {
10 #[error("Unexpected error: {0}")]
11 UnexpectedError(String),
12
13 #[error("Invalid URL")]
14 InvalidUrl,
15
16 #[error("System clock is out of sync")]
17 SystemClockUnsynced,
18
19 #[error("Decryption error: {0}")]
20 DecryptionError(String),
21
22 #[error("HTTP client error: {0}")]
23 HttpClient(#[from] reqwest::Error),
24
25 #[error("URL parse error: {0}")]
26 UrlParse(#[from] ParseError),
27
28 #[error("JSON error: {0}")]
29 JsonError(#[from] serde_json::Error),
30
31 #[error("Invalid header value: {0}")]
32 InvalidHeader(#[from] InvalidHeaderValue),
33
34 #[error("URL encoding error: {0}")]
35 UrlEncode(#[from] UrlEncodedError),
36
37 #[error("Rate limit exceeded")]
38 RateLimitExceeded {
39 window: String,
40 count: u32,
41 limit: u32,
42 remaining: u32,
43 reset: u64,
44 retry_after: u64,
45 },
46
47 #[error("License key is missing")]
48 LicenseKeyMissing,
49
50 #[error("License scheme is missing")]
51 LicenseSchemeMissing,
52
53 #[error("License scheme is not supported")]
54 LicenseSchemeNotSupported,
55
56 #[error("License is not signed")]
57 LicenseNotSigned,
58
59 #[error("License key is not genuine")]
60 LicenseKeyNotGenuine,
61
62 #[error("Public key is missing")]
63 PublicKeyMissing,
64
65 #[error("Public key is invalid")]
66 PublicKeyInvalid,
67
68 #[error("License scheme unsupported")]
69 LicenseSchemeUnsupported,
70
71 #[error("{0}")]
72 CertificateFileInvalid(String),
73
74 #[error("{0}")]
75 CertificateFileNotGenuine(String),
76
77 #[error("{0}")]
78 CertificateFileNotSupported(String),
79
80 #[error("Certificate file expired")]
81 CertificateFileExpired,
82
83 #[error("License file invalid: {0}")]
84 LicenseFileInvalid(String),
85
86 #[error("License file not genuine: {0}")]
87 LicenseFileNotGenuine(String),
88
89 #[error("License file not supported: {0}")]
90 LicenseFileNotSupported(String),
91
92 #[error("License file not encrypted")]
93 LicenseFileNotEncrypted,
94
95 #[error("License file expired")]
96 LicenseFileExpired(Box<LicenseFileDataset>),
97
98 #[error("Machine file invalid")]
99 MachineFileInvalid(String),
100
101 #[error("Machine file not genuine")]
102 MachineFileNotGenuine(String),
103
104 #[error("Machine file not supported")]
105 MachineFileNotSupported(String),
106
107 #[error("License file expired")]
108 MachineFileExpired(Box<MachineFileDataset>),
109
110 #[error("API error: {detail}")]
111 KeygenApiError {
112 code: String,
113 detail: String,
114 body: serde_json::Value,
115 },
116
117 #[error("Token not allowed")]
118 TokenNotAllowed { code: String, detail: String },
119
120 #[error("Token format invalid")]
121 TokenFormatInvalid { code: String, detail: String },
122
123 #[error("Token invalid")]
124 TokenInvalid { code: String, detail: String },
125
126 #[error("Token expired")]
127 TokenExpired { code: String, detail: String },
128
129 #[error("License suspended")]
130 LicenseSuspended { code: String, detail: String },
131
132 #[error("License expired")]
133 LicenseExpired { code: String, detail: String },
134
135 #[error("License not allowed")]
136 LicenseNotAllowed { code: String, detail: String },
137
138 #[error("License not activated")]
139 LicenseNotActivated {
140 code: String,
141 detail: String,
142 license: Box<License>,
143 },
144
145 #[error("License key invalid")]
146 LicenseKeyInvalid { code: String, detail: String },
147
148 #[error("License token invalid")]
149 LicenseTokenInvalid { code: String, detail: String },
150
151 #[error("License has too many machines")]
152 LicenseTooManyMachines { code: String, detail: String },
153
154 #[error("License has too many cores")]
155 LicenseTooManyCores { code: String, detail: String },
156
157 #[error("License has too many processes")]
158 LicenseTooManyProcesses { code: String, detail: String },
159
160 #[error("Machine already activated")]
161 MachineAlreadyActivated { code: String, detail: String },
162
163 #[error("Machine limit exceeded")]
164 MachineLimitExceeded { code: String, detail: String },
165
166 #[error("Machine no longer exists")]
167 MachineNotFound,
168
169 #[error("Process limit exceeded")]
170 ProcessLimitExceeded { code: String, detail: String },
171
172 #[error("Process no longer exists")]
173 ProcessNotFound,
174
175 #[error("Component conflict")]
176 ComponentConflict { code: String, detail: String },
177
178 #[error("Component already activated")]
179 ComponentAlreadyActivated { code: String, detail: String },
180
181 #[error("Component is not activated")]
182 ComponentNotActivated { code: String, detail: String },
183
184 #[error("Environment error")]
185 EnvironmentError { code: String, detail: String },
186
187 #[error("Heartbeat dead")]
188 HeartbeatDead { code: String, detail: String },
189
190 #[error("Heartbeat ping failed")]
191 HeartbeatPingFailed { code: String, detail: String },
192
193 #[error("Heartbeat is required")]
194 HeartbeatRequired { code: String, detail: String },
195
196 #[error("Validation fingerprint scope is missing")]
197 ValidationFingerprintMissing { code: String, detail: String },
198
199 #[error("Validation components scope is missing")]
200 ValidationComponentsMissing { code: String, detail: String },
201
202 #[error("Validation product scope is missing")]
203 ValidationProductMissing { code: String, detail: String },
204
205 #[error("Not found")]
206 NotFound { code: String, detail: String },
207
208 #[error("Keygen signature validation failed: {reason}")]
209 KeygenSignatureInvalid { reason: String },
210
211 #[error("Keygen signature missing")]
212 KeygenSignatureMissing,
213
214 #[error("Configuration missing")]
215 MissingConfiguration,
216}
217
218pub trait ErrorMeta {
219 fn code(&self) -> String;
220 fn detail(&self) -> String;
221}
222
223impl ErrorMeta for Error {
224 fn code(&self) -> String {
225 match self {
226 Error::KeygenApiError { code, .. }
227 | Error::TokenNotAllowed { code, .. }
228 | Error::TokenFormatInvalid { code, .. }
229 | Error::TokenInvalid { code, .. }
230 | Error::TokenExpired { code, .. }
231 | Error::LicenseSuspended { code, .. }
232 | Error::LicenseExpired { code, .. }
233 | Error::LicenseNotAllowed { code, .. }
234 | Error::LicenseNotActivated { code, .. }
235 | Error::LicenseKeyInvalid { code, .. }
236 | Error::LicenseTokenInvalid { code, .. }
237 | Error::LicenseTooManyMachines { code, .. }
238 | Error::LicenseTooManyCores { code, .. }
239 | Error::LicenseTooManyProcesses { code, .. }
240 | Error::MachineAlreadyActivated { code, .. }
241 | Error::MachineLimitExceeded { code, .. }
242 | Error::ProcessLimitExceeded { code, .. }
243 | Error::ComponentConflict { code, .. }
244 | Error::ComponentAlreadyActivated { code, .. }
245 | Error::ComponentNotActivated { code, .. }
246 | Error::EnvironmentError { code, .. }
247 | Error::HeartbeatDead { code, .. }
248 | Error::HeartbeatPingFailed { code, .. }
249 | Error::HeartbeatRequired { code, .. }
250 | Error::ValidationFingerprintMissing { code, .. }
251 | Error::ValidationComponentsMissing { code, .. }
252 | Error::ValidationProductMissing { code, .. }
253 | Error::NotFound { code, .. } => code.to_string(),
254 _ => "ERROR".to_string(),
255 }
256 }
257
258 fn detail(&self) -> String {
259 match self {
260 Error::KeygenApiError { detail, .. }
261 | Error::TokenNotAllowed { detail, .. }
262 | Error::TokenFormatInvalid { detail, .. }
263 | Error::TokenInvalid { detail, .. }
264 | Error::TokenExpired { detail, .. }
265 | Error::LicenseSuspended { detail, .. }
266 | Error::LicenseExpired { detail, .. }
267 | Error::LicenseNotAllowed { detail, .. }
268 | Error::LicenseNotActivated { detail, .. }
269 | Error::LicenseKeyInvalid { detail, .. }
270 | Error::LicenseTokenInvalid { detail, .. }
271 | Error::LicenseTooManyMachines { detail, .. }
272 | Error::LicenseTooManyCores { detail, .. }
273 | Error::LicenseTooManyProcesses { detail, .. }
274 | Error::MachineAlreadyActivated { detail, .. }
275 | Error::MachineLimitExceeded { detail, .. }
276 | Error::ProcessLimitExceeded { detail, .. }
277 | Error::ComponentConflict { detail, .. }
278 | Error::ComponentAlreadyActivated { detail, .. }
279 | Error::ComponentNotActivated { detail, .. }
280 | Error::EnvironmentError { detail, .. }
281 | Error::HeartbeatDead { detail, .. }
282 | Error::HeartbeatPingFailed { detail, .. }
283 | Error::HeartbeatRequired { detail, .. }
284 | Error::ValidationFingerprintMissing { detail, .. }
285 | Error::ValidationComponentsMissing { detail, .. }
286 | Error::ValidationProductMissing { detail, .. }
287 | Error::NotFound { detail, .. } => detail.to_string(),
288 _ => self.to_string(),
289 }
290 }
291}