1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
7pub enum ErrorCode {
8 InvalidCredentials,
9 InvalidApiKey,
10 InvalidInput,
11 NotFound,
12 Forbidden,
13 AccountSuspended,
14 RateLimited,
15 InternalError,
16}
17
18impl std::fmt::Display for ErrorCode {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 let s = match self {
21 Self::InvalidCredentials => "INVALID_CREDENTIALS",
22 Self::InvalidApiKey => "INVALID_API_KEY",
23 Self::InvalidInput => "INVALID_INPUT",
24 Self::NotFound => "NOT_FOUND",
25 Self::Forbidden => "FORBIDDEN",
26 Self::AccountSuspended => "ACCOUNT_SUSPENDED",
27 Self::RateLimited => "RATE_LIMITED",
28 Self::InternalError => "INTERNAL_ERROR",
29 };
30 write!(f, "{}", s)
31 }
32}
33
34#[derive(Debug, Error)]
36pub enum JwtError {
37 #[error("Invalid token format: {0}")]
38 InvalidFormat(String),
39
40 #[error("Token has expired")]
41 Expired,
42
43 #[error("Invalid signature")]
44 InvalidSignature,
45
46 #[error("Invalid claims: {0}")]
47 InvalidClaims(String),
48
49 #[error("Missing required claim: {0}")]
50 MissingClaim(String),
51
52 #[error("JWT library error: {0}")]
53 Library(#[from] jsonwebtoken::errors::Error),
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn test_error_code_serde() {
62 let code = ErrorCode::InvalidCredentials;
63 let json = serde_json::to_string(&code).unwrap();
64 assert_eq!(json, r#""INVALID_CREDENTIALS""#);
65
66 let parsed: ErrorCode = serde_json::from_str(&json).unwrap();
67 assert_eq!(parsed, code);
68 }
69}