casbin-rs/src/management_api.rs (1,081 lines of code) (raw):

use crate::{InternalApi, Result}; use async_trait::async_trait; #[async_trait] pub trait MgmtApi: InternalApi { async fn add_policy(&mut self, params: Vec<String>) -> Result<bool> { self.add_named_policy("p", params).await } async fn add_policies( &mut self, paramss: Vec<Vec<String>>, ) -> Result<bool> { self.add_named_policies("p", paramss).await } async fn remove_policy(&mut self, params: Vec<String>) -> Result<bool> { self.remove_named_policy("p", params).await } async fn remove_policies( &mut self, paramss: Vec<Vec<String>>, ) -> Result<bool> { self.remove_named_policies("p", paramss).await } async fn add_named_policy( &mut self, ptype: &str, params: Vec<String>, ) -> Result<bool>; async fn add_named_policies( &mut self, ptype: &str, paramss: Vec<Vec<String>>, ) -> Result<bool>; async fn remove_named_policy( &mut self, ptype: &str, params: Vec<String>, ) -> Result<bool>; async fn remove_named_policies( &mut self, ptype: &str, paramss: Vec<Vec<String>>, ) -> Result<bool>; async fn add_grouping_policy( &mut self, params: Vec<String>, ) -> Result<bool> { self.add_named_grouping_policy("g", params).await } async fn add_grouping_policies( &mut self, paramss: Vec<Vec<String>>, ) -> Result<bool> { self.add_named_grouping_policies("g", paramss).await } async fn remove_grouping_policy( &mut self, params: Vec<String>, ) -> Result<bool> { self.remove_named_grouping_policy("g", params).await } async fn remove_grouping_policies( &mut self, paramss: Vec<Vec<String>>, ) -> Result<bool> { self.remove_named_grouping_policies("g", paramss).await } async fn add_named_grouping_policy( &mut self, ptype: &str, params: Vec<String>, ) -> Result<bool>; async fn add_named_grouping_policies( &mut self, ptype: &str, paramss: Vec<Vec<String>>, ) -> Result<bool>; async fn remove_named_grouping_policy( &mut self, ptype: &str, params: Vec<String>, ) -> Result<bool>; async fn remove_named_grouping_policies( &mut self, ptype: &str, paramss: Vec<Vec<String>>, ) -> Result<bool>; async fn remove_filtered_policy( &mut self, field_index: usize, field_values: Vec<String>, ) -> Result<bool> { self.remove_filtered_named_policy("p", field_index, field_values) .await } async fn remove_filtered_grouping_policy( &mut self, field_index: usize, field_values: Vec<String>, ) -> Result<bool> { self.remove_filtered_named_grouping_policy( "g", field_index, field_values, ) .await } async fn remove_filtered_named_policy( &mut self, ptype: &str, field_index: usize, field_values: Vec<String>, ) -> Result<bool>; async fn remove_filtered_named_grouping_policy( &mut self, ptype: &str, field_index: usize, field_values: Vec<String>, ) -> Result<bool>; fn get_policy(&self) -> Vec<Vec<String>> { self.get_named_policy("p") } fn get_all_policy(&self) -> Vec<Vec<String>>; fn get_named_policy(&self, ptype: &str) -> Vec<Vec<String>>; fn get_filtered_policy( &self, field_index: usize, field_values: Vec<String>, ) -> Vec<Vec<String>> { self.get_filtered_named_policy("p", field_index, field_values) } fn get_filtered_named_policy( &self, ptype: &str, field_index: usize, field_values: Vec<String>, ) -> Vec<Vec<String>>; fn has_policy(&self, params: Vec<String>) -> bool { self.has_named_policy("p", params) } fn has_named_policy(&self, ptype: &str, params: Vec<String>) -> bool; fn get_grouping_policy(&self) -> Vec<Vec<String>> { self.get_named_grouping_policy("g") } fn get_all_grouping_policy(&self) -> Vec<Vec<String>>; fn get_named_grouping_policy(&self, ptype: &str) -> Vec<Vec<String>>; fn get_filtered_grouping_policy( &self, field_index: usize, field_values: Vec<String>, ) -> Vec<Vec<String>> { self.get_filtered_named_grouping_policy("g", field_index, field_values) } fn get_filtered_named_grouping_policy( &self, ptype: &str, field_index: usize, field_values: Vec<String>, ) -> Vec<Vec<String>>; fn has_grouping_policy(&self, params: Vec<String>) -> bool { self.has_grouping_named_policy("g", params) } fn has_grouping_named_policy( &self, ptype: &str, params: Vec<String>, ) -> bool; fn get_all_subjects(&self) -> Vec<String> { self.get_all_named_subjects("p") } fn get_all_named_subjects(&self, ptype: &str) -> Vec<String>; fn get_all_objects(&self) -> Vec<String> { self.get_all_named_objects("p") } fn get_all_named_objects(&self, ptype: &str) -> Vec<String>; fn get_all_actions(&self) -> Vec<String> { self.get_all_named_actions("p") } fn get_all_roles(&self) -> Vec<String> { self.get_all_named_roles("g") } fn get_all_named_actions(&self, ptype: &str) -> Vec<String>; fn get_all_named_roles(&self, ptype: &str) -> Vec<String>; } #[async_trait] impl<T> MgmtApi for T where T: InternalApi, { async fn add_named_policy( &mut self, ptype: &str, params: Vec<String>, ) -> Result<bool> { self.add_policy_internal("p", ptype, params).await } async fn add_named_policies( &mut self, ptype: &str, paramss: Vec<Vec<String>>, ) -> Result<bool> { self.add_policies_internal("p", ptype, paramss).await } async fn remove_named_policy( &mut self, ptype: &str, params: Vec<String>, ) -> Result<bool> { self.remove_policy_internal("p", ptype, params).await } async fn remove_named_policies( &mut self, ptype: &str, paramss: Vec<Vec<String>>, ) -> Result<bool> { self.remove_policies_internal("p", ptype, paramss).await } async fn add_named_grouping_policy( &mut self, ptype: &str, params: Vec<String>, ) -> Result<bool> { let rule_added = self.add_policy_internal("g", ptype, params).await?; Ok(rule_added) } async fn add_named_grouping_policies( &mut self, ptype: &str, paramss: Vec<Vec<String>>, ) -> Result<bool> { let all_added = self.add_policies_internal("g", ptype, paramss).await?; Ok(all_added) } async fn remove_named_grouping_policy( &mut self, ptype: &str, params: Vec<String>, ) -> Result<bool> { let rule_removed = self.remove_policy_internal("g", ptype, params).await?; Ok(rule_removed) } async fn remove_named_grouping_policies( &mut self, ptype: &str, paramss: Vec<Vec<String>>, ) -> Result<bool> { let all_removed = self.remove_policies_internal("g", ptype, paramss).await?; Ok(all_removed) } async fn remove_filtered_named_grouping_policy( &mut self, ptype: &str, field_index: usize, field_values: Vec<String>, ) -> Result<bool> { #[allow(unused_variables)] let (rule_removed, rules) = self .remove_filtered_policy_internal( "g", ptype, field_index, field_values, ) .await?; Ok(rule_removed) } async fn remove_filtered_named_policy( &mut self, ptype: &str, field_index: usize, field_values: Vec<String>, ) -> Result<bool> { Ok(self .remove_filtered_policy_internal( "p", ptype, field_index, field_values, ) .await? .0) } fn get_named_policy(&self, ptype: &str) -> Vec<Vec<String>> { self.get_model().get_policy("p", ptype) } fn get_all_policy(&self) -> Vec<Vec<String>> { let mut res: Vec<Vec<String>> = vec![]; let sec = "p"; if let Some(ast_map) = self.get_model().get_model().get(sec) { for (ptype, ast) in ast_map { res.extend(ast.get_policy().clone().into_iter().map(|mut x| { x.insert(0, ptype.clone()); x.insert(0, sec.to_owned()); x })) } } res } fn get_filtered_named_policy( &self, ptype: &str, field_index: usize, field_values: Vec<String>, ) -> Vec<Vec<String>> { self.get_model().get_filtered_policy( "p", ptype, field_index, field_values, ) } fn has_named_policy(&self, ptype: &str, params: Vec<String>) -> bool { self.get_model().has_policy("p", ptype, params) } fn get_named_grouping_policy(&self, ptype: &str) -> Vec<Vec<String>> { self.get_model().get_policy("g", ptype) } fn get_all_grouping_policy(&self) -> Vec<Vec<String>> { let mut res: Vec<Vec<String>> = vec![]; let sec = "g"; if let Some(ast_map) = self.get_model().get_model().get(sec) { for (ptype, ast) in ast_map { res.extend(ast.get_policy().clone().into_iter().map(|mut x| { x.insert(0, ptype.clone()); x.insert(0, sec.to_owned()); x })) } } res } fn get_filtered_named_grouping_policy( &self, ptype: &str, field_index: usize, field_values: Vec<String>, ) -> Vec<Vec<String>> { self.get_model().get_filtered_policy( "g", ptype, field_index, field_values, ) } fn has_grouping_named_policy( &self, ptype: &str, params: Vec<String>, ) -> bool { self.get_model().has_policy("g", ptype, params) } fn get_all_named_subjects(&self, ptype: &str) -> Vec<String> { self.get_model() .get_values_for_field_in_policy("p", ptype, 0) } fn get_all_named_objects(&self, ptype: &str) -> Vec<String> { self.get_model() .get_values_for_field_in_policy("p", ptype, 1) } fn get_all_named_actions(&self, ptype: &str) -> Vec<String> { self.get_model() .get_values_for_field_in_policy("p", ptype, 2) } fn get_all_named_roles(&self, ptype: &str) -> Vec<String> { self.get_model() .get_values_for_field_in_policy("g", ptype, 1) } } #[cfg(test)] mod tests { use crate::prelude::*; fn sort_unstable<T: Ord>(mut v: Vec<T>) -> Vec<T> { v.sort_unstable(); v } #[cfg(not(target_arch = "wasm32"))] #[cfg_attr( all(feature = "runtime-async-std", not(target_arch = "wasm32")), async_std::test )] #[cfg_attr( all(feature = "runtime-tokio", not(target_arch = "wasm32")), tokio::test )] async fn test_modify_grouping_policy_api() { let m = DefaultModel::from_file("examples/rbac_model.conf") .await .unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let mut e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!(vec!["data2_admin"], e.get_roles_for_user("alice", None)); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None)); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("eve", None)); assert_eq!( vec![String::new(); 0], e.get_roles_for_user("non_exist", None) ); e.remove_grouping_policy( vec!["alice", "data2_admin"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); e.add_grouping_policy( vec!["bob", "data1_admin"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); e.add_grouping_policy( vec!["eve", "data3_admin"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); let named_grouping_policy = vec!["alice".to_string(), "data2_admin".to_string()]; assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None)); e.add_named_grouping_policy("g", named_grouping_policy.clone()) .await .unwrap(); assert_eq!(vec!["data2_admin"], e.get_roles_for_user("alice", None)); e.remove_named_grouping_policy("g", named_grouping_policy.clone()) .await .unwrap(); e.remove_grouping_policy( vec!["alice", "data2_admin"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); e.add_grouping_policy( vec!["bob", "data1_admin"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); e.add_grouping_policy( vec!["eve", "data3_admin"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); assert_eq!(vec!["bob"], e.get_users_for_role("data1_admin", None)); assert_eq!( vec![String::new(); 0], e.get_users_for_role("data2_admin", None) ); assert_eq!(vec!["eve"], e.get_users_for_role("data3_admin", None)); e.remove_filtered_grouping_policy( 0, vec!["bob"].iter().map(|s| s.to_string()).collect(), ) .await .unwrap(); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None)); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None)); assert_eq!(vec!["data3_admin"], e.get_roles_for_user("eve", None)); assert_eq!( vec![String::new(); 0], e.get_roles_for_user("non_exist", None) ); assert_eq!( vec![String::new(); 0], e.get_users_for_role("data1_admin", None) ); assert_eq!( vec![String::new(); 0], e.get_users_for_role("data2_admin", None) ); assert_eq!(vec!["eve"], e.get_users_for_role("data3_admin", None)); } #[cfg(not(target_arch = "wasm32"))] #[cfg_attr( all(feature = "runtime-async-std", not(target_arch = "wasm32")), async_std::test )] #[cfg_attr( all(feature = "runtime-tokio", not(target_arch = "wasm32")), tokio::test )] async fn test_modify_policy_api() { let m = DefaultModel::from_file("examples/rbac_model.conf") .await .unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let mut e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!( vec![ vec!["alice", "data1", "read"], vec!["bob", "data2", "write"], vec!["data2_admin", "data2", "read"], vec!["data2_admin", "data2", "write"], ], sort_unstable(e.get_policy()) ); e.remove_policy( vec!["alice", "data1", "read"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); e.remove_policy( vec!["bob", "data2", "write"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); e.remove_policy( vec!["alice", "data1", "read"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); e.add_policy( vec!["eve", "data3", "read"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); e.add_policy( vec!["eve", "data3", "read"] .iter() .map(|s| s.to_string()) .collect(), ) .await .unwrap(); let named_policy = vec!["eve".to_string(), "data3".to_string(), "read".to_string()]; e.remove_named_policy("p", named_policy.clone()) .await .unwrap(); e.add_named_policy("p", named_policy.clone()).await.unwrap(); assert_eq!( vec![ vec!["data2_admin", "data2", "read"], vec!["data2_admin", "data2", "write"], vec!["eve", "data3", "read"], ], sort_unstable(e.get_policy()) ); e.remove_filtered_policy( 1, vec!["data2"].iter().map(|s| s.to_string()).collect(), ) .await .unwrap(); assert_eq!(vec![vec!["eve", "data3", "read"],], e.get_policy()); } #[cfg(not(target_arch = "wasm32"))] #[cfg_attr( all(feature = "runtime-async-std", not(target_arch = "wasm32")), async_std::test )] #[cfg_attr( all(feature = "runtime-tokio", not(target_arch = "wasm32")), tokio::test )] async fn test_get_policy_api() { let m = DefaultModel::from_file("examples/rbac_model.conf") .await .unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!( vec![ vec!["alice", "data1", "read"], vec!["bob", "data2", "write"], vec!["data2_admin", "data2", "read"], vec!["data2_admin", "data2", "write"], ], sort_unstable(e.get_policy()) ); assert_eq!( vec![vec!["alice", "data1", "read"]], e.get_filtered_policy( 0, vec!["alice"].iter().map(|s| s.to_string()).collect() ) ); assert_eq!( vec![vec!["bob", "data2", "write"]], e.get_filtered_policy( 0, vec!["bob"].iter().map(|s| s.to_string()).collect() ) ); assert_eq!( vec![ vec!["data2_admin", "data2", "read"], vec!["data2_admin", "data2", "write"], ], sort_unstable(e.get_filtered_policy( 0, vec!["data2_admin"].iter().map(|s| s.to_string()).collect() )) ); assert_eq!( vec![vec!["alice", "data1", "read"],], e.get_filtered_policy( 1, vec!["data1"].iter().map(|s| s.to_string()).collect() ) ); assert_eq!( vec![ vec!["bob", "data2", "write"], vec!["data2_admin", "data2", "read"], vec!["data2_admin", "data2", "write"], ], sort_unstable(e.get_filtered_policy( 1, vec!["data2"].iter().map(|s| s.to_string()).collect() )) ); assert_eq!( vec![ vec!["alice", "data1", "read"], vec!["data2_admin", "data2", "read"], ], sort_unstable(e.get_filtered_policy( 2, vec!["read"].iter().map(|s| s.to_string()).collect() )) ); assert_eq!( vec![ vec!["bob", "data2", "write"], vec!["data2_admin", "data2", "write"], ], sort_unstable(e.get_filtered_policy( 2, vec!["write"].iter().map(|s| s.to_string()).collect() )) ); assert_eq!( vec![ vec!["data2_admin", "data2", "read"], vec!["data2_admin", "data2", "write"], ], sort_unstable( e.get_filtered_policy( 0, vec!["data2_admin", "data2"] .iter() .map(|s| s.to_string()) .collect() ) ) ); // Note: "" (empty string) in fieldValues means matching all values. assert_eq!( vec![vec!["data2_admin", "data2", "read"],], e.get_filtered_policy( 0, vec!["data2_admin", "", "read"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( vec![ vec!["bob", "data2", "write"], vec!["data2_admin", "data2", "write"], ], sort_unstable( e.get_filtered_policy( 1, vec!["data2", "write"] .iter() .map(|s| s.to_string()) .collect() ) ) ); assert_eq!( true, e.has_policy( vec!["alice", "data1", "read"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( true, e.has_policy( vec!["bob", "data2", "write"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( false, e.has_policy( vec!["alice", "data2", "read"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( false, e.has_policy( vec!["bob", "data3", "write"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( vec![vec!["alice", "data2_admin"]], e.get_filtered_grouping_policy( 0, vec!["alice"].iter().map(|s| s.to_string()).collect() ) ); let empty_policy: Vec<Vec<String>> = vec![]; assert_eq!( empty_policy, e.get_filtered_grouping_policy( 0, vec!["bob"].iter().map(|s| s.to_string()).collect() ) ); assert_eq!( empty_policy, e.get_filtered_grouping_policy( 1, vec!["data1_admin"].iter().map(|s| s.to_string()).collect() ) ); assert_eq!( vec![vec!["alice", "data2_admin"],], e.get_filtered_grouping_policy( 1, vec!["data2_admin"].iter().map(|s| s.to_string()).collect() ) ); // Note: "" (empty string) in fieldValues means matching all values. assert_eq!( empty_policy, e.get_filtered_grouping_policy( 0, vec!["data2_admin"].iter().map(|s| s.to_string()).collect() ) ); assert_eq!( true, e.has_grouping_policy( vec!["alice", "data2_admin"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( false, e.has_grouping_policy( vec!["bob", "data2_admin"] .iter() .map(|s| s.to_string()) .collect() ) ); } #[cfg(not(target_arch = "wasm32"))] #[cfg_attr( all(feature = "runtime-async-std", not(target_arch = "wasm32")), async_std::test )] #[cfg_attr( all(feature = "runtime-tokio", not(target_arch = "wasm32")), tokio::test )] async fn test_get_list() { let m = DefaultModel::from_file("examples/rbac_model.conf") .await .unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!( vec!["alice", "bob", "data2_admin"], sort_unstable(e.get_all_subjects()) ); assert_eq!(vec!["data1", "data2"], sort_unstable(e.get_all_objects())); assert_eq!(vec!["read", "write"], sort_unstable(e.get_all_actions())); assert_eq!(vec!["data2_admin"], e.get_all_roles()); } #[cfg(not(target_arch = "wasm32"))] #[cfg_attr( all(feature = "runtime-async-std", not(target_arch = "wasm32")), async_std::test )] #[cfg_attr( all(feature = "runtime-tokio", not(target_arch = "wasm32")), tokio::test )] async fn test_modify_policies_api() { let m = DefaultModel::from_file("examples/rbac_model.conf") .await .unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let mut e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!( vec![ vec!["alice", "data1", "read"], vec!["bob", "data2", "write"], vec!["data2_admin", "data2", "read"], vec!["data2_admin", "data2", "write"], ], sort_unstable(e.get_policy()) ); e.remove_policies(vec![ vec!["alice", "data1", "read"] .iter() .map(|s| s.to_string()) .collect(), vec!["bob", "data2", "write"] .iter() .map(|s| s.to_string()) .collect(), ]) .await .unwrap(); e.remove_policies(vec![vec!["alice", "data1", "read"] .iter() .map(|s| s.to_string()) .collect()]) .await .unwrap(); assert_eq!( false, e.has_policy( vec!["alice", "data1", "read"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( false, e.has_policy( vec!["bob", "data2", "write"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( true, e.has_policy( vec!["data2_admin", "data2", "read"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( true, e.has_policy( vec!["data2_admin", "data2", "write"] .iter() .map(|s| s.to_string()) .collect() ) ); e.add_policies(vec![vec!["eve", "data3", "read"] .iter() .map(|s| s.to_string()) .collect()]) .await .unwrap(); e.add_policies(vec![ vec!["eve", "data3", "read"] .iter() .map(|s| s.to_string()) .collect(), vec!["eve", "data3", "read"] .iter() .map(|s| s.to_string()) .collect(), ]) .await .unwrap(); assert_eq!( false, e.has_policy( vec!["alice", "data1", "read"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( false, e.has_policy( vec!["bob", "data2", "write"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( true, e.has_policy( vec!["eve", "data3", "read"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( true, e.has_policy( vec!["data2_admin", "data2", "read"] .iter() .map(|s| s.to_string()) .collect() ) ); assert_eq!( true, e.has_policy( vec!["data2_admin", "data2", "write"] .iter() .map(|s| s.to_string()) .collect() ) ); let named_policy = vec!["eve".to_string(), "data3".to_string(), "read".to_string()]; e.remove_named_policies("p", vec![named_policy.clone()]) .await .unwrap(); e.add_named_policies("p", vec![named_policy.clone()]) .await .unwrap(); assert_eq!( vec![ vec!["data2_admin", "data2", "read"], vec!["data2_admin", "data2", "write"], vec!["eve", "data3", "read"], ], sort_unstable(e.get_policy()) ); e.remove_filtered_policy( 1, vec!["data2"].iter().map(|s| s.to_string()).collect(), ) .await .unwrap(); assert_eq!(vec![vec!["eve", "data3", "read"],], e.get_policy()); } #[cfg(not(target_arch = "wasm32"))] #[cfg_attr( all(feature = "runtime-async-std", not(target_arch = "wasm32")), async_std::test )] #[cfg_attr( all(feature = "runtime-tokio", not(target_arch = "wasm32")), tokio::test )] async fn test_modify_grouping_policies_api() { let m = DefaultModel::from_file("examples/rbac_model.conf") .await .unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let mut e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!(vec!["data2_admin"], e.get_roles_for_user("alice", None)); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None)); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("eve", None)); assert_eq!( vec![String::new(); 0], e.get_roles_for_user("non_exist", None) ); e.remove_grouping_policies(vec![vec!["alice", "data2_admin"] .iter() .map(|s| s.to_string()) .collect()]) .await .unwrap(); e.add_grouping_policies(vec![ vec!["bob", "data1_admin"] .iter() .map(|s| s.to_string()) .collect(), vec!["eve", "data3_admin"] .iter() .map(|s| s.to_string()) .collect(), ]) .await .unwrap(); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None)); assert_eq!(vec!["data1_admin"], e.get_roles_for_user("bob", None)); assert_eq!(vec!["data3_admin"], e.get_roles_for_user("eve", None)); let named_grouping_policy = vec!["alice".to_string(), "data2_admin".to_string()]; assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None)); e.add_named_grouping_policies("g", vec![named_grouping_policy.clone()]) .await .unwrap(); assert_eq!(vec!["data2_admin"], e.get_roles_for_user("alice", None)); e.remove_named_grouping_policies( "g", vec![named_grouping_policy.clone()], ) .await .unwrap(); e.remove_grouping_policies(vec![vec!["alice", "data2_admin"] .iter() .map(|s| s.to_string()) .collect()]) .await .unwrap(); e.add_grouping_policies(vec![ vec!["bob", "data1_admin"] .iter() .map(|s| s.to_string()) .collect(), vec!["eve", "data3_admin"] .iter() .map(|s| s.to_string()) .collect(), ]) .await .unwrap(); assert_eq!(vec!["bob"], e.get_users_for_role("data1_admin", None)); assert_eq!( vec![String::new(); 0], e.get_users_for_role("data2_admin", None) ); assert_eq!(vec!["eve"], e.get_users_for_role("data3_admin", None)); e.remove_filtered_grouping_policy( 0, vec!["bob"].iter().map(|s| s.to_string()).collect(), ) .await .unwrap(); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("alice", None)); assert_eq!(vec![String::new(); 0], e.get_roles_for_user("bob", None)); assert_eq!(vec!["data3_admin"], e.get_roles_for_user("eve", None)); assert_eq!( vec![String::new(); 0], e.get_roles_for_user("non_exist", None) ); assert_eq!( vec![String::new(); 0], e.get_users_for_role("data1_admin", None) ); assert_eq!( vec![String::new(); 0], e.get_users_for_role("data2_admin", None) ); assert_eq!(vec!["eve"], e.get_users_for_role("data3_admin", None)); } }