pulseengine_mcp_security_middleware/
error.rs1use thiserror::Error;
4
5pub type SecurityResult<T> = Result<T, SecurityError>;
7
8#[derive(Debug, Error)]
10pub enum SecurityError {
11    #[error("Configuration error: {0}")]
13    Config(String),
14
15    #[error("Authentication failed: {0}")]
17    AuthenticationFailed(String),
18
19    #[error("Authorization failed: {0}")]
21    AuthorizationFailed(String),
22
23    #[error("Invalid token: {0}")]
25    InvalidToken(String),
26
27    #[error("Token expired")]
29    TokenExpired,
30
31    #[error("Missing authentication credentials")]
33    MissingAuth,
34
35    #[error("Rate limit exceeded")]
37    RateLimitExceeded,
38
39    #[error("Invalid API key")]
41    InvalidApiKey,
42
43    #[error("JWT validation error: {0}")]
45    JwtValidation(String),
46
47    #[error("Environment variable error: {0}")]
49    Environment(#[from] std::env::VarError),
50
51    #[error("IO error: {0}")]
53    Io(#[from] std::io::Error),
54
55    #[error("JSON error: {0}")]
57    Json(#[from] serde_json::Error),
58
59    #[error("Random generation error: {0}")]
61    Random(String),
62
63    #[error("Cryptographic error: {0}")]
65    Crypto(String),
66
67    #[error("HTTP error: {0}")]
69    Http(String),
70
71    #[error("Internal security error: {0}")]
73    Internal(String),
74}
75
76impl SecurityError {
77    pub fn config<S: Into<String>>(msg: S) -> Self {
79        Self::Config(msg.into())
80    }
81
82    pub fn auth<S: Into<String>>(msg: S) -> Self {
84        Self::AuthenticationFailed(msg.into())
85    }
86
87    pub fn authz<S: Into<String>>(msg: S) -> Self {
89        Self::AuthorizationFailed(msg.into())
90    }
91
92    pub fn invalid_token<S: Into<String>>(msg: S) -> Self {
94        Self::InvalidToken(msg.into())
95    }
96
97    pub fn jwt<S: Into<String>>(msg: S) -> Self {
99        Self::JwtValidation(msg.into())
100    }
101
102    pub fn random<S: Into<String>>(msg: S) -> Self {
104        Self::Random(msg.into())
105    }
106
107    pub fn crypto<S: Into<String>>(msg: S) -> Self {
109        Self::Crypto(msg.into())
110    }
111
112    pub fn http<S: Into<String>>(msg: S) -> Self {
114        Self::Http(msg.into())
115    }
116
117    pub fn internal<S: Into<String>>(msg: S) -> Self {
119        Self::Internal(msg.into())
120    }
121}
122
123impl From<jsonwebtoken::errors::Error> for SecurityError {
125    fn from(err: jsonwebtoken::errors::Error) -> Self {
126        use jsonwebtoken::errors::ErrorKind;
127
128        match err.kind() {
129            ErrorKind::ExpiredSignature => SecurityError::TokenExpired,
130            ErrorKind::InvalidToken => SecurityError::InvalidToken("Invalid JWT token".to_string()),
131            ErrorKind::InvalidSignature => {
132                SecurityError::InvalidToken("Invalid JWT signature".to_string())
133            }
134            ErrorKind::InvalidAudience => {
135                SecurityError::InvalidToken("Invalid JWT audience".to_string())
136            }
137            ErrorKind::InvalidIssuer => {
138                SecurityError::InvalidToken("Invalid JWT issuer".to_string())
139            }
140            _ => SecurityError::JwtValidation(err.to_string()),
141        }
142    }
143}