1use crate::{MgmtApi, Result};
2
3use async_trait::async_trait;
4
5use std::collections::HashSet;
6
7#[async_trait]
8pub trait RbacApi: MgmtApi {
9 async fn add_permission_for_user(
10 &mut self,
11 user: &str,
12 permission: Vec<String>,
13 ) -> Result<bool>;
14 async fn add_permissions_for_user(
15 &mut self,
16 user: &str,
17 permissions: Vec<Vec<String>>,
18 ) -> Result<bool>;
19 async fn add_role_for_user(
20 &mut self,
21 user: &str,
22 role: &str,
23 domain: Option<&str>,
24 ) -> Result<bool>;
25 async fn add_roles_for_user(
26 &mut self,
27 user: &str,
28 roles: Vec<String>,
29 domain: Option<&str>,
30 ) -> Result<bool>;
31 async fn delete_role_for_user(
32 &mut self,
33 user: &str,
34 role: &str,
35 domain: Option<&str>,
36 ) -> Result<bool>;
37 async fn delete_roles_for_user(
38 &mut self,
39 user: &str,
40 domain: Option<&str>,
41 ) -> Result<bool>;
42 async fn delete_user(&mut self, name: &str) -> Result<bool>;
43 async fn delete_role(&mut self, name: &str) -> Result<bool>;
44
45 async fn delete_permission(
46 &mut self,
47 permission: Vec<String>,
48 ) -> Result<bool> {
49 self.remove_filtered_policy(1, permission).await
50 }
51 async fn delete_permission_for_user(
52 &mut self,
53 user: &str,
54 permission: Vec<String>,
55 ) -> Result<bool>;
56
57 async fn delete_permissions_for_user(
58 &mut self,
59 user: &str,
60 ) -> Result<bool> {
61 self.remove_filtered_policy(
62 0,
63 [user].iter().map(|s| (*s).to_string()).collect(),
64 )
65 .await
66 }
67
68 fn get_roles_for_user(
69 &self,
70 name: &str,
71 domain: Option<&str>,
72 ) -> Vec<String>;
73 fn get_users_for_role(
74 &self,
75 name: &str,
76 domain: Option<&str>,
77 ) -> Vec<String>;
78 fn has_role_for_user(
79 &self,
80 name: &str,
81 role: &str,
82 domain: Option<&str>,
83 ) -> bool;
84 fn get_permissions_for_user(
85 &self,
86 user: &str,
87 domain: Option<&str>,
88 ) -> Vec<Vec<String>>;
89 fn has_permission_for_user(
90 &self,
91 user: &str,
92 permission: Vec<String>,
93 ) -> bool;
94 fn get_implicit_roles_for_user(
95 &self,
96 name: &str,
97 domain: Option<&str>,
98 ) -> Vec<String>;
99 fn get_implicit_permissions_for_user(
100 &self,
101 name: &str,
102 domain: Option<&str>,
103 ) -> Vec<Vec<String>>;
104 async fn get_implicit_users_for_permission(
105 &self,
106 permission: Vec<String>,
107 ) -> Vec<String>;
108}
109
110#[async_trait]
111impl<T> RbacApi for T
112where
113 T: MgmtApi,
114{
115 async fn add_permission_for_user(
116 &mut self,
117 user: &str,
118 permission: Vec<String>,
119 ) -> Result<bool> {
120 let mut perm = permission;
121 perm.insert(0, user.to_string());
122 self.add_policy(perm).await
123 }
124
125 async fn add_permissions_for_user(
126 &mut self,
127 user: &str,
128 permissions: Vec<Vec<String>>,
129 ) -> Result<bool> {
130 let perms = permissions
131 .into_iter()
132 .map(|mut p| {
133 p.insert(0, user.to_string());
134 p
135 })
136 .collect();
137 self.add_policies(perms).await
138 }
139
140 async fn add_role_for_user(
141 &mut self,
142 user: &str,
143 role: &str,
144 domain: Option<&str>,
145 ) -> Result<bool> {
146 self.add_grouping_policy(if let Some(domain) = domain {
147 [user, role, domain]
148 .iter()
149 .map(|s| (*s).to_string())
150 .collect()
151 } else {
152 [user, role].iter().map(|s| (*s).to_string()).collect()
153 })
154 .await
155 }
156
157 async fn add_roles_for_user(
158 &mut self,
159 user: &str,
160 roles: Vec<String>,
161 domain: Option<&str>,
162 ) -> Result<bool> {
163 self.add_grouping_policies(
164 roles
165 .into_iter()
166 .map(|role| {
167 if let Some(domain) = domain {
168 vec![user.to_string(), role, domain.to_string()]
169 } else {
170 vec![user.to_string(), role]
171 }
172 })
173 .collect(),
174 )
175 .await
176 }
177
178 async fn delete_role_for_user(
179 &mut self,
180 user: &str,
181 role: &str,
182 domain: Option<&str>,
183 ) -> Result<bool> {
184 self.remove_grouping_policy(if let Some(domain) = domain {
185 [user, role, domain]
186 .iter()
187 .map(|s| (*s).to_string())
188 .collect()
189 } else {
190 [user, role].iter().map(|s| (*s).to_string()).collect()
191 })
192 .await
193 }
194
195 async fn delete_roles_for_user(
196 &mut self,
197 user: &str,
198 domain: Option<&str>,
199 ) -> Result<bool> {
200 self.remove_filtered_grouping_policy(
201 0,
202 if let Some(domain) = domain {
203 [user, "", domain]
204 .iter()
205 .map(|s| (*s).to_string())
206 .collect()
207 } else {
208 [user].iter().map(|s| (*s).to_string()).collect()
209 },
210 )
211 .await
212 }
213
214 fn get_roles_for_user(
215 &self,
216 name: &str,
217 domain: Option<&str>,
218 ) -> Vec<String> {
219 let mut roles = vec![];
220 if let Some(t1) = self.get_model().get_model().get("g") {
221 if let Some(t2) = t1.get("g") {
222 roles = t2.rm.read().get_roles(name, domain);
223 }
224 }
225
226 roles
227 }
228
229 fn get_users_for_role(
230 &self,
231 name: &str,
232 domain: Option<&str>,
233 ) -> Vec<String> {
234 if let Some(t1) = self.get_model().get_model().get("g") {
235 if let Some(t2) = t1.get("g") {
236 return t2.rm.read().get_users(name, domain);
237 }
238 }
239 vec![]
240 }
241
242 fn has_role_for_user(
243 &self,
244 name: &str,
245 role: &str,
246 domain: Option<&str>,
247 ) -> bool {
248 let roles = self.get_roles_for_user(name, domain);
249 let mut has_role = false;
250 for r in roles {
251 if r == role {
252 has_role = true;
253 break;
254 }
255 }
256 has_role
257 }
258
259 async fn delete_user(&mut self, name: &str) -> Result<bool> {
260 let res1 = self
261 .remove_filtered_grouping_policy(0, vec![name.to_string()])
262 .await?;
263 let res2 = self
264 .remove_filtered_policy(0, vec![name.to_string()])
265 .await?;
266 Ok(res1 || res2)
267 }
268
269 async fn delete_role(&mut self, name: &str) -> Result<bool> {
270 let res1 = self
271 .remove_filtered_grouping_policy(1, vec![name.to_string()])
272 .await?;
273 let res2 = self
274 .remove_filtered_policy(0, vec![name.to_string()])
275 .await?;
276 Ok(res1 || res2)
277 }
278
279 async fn delete_permission_for_user(
280 &mut self,
281 user: &str,
282 permission: Vec<String>,
283 ) -> Result<bool> {
284 let mut permission = permission;
285 permission.insert(0, user.to_string());
286 self.remove_policy(permission).await
287 }
288
289 fn get_permissions_for_user(
290 &self,
291 user: &str,
292 domain: Option<&str>,
293 ) -> Vec<Vec<String>> {
294 self.get_filtered_policy(0, {
295 if let Some(domain) = domain {
296 [user, domain].iter().map(|s| (*s).to_string()).collect()
297 } else {
298 [user].iter().map(|s| (*s).to_string()).collect()
299 }
300 })
301 }
302
303 fn has_permission_for_user(
304 &self,
305 user: &str,
306 permission: Vec<String>,
307 ) -> bool {
308 let mut permission = permission;
309 permission.insert(0, user.to_string());
310 self.has_policy(permission)
311 }
312
313 fn get_implicit_roles_for_user(
314 &self,
315 name: &str,
316 domain: Option<&str>,
317 ) -> Vec<String> {
318 let mut res: HashSet<String> = HashSet::new();
319 let mut q: Vec<String> = vec![name.to_owned()];
320 while !q.is_empty() {
321 let name = q.swap_remove(0);
322 let roles = self.get_role_manager().read().get_roles(&name, domain);
323 for r in roles.into_iter() {
324 if res.insert(r.to_owned()) {
325 q.push(r);
326 }
327 }
328 }
329 res.into_iter().collect()
330 }
331
332 fn get_implicit_permissions_for_user(
333 &self,
334 user: &str,
335 domain: Option<&str>,
336 ) -> Vec<Vec<String>> {
337 let mut roles = self.get_implicit_roles_for_user(user, domain);
338 roles.insert(0, user.to_owned());
339
340 let mut res = vec![];
341
342 for role in roles.iter() {
343 let permissions = self.get_permissions_for_user(role, domain);
344 res.extend(permissions);
345 }
346 res
347 }
348
349 async fn get_implicit_users_for_permission(
350 &self,
351 permission: Vec<String>,
352 ) -> Vec<String> {
353 let mut subjects = self.get_all_subjects();
354 let roles = self.get_all_roles();
355
356 subjects.extend(roles.iter().flat_map(|role| {
357 self.get_role_manager().read().get_users(role, None)
358 }));
359
360 let users: Vec<String> = subjects
361 .into_iter()
362 .filter(|subject| !roles.contains(subject))
363 .collect();
364
365 let mut res: Vec<String> = vec![];
366 for user in users.iter() {
367 let mut req = permission.clone();
368 req.insert(0, user.to_string());
369 if let Ok(r) = self.enforce(req) {
370 if r && !res.contains(user) {
371 res.push(user.to_owned());
372 }
373 }
374 }
375 res
376 }
377}
378
379#[cfg(test)]
380mod tests {
381 use crate::prelude::*;
382
383 fn sort_unstable<T: Ord>(mut v: Vec<T>) -> Vec<T> {
384 v.sort_unstable();
385 v
386 }
387
388 #[cfg(not(target_arch = "wasm32"))]
389 #[cfg_attr(
390 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
391 async_std::test
392 )]
393 #[cfg_attr(
394 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
395 tokio::test
396 )]
397 async fn test_role_api() {
398 let m = DefaultModel::from_file("examples/rbac_model.conf")
399 .await
400 .unwrap();
401
402 let adapter = FileAdapter::new("examples/rbac_policy.csv");
403 let mut e = Enforcer::new(m, adapter).await.unwrap();
404
405 assert_eq!(vec!["data2_admin"], e.get_roles_for_user("alice", None));
406 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None));
407 assert_eq!(
408 vec![String::new(); 0],
409 e.get_roles_for_user("data2_admin", None)
410 );
411 assert_eq!(
412 vec![String::new(); 0],
413 e.get_roles_for_user("non_exists", None)
414 );
415
416 assert_eq!(false, e.has_role_for_user("alice", "data1_admin", None));
417 assert_eq!(true, e.has_role_for_user("alice", "data2_admin", None));
418
419 e.add_role_for_user("alice", "data1_admin", None)
420 .await
421 .unwrap();
422 assert_eq!(
423 vec!["data1_admin", "data2_admin"],
424 sort_unstable(e.get_roles_for_user("alice", None))
425 );
426 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None));
427 assert_eq!(
428 vec![String::new(); 0],
429 e.get_roles_for_user("data2_admin", None)
430 );
431
432 e.delete_role_for_user("alice", "data1_admin", None)
433 .await
434 .unwrap();
435 assert_eq!(vec!["data2_admin"], e.get_roles_for_user("alice", None));
436 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None));
437 assert_eq!(
438 vec![String::new(); 0],
439 e.get_roles_for_user("data2_admin", None)
440 );
441
442 e.delete_roles_for_user("alice", None).await.unwrap();
443 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None));
444 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None));
445 assert_eq!(
446 vec![String::new(); 0],
447 e.get_roles_for_user("data2_admin", None)
448 );
449
450 e.add_roles_for_user(
451 "bob",
452 vec!["data1_admin", "data2_admin"]
453 .iter()
454 .map(|s| s.to_string())
455 .collect(),
456 None,
457 )
458 .await
459 .unwrap();
460 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None));
461 assert_eq!(
462 vec!["data1_admin", "data2_admin"],
463 sort_unstable(e.get_roles_for_user("bob", None))
464 );
465
466 e.delete_roles_for_user("bob", None).await.unwrap();
467 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None));
468 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None));
469
470 e.add_role_for_user("alice", "data1_admin", None)
471 .await
472 .unwrap();
473 e.delete_user("alice").await.unwrap();
474 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None));
475 assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None));
476 assert_eq!(
477 vec![String::new(); 0],
478 e.get_roles_for_user("data2_admin", None)
479 );
480
481 e.add_role_for_user("alice", "data2_admin", None)
482 .await
483 .unwrap();
484 assert_eq!(false, e.enforce(("alice", "data1", "read")).unwrap());
485 assert_eq!(false, e.enforce(("alice", "data1", "write")).unwrap());
486 assert_eq!(true, e.enforce(("alice", "data2", "read")).unwrap());
487 assert_eq!(true, e.enforce(("alice", "data2", "write")).unwrap());
488 assert_eq!(false, e.enforce(("bob", "data1", "read")).unwrap());
489 assert_eq!(false, e.enforce(("bob", "data1", "write")).unwrap());
490 assert_eq!(false, e.enforce(("bob", "data2", "read")).unwrap());
491 assert_eq!(true, e.enforce(("bob", "data2", "write")).unwrap());
492
493 e.delete_role("data2_admin").await.unwrap();
494 assert_eq!(false, e.enforce(("alice", "data1", "read")).unwrap());
495 assert_eq!(false, e.enforce(("alice", "data1", "write")).unwrap());
496 assert_eq!(false, e.enforce(("alice", "data2", "read")).unwrap());
497 assert_eq!(false, e.enforce(("alice", "data2", "write")).unwrap());
498 assert_eq!(false, e.enforce(("bob", "data1", "read")).unwrap());
499 assert_eq!(false, e.enforce(("bob", "data1", "write")).unwrap());
500 assert_eq!(false, e.enforce(("bob", "data2", "read")).unwrap());
501 assert_eq!(true, e.enforce(("bob", "data2", "write")).unwrap());
502 }
503
504 #[cfg(not(target_arch = "wasm32"))]
505 #[cfg_attr(
506 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
507 async_std::test
508 )]
509 #[cfg_attr(
510 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
511 tokio::test
512 )]
513 async fn test_role_api_threads() {
514 use parking_lot::RwLock;
515
516 use std::sync::Arc;
517 use std::thread;
518
519 #[cfg(feature = "runtime-async-std")]
520 use async_std::task;
521
522 let m = DefaultModel::from_file("examples/rbac_model.conf")
523 .await
524 .unwrap();
525
526 let adapter = FileAdapter::new("examples/rbac_policy.csv");
527 let e = Arc::new(RwLock::new(Enforcer::new(m, adapter).await.unwrap()));
528 let ee = e.clone();
529
530 assert_eq!(
531 vec!["data2_admin"],
532 e.write().get_roles_for_user("alice", None)
533 );
534 assert_eq!(
535 vec![String::new(); 0],
536 e.write().get_roles_for_user("bob", None)
537 );
538 assert_eq!(
539 vec![String::new(); 0],
540 e.write().get_roles_for_user("data2_admin", None)
541 );
542 assert_eq!(
543 vec![String::new(); 0],
544 e.write().get_roles_for_user("non_exists", None)
545 );
546
547 assert_eq!(
548 false,
549 e.write().has_role_for_user("alice", "data1_admin", None)
550 );
551 assert_eq!(
552 true,
553 e.write().has_role_for_user("alice", "data2_admin", None)
554 );
555
556 thread::spawn(move || {
557 #[cfg(feature = "runtime-async-std")]
558 {
559 task::block_on(async move {
560 ee.write()
561 .add_role_for_user("alice", "data1_admin", None)
562 .await
563 .unwrap();
564
565 assert_eq!(
566 vec!["data1_admin", "data2_admin"],
567 sort_unstable(
568 ee.write().get_roles_for_user("alice", None)
569 )
570 );
571 assert_eq!(
572 vec![String::new(); 0],
573 ee.write().get_roles_for_user("bob", None)
574 );
575 assert_eq!(
576 vec![String::new(); 0],
577 ee.write().get_roles_for_user("data2_admin", None)
578 );
579
580 ee.write()
581 .add_roles_for_user(
582 "bob",
583 vec!["data2_admin"]
584 .iter()
585 .map(|s| s.to_string())
586 .collect(),
587 None,
588 )
589 .await
590 .unwrap();
591
592 assert_eq!(
593 vec!["data1_admin", "data2_admin"],
594 sort_unstable(
595 ee.write().get_roles_for_user("alice", None)
596 )
597 );
598 assert_eq!(
599 vec!["data2_admin"],
600 ee.write().get_roles_for_user("bob", None)
601 );
602 assert_eq!(
603 vec![String::new(); 0],
604 ee.write().get_roles_for_user("data2_admin", None)
605 );
606 });
607 }
608
609 #[cfg(feature = "runtime-tokio")]
610 {
611 tokio::runtime::Builder::new_multi_thread()
612 .enable_all()
613 .build()
614 .unwrap()
615 .block_on(async move {
616 ee.write()
617 .add_role_for_user("alice", "data1_admin", None)
618 .await
619 .unwrap();
620
621 assert_eq!(
622 vec!["data1_admin", "data2_admin"],
623 sort_unstable(
624 ee.write().get_roles_for_user("alice", None)
625 )
626 );
627 assert_eq!(
628 vec![String::new(); 0],
629 ee.write().get_roles_for_user("bob", None)
630 );
631 assert_eq!(
632 vec![String::new(); 0],
633 ee.write().get_roles_for_user("data2_admin", None)
634 );
635
636 ee.write()
637 .add_roles_for_user(
638 "bob",
639 vec!["data2_admin".to_owned()],
640 None,
641 )
642 .await
643 .unwrap();
644
645 assert_eq!(
646 vec!["data1_admin", "data2_admin"],
647 sort_unstable(
648 ee.write().get_roles_for_user("alice", None)
649 )
650 );
651 assert_eq!(
652 vec!["data2_admin"],
653 ee.write().get_roles_for_user("bob", None)
654 );
655 assert_eq!(
656 vec![String::new(); 0],
657 ee.write().get_roles_for_user("data2_admin", None)
658 );
659 });
660 }
661 })
662 .join()
663 .unwrap();
664
665 e.write()
666 .delete_role_for_user("alice", "data1_admin", None)
667 .await
668 .unwrap();
669 e.write().delete_roles_for_user("bob", None).await.unwrap();
670 assert_eq!(
671 vec!["data2_admin"],
672 e.write().get_roles_for_user("alice", None)
673 );
674 assert_eq!(
675 vec![String::new(); 0],
676 e.write().get_roles_for_user("bob", None)
677 );
678 assert_eq!(
679 vec![String::new(); 0],
680 e.write().get_roles_for_user("data2_admin", None)
681 );
682
683 e.write()
684 .delete_roles_for_user("alice", None)
685 .await
686 .unwrap();
687 assert_eq!(
688 vec![String::new(); 0],
689 e.write().get_roles_for_user("alice", None)
690 );
691 assert_eq!(
692 vec![String::new(); 0],
693 e.write().get_roles_for_user("bob", None)
694 );
695 assert_eq!(
696 vec![String::new(); 0],
697 e.write().get_roles_for_user("data2_admin", None)
698 );
699
700 e.write()
701 .add_role_for_user("alice", "data1_admin", None)
702 .await
703 .unwrap();
704 e.write().delete_user("alice").await.unwrap();
705 assert_eq!(
706 vec![String::new(); 0],
707 e.write().get_roles_for_user("alice", None)
708 );
709 assert_eq!(
710 vec![String::new(); 0],
711 e.write().get_roles_for_user("bob", None)
712 );
713 assert_eq!(
714 vec![String::new(); 0],
715 e.write().get_roles_for_user("data2_admin", None)
716 );
717
718 e.write()
719 .add_role_for_user("alice", "data2_admin", None)
720 .await
721 .unwrap();
722 assert_eq!(
723 false,
724 e.write().enforce(("alice", "data1", "read")).unwrap()
725 );
726 assert_eq!(
727 false,
728 e.write().enforce(("alice", "data1", "write")).unwrap()
729 );
730 assert_eq!(
731 true,
732 e.write().enforce(("alice", "data2", "read")).unwrap()
733 );
734 assert_eq!(
735 true,
736 e.write().enforce(("alice", "data2", "write")).unwrap()
737 );
738 assert_eq!(false, e.write().enforce(("bob", "data1", "read")).unwrap());
739 assert_eq!(
740 false,
741 e.write().enforce(("bob", "data1", "write")).unwrap()
742 );
743 assert_eq!(false, e.write().enforce(("bob", "data2", "read")).unwrap());
744 assert_eq!(true, e.write().enforce(("bob", "data2", "write")).unwrap());
745
746 e.write().delete_role("data2_admin").await.unwrap();
747 assert_eq!(
748 false,
749 e.write().enforce(("alice", "data1", "read")).unwrap()
750 );
751 assert_eq!(
752 false,
753 e.write().enforce(("alice", "data1", "write")).unwrap()
754 );
755 assert_eq!(
756 false,
757 e.write().enforce(("alice", "data2", "read")).unwrap()
758 );
759 assert_eq!(
760 false,
761 e.write().enforce(("alice", "data2", "write")).unwrap()
762 );
763 assert_eq!(false, e.write().enforce(("bob", "data1", "read")).unwrap());
764 assert_eq!(
765 false,
766 e.write().enforce(("bob", "data1", "write")).unwrap()
767 );
768 assert_eq!(false, e.write().enforce(("bob", "data2", "read")).unwrap());
769 assert_eq!(true, e.write().enforce(("bob", "data2", "write")).unwrap());
770 }
771
772 #[cfg(not(target_arch = "wasm32"))]
773 #[cfg_attr(
774 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
775 async_std::test
776 )]
777 #[cfg_attr(
778 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
779 tokio::test
780 )]
781 async fn test_permission_api() {
782 let m = DefaultModel::from_file(
783 "examples/basic_without_resources_model.conf",
784 )
785 .await
786 .unwrap();
787
788 let adapter =
789 FileAdapter::new("examples/basic_without_resources_policy.csv");
790 let mut e = Enforcer::new(m, adapter).await.unwrap();
791
792 assert_eq!(true, e.enforce(("alice", "read")).unwrap());
793 assert_eq!(false, e.enforce(("alice", "write")).unwrap());
794 assert_eq!(false, e.enforce(("bob", "read")).unwrap());
795 assert_eq!(true, e.enforce(("bob", "write")).unwrap());
796
797 assert_eq!(
798 vec![vec!["alice", "read"]],
799 e.get_permissions_for_user("alice", None)
800 );
801 assert_eq!(
802 vec![vec!["bob", "write"]],
803 e.get_permissions_for_user("bob", None)
804 );
805
806 assert_eq!(
807 true,
808 e.has_permission_for_user(
809 "alice",
810 vec!["read"].iter().map(|s| s.to_string()).collect()
811 )
812 );
813 assert_eq!(
814 false,
815 e.has_permission_for_user(
816 "alice",
817 vec!["write"].iter().map(|s| s.to_string()).collect()
818 )
819 );
820 assert_eq!(
821 false,
822 e.has_permission_for_user(
823 "bob",
824 vec!["read"].iter().map(|s| s.to_string()).collect()
825 )
826 );
827 assert_eq!(
828 true,
829 e.has_permission_for_user(
830 "bob",
831 vec!["write"].iter().map(|s| s.to_string()).collect()
832 )
833 );
834
835 e.delete_permission(
836 vec!["read"].iter().map(|s| s.to_string()).collect(),
837 )
838 .await
839 .unwrap();
840
841 assert_eq!(false, e.enforce(("alice", "read")).unwrap());
842 assert_eq!(false, e.enforce(("alice", "write")).unwrap());
843 assert_eq!(false, e.enforce(("bob", "read")).unwrap());
844 assert_eq!(true, e.enforce(("bob", "write")).unwrap());
845
846 e.add_permission_for_user(
847 "bob",
848 vec!["read"].iter().map(|s| s.to_string()).collect(),
849 )
850 .await
851 .unwrap();
852 e.add_permissions_for_user(
853 "eve",
854 vec![
855 vec!["read"].iter().map(|s| s.to_string()).collect(),
856 vec!["write"].iter().map(|s| s.to_string()).collect(),
857 ],
858 )
859 .await
860 .unwrap();
861
862 assert_eq!(false, e.enforce(("alice", "read")).unwrap());
863 assert_eq!(false, e.enforce(("alice", "write")).unwrap());
864 assert_eq!(true, e.enforce(("bob", "read")).unwrap());
865 assert_eq!(true, e.enforce(("bob", "write")).unwrap());
866 assert_eq!(true, e.enforce(("eve", "read")).unwrap());
867 assert_eq!(true, e.enforce(("eve", "write")).unwrap());
868
869 e.delete_permission_for_user(
870 "bob",
871 vec!["read"].iter().map(|s| s.to_string()).collect(),
872 )
873 .await
874 .unwrap();
875
876 assert_eq!(false, e.enforce(("alice", "read")).unwrap());
877 assert_eq!(false, e.enforce(("alice", "write")).unwrap());
878 assert_eq!(false, e.enforce(("bob", "read")).unwrap());
879 assert_eq!(true, e.enforce(("bob", "write")).unwrap());
880 assert_eq!(true, e.enforce(("eve", "read")).unwrap());
881 assert_eq!(true, e.enforce(("eve", "write")).unwrap());
882
883 e.delete_permissions_for_user("bob").await.unwrap();
884 e.delete_permissions_for_user("eve").await.unwrap();
885
886 assert_eq!(false, e.enforce(("alice", "read")).unwrap());
887 assert_eq!(false, e.enforce(("alice", "write")).unwrap());
888 assert_eq!(false, e.enforce(("bob", "read")).unwrap());
889 assert_eq!(false, e.enforce(("bob", "write")).unwrap());
890 assert_eq!(false, e.enforce(("eve", "read")).unwrap());
891 assert_eq!(false, e.enforce(("eve", "write")).unwrap());
892 }
893
894 #[cfg(not(target_arch = "wasm32"))]
895 #[cfg_attr(
896 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
897 async_std::test
898 )]
899 #[cfg_attr(
900 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
901 tokio::test
902 )]
903 async fn test_implicit_role_api() {
904 let m = DefaultModel::from_file("examples/rbac_model.conf")
905 .await
906 .unwrap();
907
908 let adapter =
909 FileAdapter::new("examples/rbac_with_hierarchy_policy.csv");
910 let e = Enforcer::new(m, adapter).await.unwrap();
911
912 assert_eq!(
913 vec![vec!["alice", "data1", "read"]],
914 e.get_permissions_for_user("alice", None)
915 );
916 assert_eq!(
917 vec![vec!["bob", "data2", "write"]],
918 e.get_permissions_for_user("bob", None)
919 );
920
921 assert_eq!(
922 vec!["admin", "data1_admin", "data2_admin"],
923 sort_unstable(e.get_implicit_roles_for_user("alice", None))
924 );
925 assert_eq!(
926 vec![String::new(); 0],
927 e.get_implicit_roles_for_user("bob", None)
928 );
929 }
930
931 #[cfg(not(target_arch = "wasm32"))]
932 #[cfg_attr(
933 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
934 async_std::test
935 )]
936 #[cfg_attr(
937 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
938 tokio::test
939 )]
940 async fn test_implicit_permission_api() {
941 let m = DefaultModel::from_file("examples/rbac_model.conf")
942 .await
943 .unwrap();
944
945 let adapter =
946 FileAdapter::new("examples/rbac_with_hierarchy_policy.csv");
947 let e = Enforcer::new(m, adapter).await.unwrap();
948
949 assert_eq!(
950 vec![vec!["alice", "data1", "read"]],
951 e.get_permissions_for_user("alice", None)
952 );
953 assert_eq!(
954 vec![vec!["bob", "data2", "write"]],
955 e.get_permissions_for_user("bob", None)
956 );
957
958 assert_eq!(
959 vec![
960 vec!["alice", "data1", "read"],
961 vec!["data1_admin", "data1", "read"],
962 vec!["data1_admin", "data1", "write"],
963 vec!["data2_admin", "data2", "read"],
964 vec!["data2_admin", "data2", "write"],
965 ],
966 sort_unstable(e.get_implicit_permissions_for_user("alice", None))
967 );
968 assert_eq!(
969 vec![vec!["bob", "data2", "write"]],
970 e.get_implicit_permissions_for_user("bob", None)
971 );
972 }
973
974 #[cfg(not(target_arch = "wasm32"))]
975 #[cfg_attr(
976 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
977 async_std::test
978 )]
979 #[cfg_attr(
980 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
981 tokio::test
982 )]
983 async fn test_implicit_user_api() {
984 let m = DefaultModel::from_file("examples/rbac_model.conf")
985 .await
986 .unwrap();
987
988 let adapter =
989 FileAdapter::new("examples/rbac_with_hierarchy_policy.csv");
990 let e = Enforcer::new(m, adapter).await.unwrap();
991
992 assert_eq!(
993 vec!["alice"],
994 e.get_implicit_users_for_permission(
995 vec!["data1", "read"]
996 .iter()
997 .map(|s| s.to_string())
998 .collect()
999 )
1000 .await
1001 );
1002 assert_eq!(
1003 vec!["alice"],
1004 e.get_implicit_users_for_permission(
1005 vec!["data1", "write"]
1006 .iter()
1007 .map(|s| s.to_string())
1008 .collect()
1009 )
1010 .await
1011 );
1012 assert_eq!(
1013 vec!["alice"],
1014 e.get_implicit_users_for_permission(
1015 vec!["data2", "read"]
1016 .iter()
1017 .map(|s| s.to_string())
1018 .collect()
1019 )
1020 .await
1021 );
1022 assert_eq!(
1023 vec!["alice", "bob"],
1024 sort_unstable(
1025 e.get_implicit_users_for_permission(
1026 vec!["data2", "write"]
1027 .iter()
1028 .map(|s| s.to_string())
1029 .collect()
1030 )
1031 .await
1032 )
1033 );
1034 }
1035
1036 #[cfg(not(target_arch = "wasm32"))]
1037 #[cfg_attr(
1038 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1039 async_std::test
1040 )]
1041 #[cfg_attr(
1042 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1043 tokio::test
1044 )]
1045 async fn test_implicit_permission_api_with_domain() {
1046 let m =
1047 DefaultModel::from_file("examples/rbac_with_domains_model.conf")
1048 .await
1049 .unwrap();
1050
1051 let adapter = FileAdapter::new(
1052 "examples/rbac_with_hierarchy_with_domains_policy.csv",
1053 );
1054 let e = Enforcer::new(m, adapter).await.unwrap();
1055
1056 assert_eq!(
1057 vec![
1058 vec!["alice", "domain1", "data2", "read"],
1059 vec!["role:reader", "domain1", "data1", "read"],
1060 vec!["role:writer", "domain1", "data1", "write"],
1061 ],
1062 sort_unstable(
1063 e.get_implicit_permissions_for_user("alice", Some("domain1"))
1064 )
1065 );
1066 }
1067
1068 #[cfg(not(target_arch = "wasm32"))]
1069 #[cfg_attr(
1070 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1071 async_std::test
1072 )]
1073 #[cfg_attr(
1074 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1075 tokio::test
1076 )]
1077 async fn test_pattern_matching_fn() {
1078 let e = Enforcer::new(
1079 "examples/rbac_with_pattern_model.conf",
1080 "examples/rbac_with_pattern_policy.csv",
1081 )
1082 .await
1083 .unwrap();
1084
1085 use crate::model::key_match2;
1086
1087 e.get_role_manager()
1088 .write()
1089 .matching_fn(Some(key_match2), None);
1090
1091 assert!(e.enforce(("alice", "/pen/1", "GET")).unwrap());
1092 assert!(e.enforce(("alice", "/pen2/1", "GET")).unwrap());
1093 assert!(e.enforce(("alice", "/book/1", "GET")).unwrap());
1094 assert!(e.enforce(("alice", "/book/2", "GET")).unwrap());
1095 assert!(e.enforce(("alice", "/pen/1", "GET")).unwrap());
1096 assert!(!e.enforce(("alice", "/pen/2", "GET")).unwrap());
1097 assert!(!e.enforce(("bob", "/book/1", "GET")).unwrap());
1098 assert!(!e.enforce(("bob", "/book/2", "GET")).unwrap());
1099 assert!(e.enforce(("bob", "/pen/1", "GET")).unwrap());
1100 assert!(e.enforce(("bob", "/pen/2", "GET")).unwrap());
1101
1102 assert_eq!(
1103 vec!["book_group"],
1104 sort_unstable(e.get_implicit_roles_for_user("/book/1", None))
1105 );
1106
1107 assert_eq!(
1108 vec!["pen_group"],
1109 sort_unstable(e.get_implicit_roles_for_user("/pen/1", None))
1110 );
1111 }
1112
1113 #[cfg(not(target_arch = "wasm32"))]
1114 #[cfg_attr(
1115 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1116 async_std::test
1117 )]
1118 #[cfg_attr(
1119 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1120 tokio::test
1121 )]
1122 async fn test_pattern_matching_fn_with_domain() {
1123 let e = Enforcer::new(
1124 "examples/rbac_with_pattern_domain_model.conf",
1125 "examples/rbac_with_pattern_domain_policy.csv",
1126 )
1127 .await
1128 .unwrap();
1129
1130 use crate::function_map::key_match;
1131
1132 e.get_role_manager()
1133 .write()
1134 .matching_fn(None, Some(key_match));
1135
1136 assert!(e.enforce(("alice", "domain1", "data1", "read")).unwrap());
1137 assert!(e.enforce(("alice", "domain1", "data1", "write")).unwrap());
1138 assert!(e.enforce(("alice", "domain2", "data2", "read")).unwrap());
1139 assert!(e.enforce(("alice", "domain2", "data2", "write")).unwrap());
1140
1141 assert!(!e.enforce(("bob", "domain1", "data1", "read")).unwrap());
1142 assert!(!e.enforce(("bob", "domain1", "data1", "write")).unwrap());
1143 assert!(e.enforce(("bob", "domain2", "data2", "read")).unwrap());
1144 assert!(e.enforce(("bob", "domain2", "data2", "write")).unwrap());
1145
1146 assert_eq!(
1147 vec!["admin".to_owned()],
1148 e.get_implicit_roles_for_user("alice", Some("domain3"))
1149 );
1150
1151 assert_eq!(
1152 vec!["alice".to_owned()],
1153 e.get_users_for_role("admin", Some("domain3"))
1154 );
1155 }
1156
1157 #[cfg(not(target_arch = "wasm32"))]
1158 #[cfg_attr(
1159 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1160 async_std::test
1161 )]
1162 #[cfg_attr(
1163 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1164 tokio::test
1165 )]
1166 async fn test_pattern_matching_basic_role() {
1167 let e = Enforcer::new(
1168 "examples/rbac_basic_role_model.conf",
1169 "examples/rbac_basic_role_policy.csv",
1170 )
1171 .await
1172 .unwrap();
1173
1174 use crate::model::key_match;
1175
1176 e.get_role_manager()
1177 .write()
1178 .matching_fn(Some(key_match), None);
1179
1180 assert!(e.enforce(("alice", "/pen/1", "GET")).unwrap());
1181 assert!(e.enforce(("alice", "/book/1", "GET")).unwrap());
1182 assert!(e.enforce(("bob", "/pen/1", "GET")).unwrap());
1183 assert!(e.enforce(("bob", "/book/1", "GET")).unwrap());
1184
1185 assert!(!e.enforce(("alice", "/pen/2", "GET")).unwrap());
1186 assert!(!e.enforce(("alice", "/book/2", "GET")).unwrap());
1187 assert!(!e.enforce(("bob", "/pen/2", "GET")).unwrap());
1188 assert!(!e.enforce(("bob", "/book/2", "GET")).unwrap());
1189
1190 assert_eq!(
1191 vec!["book_admin", "pen_admin"],
1192 sort_unstable(e.get_implicit_roles_for_user("alice", None))
1193 );
1194 assert_eq!(
1195 vec!["book_admin", "pen_admin"],
1196 sort_unstable(e.get_implicit_roles_for_user("bob", None))
1197 );
1198 }
1199
1200 #[cfg(not(target_arch = "wasm32"))]
1201 #[cfg_attr(
1202 all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1203 async_std::test
1204 )]
1205 #[cfg_attr(
1206 all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1207 tokio::test
1208 )]
1209 async fn test_implicit_users_for_permission() {
1210 let mut m = DefaultModel::default();
1211 m.add_def("r", "r", "sub, obj, act");
1212 m.add_def("p", "p", "sub, obj, act");
1213 m.add_def("g", "g", "_, _");
1214 m.add_def("e", "e", "some(where (p.eft == allow))");
1215 m.add_def(
1216 "m",
1217 "m",
1218 "g(r.sub, p.sub) && r.obj == p.obj && regexMatch(r.act, p.act)",
1219 );
1220
1221 let a = MemoryAdapter::default();
1222
1223 let mut e = Enforcer::new(m, a).await.unwrap();
1224
1225 assert!(e
1226 .add_policy(vec![
1227 "role::r1".to_owned(),
1228 "data1".to_owned(),
1229 "(read)|(writer)".to_owned()
1230 ])
1231 .await
1232 .unwrap());
1233
1234 assert!(e
1235 .add_policy(vec![
1236 "role::r2".to_owned(),
1237 "data2".to_owned(),
1238 "writer".to_owned()
1239 ])
1240 .await
1241 .unwrap());
1242
1243 assert!(e
1244 .add_policy(vec![
1245 "user1".to_owned(),
1246 "data2".to_owned(),
1247 "writer".to_owned()
1248 ])
1249 .await
1250 .unwrap());
1251
1252 assert!(e
1253 .add_grouping_policy(vec![
1254 "user2".to_owned(),
1255 "role::r2".to_owned(),
1256 ])
1257 .await
1258 .unwrap());
1259
1260 assert!(e
1261 .add_grouping_policy(vec![
1262 "user3".to_owned(),
1263 "role::r2".to_owned(),
1264 ])
1265 .await
1266 .unwrap());
1267
1268 assert_eq!(
1269 vec!["user1".to_owned(), "user2".to_owned(), "user3".to_owned()],
1270 sort_unstable(
1271 e.get_implicit_users_for_permission(vec![
1272 "data2".to_owned(),
1273 "writer".to_owned()
1274 ])
1275 .await
1276 )
1277 );
1278 }
1279}