rustack_sts_model/
error.rs1use std::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
10#[non_exhaustive]
11pub enum StsErrorCode {
12 #[default]
14 ExpiredTokenException,
15 IDPCommunicationErrorException,
17 IDPRejectedClaimException,
19 InternalError,
21 InvalidAction,
23 InvalidAuthorizationMessageException,
25 InvalidClientTokenIdException,
27 InvalidIdentityTokenException,
29 InvalidParameterValue,
31 MalformedPolicyDocumentException,
33 MissingAction,
35 PackedPolicyTooLargeException,
37 RegionDisabledException,
39}
40
41impl StsErrorCode {
42 #[must_use]
44 pub fn as_str(&self) -> &'static str {
45 match self {
46 Self::ExpiredTokenException => "ExpiredTokenException",
47 Self::IDPCommunicationErrorException => "IDPCommunicationError",
48 Self::IDPRejectedClaimException => "IDPRejectedClaim",
49 Self::InternalError => "InternalFailure",
50 Self::InvalidAction => "InvalidAction",
51 Self::InvalidAuthorizationMessageException => "InvalidAuthorizationMessageException",
52 Self::InvalidClientTokenIdException => "InvalidClientTokenId",
53 Self::InvalidIdentityTokenException => "InvalidIdentityToken",
54 Self::InvalidParameterValue => "InvalidParameterValue",
55 Self::MalformedPolicyDocumentException => "MalformedPolicyDocument",
56 Self::MissingAction => "MissingAction",
57 Self::PackedPolicyTooLargeException => "PackedPolicyTooLarge",
58 Self::RegionDisabledException => "RegionDisabledException",
59 }
60 }
61
62 #[must_use]
64 pub fn code(&self) -> &'static str {
65 self.as_str()
66 }
67
68 #[must_use]
70 pub fn default_status_code(&self) -> http::StatusCode {
71 self.status_code()
72 }
73
74 #[must_use]
76 pub fn status_code(&self) -> http::StatusCode {
77 match self {
78 Self::MissingAction
79 | Self::InvalidAction
80 | Self::MalformedPolicyDocumentException
81 | Self::PackedPolicyTooLargeException
82 | Self::InvalidIdentityTokenException
83 | Self::IDPRejectedClaimException
84 | Self::InvalidParameterValue
85 | Self::InvalidAuthorizationMessageException => http::StatusCode::BAD_REQUEST,
86
87 Self::ExpiredTokenException
88 | Self::InvalidClientTokenIdException
89 | Self::RegionDisabledException => http::StatusCode::FORBIDDEN,
90
91 Self::IDPCommunicationErrorException | Self::InternalError => {
92 http::StatusCode::INTERNAL_SERVER_ERROR
93 }
94 }
95 }
96
97 #[must_use]
99 pub fn fault(&self) -> &'static str {
100 match self {
101 Self::InternalError | Self::IDPCommunicationErrorException => "Receiver",
102 _ => "Sender",
103 }
104 }
105}
106
107impl fmt::Display for StsErrorCode {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 f.write_str(self.as_str())
110 }
111}
112
113#[derive(Debug)]
115pub struct StsError {
116 pub code: StsErrorCode,
118 pub message: String,
120 pub status_code: http::StatusCode,
122 pub source: Option<Box<dyn std::error::Error + Send + Sync>>,
124}
125
126impl fmt::Display for StsError {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 write!(f, "StsError({}): {}", self.code, self.message)
129 }
130}
131
132impl std::error::Error for StsError {
133 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
134 self.source
135 .as_ref()
136 .map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
137 }
138}
139
140impl StsError {
141 #[must_use]
143 pub fn new(code: StsErrorCode) -> Self {
144 Self {
145 status_code: code.default_status_code(),
146 message: code.as_str().to_owned(),
147 code,
148 source: None,
149 }
150 }
151
152 #[must_use]
154 pub fn with_message(code: StsErrorCode, message: impl Into<String>) -> Self {
155 Self {
156 status_code: code.default_status_code(),
157 message: message.into(),
158 code,
159 source: None,
160 }
161 }
162
163 #[must_use]
165 pub fn internal_error(message: impl Into<String>) -> Self {
166 Self::with_message(StsErrorCode::InternalError, message)
167 }
168
169 #[must_use]
171 pub fn missing_action() -> Self {
172 Self::with_message(
173 StsErrorCode::MissingAction,
174 "Missing required parameter: Action",
175 )
176 }
177
178 #[must_use]
180 pub fn unknown_operation(target: &str) -> Self {
181 Self::with_message(
182 StsErrorCode::InvalidAction,
183 format!("Operation {target} is not supported."),
184 )
185 }
186
187 #[must_use]
189 pub fn not_implemented(operation: &str) -> Self {
190 Self::with_message(
191 StsErrorCode::InternalError,
192 format!("Operation {operation} is not yet implemented"),
193 )
194 }
195
196 #[must_use]
198 pub fn invalid_parameter_value(message: impl Into<String>) -> Self {
199 Self::with_message(StsErrorCode::InvalidParameterValue, message)
200 }
201
202 #[must_use]
204 pub fn invalid_client_token_id(message: impl Into<String>) -> Self {
205 Self::with_message(StsErrorCode::InvalidClientTokenIdException, message)
206 }
207
208 #[must_use]
210 pub fn invalid_identity_token(message: impl Into<String>) -> Self {
211 Self::with_message(StsErrorCode::InvalidIdentityTokenException, message)
212 }
213
214 #[must_use]
216 pub fn malformed_policy(message: impl Into<String>) -> Self {
217 Self::with_message(StsErrorCode::MalformedPolicyDocumentException, message)
218 }
219
220 #[must_use]
222 pub fn invalid_action(message: impl Into<String>) -> Self {
223 Self::with_message(StsErrorCode::InvalidAction, message)
224 }
225}
226
227#[macro_export]
236macro_rules! sts_error {
237 ($code:ident) => {
238 $crate::error::StsError::new($crate::error::StsErrorCode::$code)
239 };
240 ($code:ident, $msg:expr) => {
241 $crate::error::StsError::with_message($crate::error::StsErrorCode::$code, $msg)
242 };
243}