1#[macro_export]
17macro_rules! permissions {
18 ($($action:expr => $resource:expr),* $(,)?) => {
19 vec![$(
20 $crate::permission::Permission::new($action, $resource)
21 ),*]
22 };
23}
24
25#[macro_export]
43macro_rules! role_with_permissions {
44 (
45 name: $name:expr,
46 description: $desc:expr,
47 permissions: [
48 $($action:expr => $resource:expr),* $(,)?
49 ]
50 ) => {
51 {
52 let mut role = $crate::role::Role::new($name).with_description($desc);
53 $(
54 role = role.add_permission($crate::permission::Permission::new($action, $resource));
55 )*
56 role
57 }
58 };
59 (
60 name: $name:expr,
61 permissions: [
62 $($action:expr => $resource:expr),* $(,)?
63 ]
64 ) => {
65 {
66 let mut role = $crate::role::Role::new($name);
67 $(
68 role = role.add_permission($crate::permission::Permission::new($action, $resource));
69 )*
70 role
71 }
72 };
73}
74
75#[macro_export]
89macro_rules! subjects {
90 (
91 $(
92 $type:ident $id:expr => display_name: $name:expr
93 ),* $(,)?
94 ) => {
95 ($(
96 $crate::subject::Subject::$type($id).with_display_name($name)
97 ),*)
98 };
99 (
100 $(
101 $type:ident $id:expr
102 ),* $(,)?
103 ) => {
104 ($(
105 $crate::subject::Subject::$type($id)
106 ),*)
107 };
108}
109
110#[macro_export]
127macro_rules! conditional_permission {
128 (
129 action: $action:expr,
130 resource: $resource:expr,
131 condition: $condition:expr
132 ) => {
133 $crate::permission::Permission::with_condition($action, $resource, $condition)
134 };
135}
136
137#[macro_export]
150macro_rules! define_role {
151 (
152 $role_name:ident {
153 $(
154 $resource:ident: [$($action:literal),* $(,)?]
155 ),* $(,)?
156 }
157 ) => {
158 {
159 let mut builder = $crate::role::RoleBuilder::new().name(stringify!($role_name));
160
161 $(
162 let resource = stringify!($resource);
163 let actions = vec![$($action),*];
164 builder = builder.allow(resource, actions);
165 )*
166
167 builder.build().expect("Failed to build role")
168 }
169 };
170}
171
172#[macro_export]
192macro_rules! define_roles {
193 (
194 $(
195 $role_name:ident {
196 $(
197 $resource:ident: [$($action:literal),* $(,)?]
198 ),* $(,)?
199 }
200 ),* $(,)?
201 ) => {
202 {
203 use std::collections::HashMap;
204
205 let mut roles = HashMap::new();
206
207 $(
208 let mut builder = $crate::role::RoleBuilder::new().name(stringify!($role_name));
209
210 $(
211 let resource = stringify!($resource);
212 let actions = vec![$($action),*];
213 builder = builder.allow(resource, actions);
214 )*
215
216 let role = builder.build().expect("Failed to build role");
217 roles.insert(stringify!($role_name).to_string(), role);
218 )*
219
220 roles
221 }
222 };
223}
224
225#[macro_export]
235macro_rules! permission {
236 ($resource:literal, $action:literal) => {
237 $crate::permission::Permission::new($action, $resource)
238 };
239
240 ($resource:literal, [$($action:literal),* $(,)?]) => {
241 vec![$(
242 $crate::permission::Permission::new($action, $resource)
243 ),*]
244 };
245}
246
247#[cfg(test)]
248mod tests {
249 use std::collections::HashMap;
250
251 #[test]
252 fn test_permissions_macro() {
253 let perms = permissions![
254 "read" => "documents",
255 "write" => "documents",
256 "delete" => "documents"
257 ];
258
259 assert_eq!(perms.len(), 3);
260 assert_eq!(perms[0].action(), "read");
261 assert_eq!(perms[0].resource_type(), "documents");
262 }
263
264 #[test]
265 fn test_role_with_permissions_macro() {
266 let role = role_with_permissions! {
267 name: "editor",
268 description: "Content editor role",
269 permissions: [
270 "read" => "documents",
271 "write" => "documents"
272 ]
273 };
274
275 assert_eq!(role.name(), "editor");
276 assert_eq!(role.description(), Some("Content editor role"));
277 assert_eq!(role.permissions().permissions().len(), 2);
278 }
279
280 #[test]
281 fn test_subjects_macro() {
282 let (admin, service) = subjects! {
283 user "admin_user" => display_name: "Administrator",
284 service "api_service" => display_name: "API Service"
285 };
286
287 assert_eq!(admin.id(), "admin_user");
288 assert_eq!(admin.display_name(), Some("Administrator"));
289 assert_eq!(service.id(), "api_service");
290 assert_eq!(service.display_name(), Some("API Service"));
291 }
292
293 #[test]
294 fn test_conditional_permission_macro() {
295 let perm = conditional_permission! {
296 action: "access",
297 resource: "secure_area",
298 condition: |context: &HashMap<String, String>| {
299 context.get("clearance") == Some(&"top_secret".to_string())
300 }
301 };
302
303 assert_eq!(perm.action(), "access");
304 assert_eq!(perm.resource_type(), "secure_area");
305
306 let mut valid_context = HashMap::new();
307 valid_context.insert("clearance".to_string(), "top_secret".to_string());
308 assert!(perm.is_granted("access", "secure_area", &valid_context));
309
310 let invalid_context = HashMap::new();
311 assert!(!perm.is_granted("access", "secure_area", &invalid_context));
312 }
313
314 #[test]
315 fn test_define_role_macro() {
316 let role = define_role!(admin {
317 users: ["create", "read", "update", "delete"],
318 roles: ["assign", "remove"]
319 });
320
321 assert_eq!(role.name(), "admin");
322 assert_eq!(role.permissions().len(), 6); }
324
325 #[test]
326 fn test_permission_macro() {
327 let single_perm = permission!("users", "read");
328 assert_eq!(single_perm.action(), "read");
329 assert_eq!(single_perm.resource_type(), "users");
330
331 let multi_perms = permission!("posts", ["create", "update", "delete"]);
332 assert_eq!(multi_perms.len(), 3);
333 }
334
335 #[test]
336 fn test_define_roles_macro() {
337 let roles = define_roles! {
338 admin {
339 users: ["create", "read", "update", "delete"],
340 roles: ["assign"]
341 },
342
343 user {
344 profile: ["read", "update"],
345 posts: ["create"]
346 }
347 };
348
349 assert_eq!(roles.len(), 2);
350 assert!(roles.contains_key("admin"));
351 assert!(roles.contains_key("user"));
352
353 let admin_role = &roles["admin"];
354 assert_eq!(admin_role.name(), "admin");
355 assert_eq!(admin_role.permissions().len(), 5); }
357}