1use axum::http::StatusCode;
2use serde::Serialize;
3
4#[derive(Debug, Clone, Serialize)]
6pub struct AwsError {
7 #[serde(skip)]
9 pub status: StatusCode,
10
11 pub code: String,
13
14 pub message: String,
16
17 pub error_type: ErrorType,
19}
20
21#[derive(Debug, Clone, Serialize)]
22pub enum ErrorType {
23 Sender,
24 Receiver,
25}
26
27impl AwsError {
28 pub fn not_found(code: impl Into<String>, message: impl Into<String>) -> Self {
29 Self {
30 status: StatusCode::NOT_FOUND,
31 code: code.into(),
32 message: message.into(),
33 error_type: ErrorType::Sender,
34 }
35 }
36
37 pub fn bad_request(code: impl Into<String>, message: impl Into<String>) -> Self {
38 Self {
39 status: StatusCode::BAD_REQUEST,
40 code: code.into(),
41 message: message.into(),
42 error_type: ErrorType::Sender,
43 }
44 }
45
46 pub fn conflict(code: impl Into<String>, message: impl Into<String>) -> Self {
47 Self {
48 status: StatusCode::CONFLICT,
49 code: code.into(),
50 message: message.into(),
51 error_type: ErrorType::Sender,
52 }
53 }
54
55 pub fn internal(message: impl Into<String>) -> Self {
56 Self {
57 status: StatusCode::INTERNAL_SERVER_ERROR,
58 code: "InternalServiceError".to_string(),
59 message: message.into(),
60 error_type: ErrorType::Receiver,
61 }
62 }
63
64 pub fn not_implemented(operation: &str) -> Self {
65 Self {
66 status: StatusCode::NOT_IMPLEMENTED,
67 code: "NotImplemented".to_string(),
68 message: format!("Operation '{operation}' is not yet implemented in AWSim"),
69 error_type: ErrorType::Receiver,
70 }
71 }
72
73 pub fn unknown_operation(operation: &str) -> Self {
74 Self {
75 status: StatusCode::BAD_REQUEST,
76 code: "UnknownOperationException".to_string(),
77 message: format!("Unknown operation: {operation}"),
78 error_type: ErrorType::Sender,
79 }
80 }
81
82 pub fn access_denied(message: impl Into<String>) -> Self {
83 Self {
84 status: StatusCode::FORBIDDEN,
85 code: "AccessDeniedException".to_string(),
86 message: message.into(),
87 error_type: ErrorType::Sender,
88 }
89 }
90
91 pub fn access_denied_for(action: &str, principal_arn: &str, resource: &str) -> Self {
92 Self {
93 status: StatusCode::FORBIDDEN,
94 code: "AccessDenied".to_string(),
95 message: format!(
96 "User: {principal_arn} is not authorized to perform: {action} on resource: {resource}"
97 ),
98 error_type: ErrorType::Sender,
99 }
100 }
101
102 pub fn validation(message: impl Into<String>) -> Self {
103 Self {
104 status: StatusCode::BAD_REQUEST,
105 code: "ValidationException".to_string(),
106 message: message.into(),
107 error_type: ErrorType::Sender,
108 }
109 }
110}
111
112impl std::fmt::Display for AwsError {
113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114 write!(f, "{}: {}", self.code, self.message)
115 }
116}
117
118impl std::error::Error for AwsError {}