iam_rs/evaluation/
request.rs1use super::context::{Context, ContextValue};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39pub struct IAMRequest {
40 pub principal: String,
42
43 pub action: String,
45
46 pub resource: String,
48
49 pub context: Context,
51}
52
53impl IAMRequest {
54 pub fn new<S: Into<String>>(principal: S, action: S, resource: S) -> Self {
56 Self {
57 principal: principal.into(),
58 action: action.into(),
59 resource: resource.into(),
60 context: Context::new(),
61 }
62 }
63
64 pub fn new_with_context<S: Into<String>>(
66 principal: S,
67 action: S,
68 resource: S,
69 context: Context,
70 ) -> Self {
71 Self {
72 principal: principal.into(),
73 action: action.into(),
74 resource: resource.into(),
75 context,
76 }
77 }
78
79 pub fn with_context(mut self, other_context: Context) -> Self {
81 self.context.extend(other_context);
82 self
83 }
84
85 pub fn with_string_context<K: Into<String>, V: Into<String>>(
87 mut self,
88 key: K,
89 value: V,
90 ) -> Self {
91 self.context = self.context.with_string(key, value);
92 self
93 }
94
95 pub fn with_boolean_context<K: Into<String>>(mut self, key: K, value: bool) -> Self {
97 self.context = self.context.with_boolean(key, value);
98 self
99 }
100
101 pub fn with_number_context<K: Into<String>>(mut self, key: K, value: f64) -> Self {
103 self.context = self.context.with_number(key, value);
104 self
105 }
106
107 pub fn get_context(&self, key: &str) -> Option<&ContextValue> {
109 self.context.get(key)
110 }
111
112 pub fn has_context(&self, key: &str) -> bool {
114 self.context.has_key(key)
115 }
116
117 pub fn context_keys(&self) -> Vec<&String> {
119 self.context.keys()
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_parc_request_creation() {
129 let request = IAMRequest::new(
130 "AROA123456789EXAMPLE",
131 "iam:DeactivateMFADevice",
132 "arn:aws:iam::user/martha",
133 );
134
135 assert_eq!(request.principal, "AROA123456789EXAMPLE");
136 assert_eq!(request.action, "iam:DeactivateMFADevice");
137 assert_eq!(request.resource, "arn:aws:iam::user/martha");
138 }
139
140 #[test]
141 fn test_parc_request_with_context() {
142 let request = IAMRequest::new("principal", "action", "resource")
143 .with_string_context("string_key", "string_value")
144 .with_boolean_context("bool_key", true)
145 .with_number_context("number_key", 42.0);
146
147 assert_eq!(
148 request
149 .get_context("string_key")
150 .unwrap()
151 .as_string()
152 .unwrap(),
153 "string_value"
154 );
155 assert_eq!(
156 request
157 .get_context("bool_key")
158 .unwrap()
159 .as_boolean()
160 .unwrap(),
161 true
162 );
163 assert_eq!(
164 request
165 .get_context("number_key")
166 .unwrap()
167 .as_number()
168 .unwrap(),
169 42.0
170 );
171 }
172
173 #[test]
174 fn test_parc_request_context_utilities() {
175 let request = IAMRequest::new("principal", "action", "resource")
176 .with_string_context("key1", "value1")
177 .with_boolean_context("key2", false);
178
179 assert!(request.has_context("key1"));
180 assert!(request.has_context("key2"));
181 assert!(!request.has_context("key3"));
182
183 let keys = request.context_keys();
184 assert_eq!(keys.len(), 2);
185 assert!(keys.contains(&&"key1".to_string()));
186 assert!(keys.contains(&&"key2".to_string()));
187 }
188}