diff --git a/Cargo.toml b/Cargo.toml index 14e160af..6bf3d69e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "casbin" -version = "0.4.4" +version = "0.5.0" authors = ["Joey ", "Cheng JIANG "] edition = "2018" license = "Apache-2.0" diff --git a/README.md b/README.md index 46c100ef..a4a971af 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Add this package to `Cargo.toml` of your project. (Check https://crates.io/crate ```toml [dependencies] -casbin = "0.4.4" +casbin = "0.5.0" async-std = { version = "1.5.0", features = ["attributes"] } ``` @@ -39,7 +39,7 @@ use casbin::prelude::*; #[async_std::main] async fn main() { - let e = Enforcer::new("path/to/model.conf", "path/to/policy.csv").await?; + let mut e = Enforcer::new("path/to/model.conf", "path/to/policy.csv").await?; } ``` @@ -50,7 +50,7 @@ async fn main() { obj = "data1"; // the resource that is going to be accessed. act = "read"; // the operation that the user performs on the resource. - if let Ok(authorized) = e.enforce(&[sub, obj, act]) { + if let Ok(authorized) = e.enforce(&[sub, obj, act]).await { if authorized { // permit alice to read data1 } else { diff --git a/benches/casbin.rs b/benches/casbin.rs index 4639ffe5..2a06a329 100644 --- a/benches/casbin.rs +++ b/benches/casbin.rs @@ -1,4 +1,4 @@ -use casbin::{DefaultModel, Enforcer, FileAdapter, MemoryAdapter, Model, RbacApi}; +use casbin::prelude::*; use criterion::{criterion_group, criterion_main, Criterion}; #[cfg(feature = "runtime-async-std")] @@ -64,7 +64,7 @@ fn enforcer_create(b: &mut Criterion) { let adpt = FileAdapter::new("examples/basic_model.conf"); // what we want to measure - let _e = await_future(Enforcer::new(Box::new(m), Box::new(adpt))).unwrap(); + let _e = await_future(Enforcer::new(m, adpt)).unwrap(); }); }); } @@ -81,13 +81,11 @@ fn enforcer_enforce(b: &mut Criterion) { "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)", ); let adapter = FileAdapter::new("examples/keymatch_policy.csv"); - let e = await_future(Enforcer::new(Box::new(m), Box::new(adapter))).unwrap(); + let mut e = await_future(Enforcer::new(m, adapter)).unwrap(); b.iter(|| { - e.enforce(&vec!["alice", "/alice_data/resource1", "GET"]) - .unwrap(); - e.enforce(&vec!["alice", "/alice_data/resource1", "POST"]) - .unwrap(); + await_future(e.enforce(&vec!["alice", "/alice_data/resource1", "GET"])).unwrap(); + await_future(e.enforce(&vec!["alice", "/alice_data/resource1", "POST"])).unwrap(); }) }); } @@ -106,7 +104,7 @@ fn enforcer_add_permission(b: &mut Criterion) { ); let adapter = MemoryAdapter::default(); - let mut e = await_future(Enforcer::new(Box::new(m), Box::new(adapter))).unwrap(); + let mut e = await_future(Enforcer::new(m, adapter)).unwrap(); b.iter(|| { await_future(e.add_permission_for_user( diff --git a/src/adapter/file_adapter.rs b/src/adapter/file_adapter.rs index 932f4f3e..69742c46 100644 --- a/src/adapter/file_adapter.rs +++ b/src/adapter/file_adapter.rs @@ -1,9 +1,4 @@ -use crate::adapter::Adapter; -use crate::error::ModelError; -use crate::model::Model; -use crate::Result; - -use std::convert::AsRef; +use crate::{adapter::Adapter, error::ModelError, model::Model, Result}; #[cfg(feature = "runtime-async-std")] use async_std::{ @@ -28,6 +23,8 @@ use tokio::{ use async_trait::async_trait; +use std::convert::AsRef; + pub struct FileAdapter

{ file_path: P, } diff --git a/src/adapter/memory_adapter.rs b/src/adapter/memory_adapter.rs index 325999ea..399e9534 100644 --- a/src/adapter/memory_adapter.rs +++ b/src/adapter/memory_adapter.rs @@ -1,10 +1,7 @@ -use crate::adapter::Adapter; -use crate::model::Model; -use crate::Result; - -use indexmap::IndexSet; +use crate::{adapter::Adapter, model::Model, Result}; use async_trait::async_trait; +use indexmap::IndexSet; #[derive(Default)] pub struct MemoryAdapter { diff --git a/src/cached_api.rs b/src/cached_api.rs new file mode 100644 index 00000000..8b64c890 --- /dev/null +++ b/src/cached_api.rs @@ -0,0 +1,9 @@ +use crate::cache::Cache; + +use std::time::Duration; + +pub trait CachedApi: Sized + Send + Sync { + fn set_cache(&mut self, cache: Box, bool>>); + fn set_ttl(&mut self, ttl: Duration); + fn set_capacity(&mut self, cap: usize); +} diff --git a/src/cached_enforcer.rs b/src/cached_enforcer.rs index 8df1399e..0b2501b1 100644 --- a/src/cached_enforcer.rs +++ b/src/cached_enforcer.rs @@ -1,25 +1,37 @@ -use crate::cache::{Cache, DefaultCache}; -use crate::convert::{TryIntoAdapter, TryIntoModel}; -use crate::emitter::{Event, CACHED_EMITTER}; -use crate::enforcer::Enforcer; -use crate::Result; +use crate::{ + adapter::Adapter, + cache::{Cache, DefaultCache}, + cached_api::CachedApi, + convert::{TryIntoAdapter, TryIntoModel}, + core_api::CoreApi, + effector::Effector, + emitter::{Event, CACHED_EMITTER}, + enforcer::Enforcer, + model::Model, + rbac::RoleManager, + watcher::Watcher, + Result, +}; #[cfg(feature = "runtime-async-std")] use async_std::task; - +use async_trait::async_trait; use emitbrown::Events; -use std::ops::{Deref, DerefMut}; -use std::time::Duration; +use std::{ + sync::{Arc, RwLock}, + time::Duration, +}; pub struct CachedEnforcer { pub(crate) enforcer: Enforcer, pub(crate) cache: Box, bool>>, } -impl CachedEnforcer { +#[async_trait] +impl CoreApi for CachedEnforcer { #[cfg(feature = "runtime-async-std")] - pub async fn new(m: M, a: A) -> Result { + async fn new(m: M, a: A) -> Result { let cached_enforcer = CachedEnforcer { enforcer: Enforcer::new(m, a).await?, cache: Box::new(DefaultCache::new(1000)) as Box, bool>>, @@ -40,7 +52,7 @@ impl CachedEnforcer { } #[cfg(feature = "runtime-tokio")] - pub async fn new(m: M, a: A) -> Result { + async fn new(m: M, a: A) -> Result { let cached_enforcer = CachedEnforcer { enforcer: Enforcer::new(m, a).await?, cache: Box::new(DefaultCache::new(1000)) as Box, bool>>, @@ -66,42 +78,131 @@ impl CachedEnforcer { Ok(cached_enforcer) } - pub fn set_cache(&mut self, cache: Box, bool>>) { - self.cache = cache; + #[inline] + fn add_function(&mut self, fname: &str, f: fn(String, String) -> bool) { + self.enforcer.fm.add_function(fname, f); } - pub fn set_ttl(&mut self, ttl: Duration) { - self.cache.set_ttl(ttl); + #[inline] + fn get_model(&self) -> &dyn Model { + self.enforcer.get_model() } - pub fn set_capacity(&mut self, cap: usize) { - self.cache.set_capacity(cap); + #[inline] + fn get_mut_model(&mut self) -> &mut dyn Model { + self.enforcer.get_mut_model() + } + + #[inline] + fn get_adapter(&self) -> &dyn Adapter { + self.enforcer.get_adapter() + } + + #[inline] + fn get_mut_adapter(&mut self) -> &mut dyn Adapter { + self.enforcer.get_mut_adapter() + } + + #[inline] + fn set_watcher(&mut self, w: Box) { + self.enforcer.set_watcher(w); + } + + #[inline] + fn get_role_manager(&self) -> Arc> { + self.enforcer.get_role_manager() + } + + #[inline] + fn set_role_manager(&mut self, rm: Arc>) { + self.enforcer.set_role_manager(rm); + } + + #[inline] + fn add_matching_fn(&mut self, f: fn(String, String) -> bool) -> Result<()> { + self.enforcer.add_matching_fn(f) + } + + #[inline] + async fn set_model(&mut self, m: M) -> Result<()> { + self.enforcer.set_model(m).await + } + + #[inline] + async fn set_adapter(&mut self, a: A) -> Result<()> { + self.enforcer.set_adapter(a).await + } + + #[inline] + fn set_effector(&mut self, e: Box) { + self.enforcer.set_effector(e); } - pub async fn enforce>(&mut self, rvals: &[S]) -> Result { + async fn enforce + Send + Sync>(&mut self, rvals: &[S]) -> Result { let key: Vec = rvals.iter().map(|x| String::from(x.as_ref())).collect(); if let Some(result) = self.cache.get(&key).await { Ok(*result) } else { - let result = self.enforcer.enforce(&rvals)?; + let result = self.enforcer.enforce(rvals).await?; self.cache.set(key, result).await; Ok(result) } } -} -impl Deref for CachedEnforcer { - type Target = Enforcer; + #[inline] + fn build_role_links(&mut self) -> Result<()> { + self.enforcer.build_role_links() + } + + #[inline] + async fn load_policy(&mut self) -> Result<()> { + self.enforcer.load_policy().await + } + + #[inline] + async fn save_policy(&mut self) -> Result<()> { + self.enforcer.save_policy().await + } - fn deref(&self) -> &Self::Target { - &self.enforcer + #[inline] + fn clear_policy(&mut self) { + self.enforcer.clear_policy(); + } + + #[inline] + fn enable_enforce(&mut self, enabled: bool) { + self.enforcer.enable_enforce(enabled); + } + + #[inline] + fn enable_auto_save(&mut self, auto_save: bool) { + self.enforcer.enable_auto_save(auto_save); + } + + #[inline] + fn enable_auto_build_role_links(&mut self, auto_build_role_links: bool) { + self.enforcer + .enable_auto_build_role_links(auto_build_role_links); + } + + #[inline] + fn has_auto_save_enabled(&self) -> bool { + self.enforcer.has_auto_save_enabled() } } -impl DerefMut for CachedEnforcer { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.enforcer +impl CachedApi for CachedEnforcer { + fn set_cache(&mut self, cache: Box, bool>>) { + self.cache = cache; + } + + fn set_ttl(&mut self, ttl: Duration) { + self.cache.set_ttl(ttl); + } + + fn set_capacity(&mut self, cap: usize) { + self.cache.set_capacity(cap); } } diff --git a/src/config.rs b/src/config.rs index d62ebecd..bea9cb26 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,5 @@ use crate::Result; -use std::collections::HashMap; -use std::convert::AsRef; - #[cfg(feature = "runtime-async-std")] use async_std::{ fs::File, @@ -19,6 +16,8 @@ use tokio::{ io::{AsyncBufReadExt, AsyncReadExt, BufReader, Error as IoError, ErrorKind}, }; +use std::collections::HashMap; + const DEFAULT_SECTION: &str = "default"; const DEFAULT_COMMENT: &str = "#"; const DEFAULT_COMMENT_SEM: &str = ";"; diff --git a/src/convert.rs b/src/convert.rs index 5e0369a8..f5445662 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -3,12 +3,12 @@ use crate::{Adapter, DefaultModel, FileAdapter, Model, Result}; use async_trait::async_trait; #[async_trait] -pub trait TryIntoModel { +pub trait TryIntoModel: Send + Sync { async fn try_into_model(self) -> Result>; } #[async_trait] -pub trait TryIntoAdapter { +pub trait TryIntoAdapter: Send + Sync { async fn try_into_adapter(self) -> Result>; } diff --git a/src/core_api.rs b/src/core_api.rs new file mode 100644 index 00000000..9d63a551 --- /dev/null +++ b/src/core_api.rs @@ -0,0 +1,31 @@ +use crate::{Adapter, Effector, Model, Result, RoleManager, TryIntoAdapter, TryIntoModel, Watcher}; + +use async_trait::async_trait; + +use std::sync::{Arc, RwLock}; + +#[async_trait] +pub trait CoreApi: Sized + Send + Sync { + async fn new(m: M, a: A) -> Result; + fn add_function(&mut self, fname: &str, f: fn(String, String) -> bool); + fn get_model(&self) -> &dyn Model; + fn get_mut_model(&mut self) -> &mut dyn Model; + fn get_adapter(&self) -> &dyn Adapter; + fn get_mut_adapter(&mut self) -> &mut dyn Adapter; + fn set_watcher(&mut self, w: Box); + fn get_role_manager(&self) -> Arc>; + fn set_role_manager(&mut self, rm: Arc>); + fn add_matching_fn(&mut self, f: fn(String, String) -> bool) -> Result<()>; + async fn set_model(&mut self, m: M) -> Result<()>; + async fn set_adapter(&mut self, a: A) -> Result<()>; + fn set_effector(&mut self, e: Box); + async fn enforce + Send + Sync>(&mut self, rvals: &[S]) -> Result; + fn build_role_links(&mut self) -> Result<()>; + async fn load_policy(&mut self) -> Result<()>; + async fn save_policy(&mut self) -> Result<()>; + fn clear_policy(&mut self); + fn enable_auto_save(&mut self, auto_save: bool); + fn enable_enforce(&mut self, enabled: bool); + fn enable_auto_build_role_links(&mut self, auto_build_role_links: bool); + fn has_auto_save_enabled(&self) -> bool; +} diff --git a/src/emitter.rs b/src/emitter.rs index d45e250a..5fa4f4f2 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -1,5 +1,4 @@ -use crate::cached_enforcer::CachedEnforcer; -use crate::enforcer::Enforcer; +use crate::{cached_enforcer::CachedEnforcer, enforcer::Enforcer}; use emitbrown::Emitter; use lazy_static::lazy_static; diff --git a/src/enforcer.rs b/src/enforcer.rs index caaf185f..d44bdfe5 100644 --- a/src/enforcer.rs +++ b/src/enforcer.rs @@ -1,14 +1,17 @@ -use crate::adapter::Adapter; -use crate::convert::{TryIntoAdapter, TryIntoModel}; -use crate::effector::{DefaultEffector, EffectKind, Effector}; -use crate::emitter::{Event, EMITTER}; -use crate::error::{Error, ModelError, PolicyError, RequestError}; -use crate::model::FunctionMap; -use crate::model::Model; -use crate::rbac::{DefaultRoleManager, RoleManager}; -use crate::watcher::Watcher; -use crate::Result; - +use crate::{ + adapter::Adapter, + convert::{TryIntoAdapter, TryIntoModel}, + core_api::CoreApi, + effector::{DefaultEffector, EffectKind, Effector}, + emitter::{Event, EMITTER}, + error::{Error, ModelError, PolicyError, RequestError}, + model::{FunctionMap, Model}, + rbac::{DefaultRoleManager, RoleManager}, + watcher::Watcher, + Result, +}; + +use async_trait::async_trait; use emitbrown::Events; use rhai::{Array, Engine, RegisterFn, Scope}; @@ -61,9 +64,9 @@ pub struct Enforcer { pub(crate) watcher: Option>, } -impl Enforcer { - /// Enforcer::new creates an enforcer via file or DB. - pub async fn new(m: M, a: A) -> Result { +#[async_trait] +impl CoreApi for Enforcer { + async fn new(m: M, a: A) -> Result { let model = m.try_into_model().await?; let adapter = a.try_into_adapter().await?; let fm = FunctionMap::default(); @@ -96,52 +99,64 @@ impl Enforcer { Ok(e) } - pub fn add_function(&mut self, fname: &str, f: fn(String, String) -> bool) { + fn add_function(&mut self, fname: &str, f: fn(String, String) -> bool) { self.fm.add_function(fname, f); } - pub fn get_model(&self) -> &dyn Model { + #[inline] + fn get_model(&self) -> &dyn Model { &*self.model } - pub fn get_mut_model(&mut self) -> &mut dyn Model { + #[inline] + fn get_mut_model(&mut self) -> &mut dyn Model { &mut *self.model } - pub fn get_adapter(&self) -> &dyn Adapter { + #[inline] + fn get_adapter(&self) -> &dyn Adapter { &*self.adapter } - pub fn get_mut_adapter(&mut self) -> &mut dyn Adapter { + #[inline] + fn get_mut_adapter(&mut self) -> &mut dyn Adapter { &mut *self.adapter } - pub fn set_watcher(&mut self, w: Box) { + #[inline] + fn set_watcher(&mut self, w: Box) { self.watcher = Some(w); } - pub fn get_role_manager(&mut self) -> Arc> { + #[inline] + fn get_role_manager(&self) -> Arc> { Arc::clone(&self.rm) } - pub fn add_matching_fn(&mut self, f: fn(String, String) -> bool) -> Result<()> { + #[inline] + fn set_role_manager(&mut self, rm: Arc>) { + self.rm = rm; + } + + fn add_matching_fn(&mut self, f: fn(String, String) -> bool) -> Result<()> { self.rm.write().unwrap().add_matching_fn(f); self.build_role_links() } - pub async fn set_model(&mut self, m: M) -> Result<()> { + async fn set_model(&mut self, m: M) -> Result<()> { self.model = m.try_into_model().await?; self.load_policy().await?; Ok(()) } - pub async fn set_adapter(&mut self, a: A) -> Result<()> { + async fn set_adapter(&mut self, a: A) -> Result<()> { self.adapter = a.try_into_adapter().await?; self.load_policy().await?; Ok(()) } - pub fn set_effector(&mut self, e: Box) { + #[inline] + fn set_effector(&mut self, e: Box) { self.eft = e; } @@ -154,20 +169,20 @@ impl Enforcer { /// #[cfg(feature = "runtime-async-std")] /// #[async_std::main] /// async fn main() { - /// let e = Enforcer::new("examples/basic_model.conf", "examples/basic_policy.csv").await.unwrap(); - /// assert_eq!(true, e.enforce(&["alice", "data1", "read"]).unwrap()); + /// let mut e = Enforcer::new("examples/basic_model.conf", "examples/basic_policy.csv").await.unwrap(); + /// assert_eq!(true, e.enforce(&["alice", "data1", "read"]).await.unwrap()); /// } /// /// #[cfg(feature = "runtime-tokio")] /// #[tokio::main] /// async fn main() { - /// let e = Enforcer::new("examples/basic_model.conf", "examples/basic_policy.csv").await.unwrap(); - /// assert_eq!(true, e.enforce(&["alice", "data1", "read"]).unwrap()); + /// let mut e = Enforcer::new("examples/basic_model.conf", "examples/basic_policy.csv").await.unwrap(); + /// assert_eq!(true, e.enforce(&["alice", "data1", "read"]).await.unwrap()); /// } /// #[cfg(all(not(feature = "runtime-async-std"), not(feature = "runtime-tokio")))] /// fn main() {} /// ``` - pub fn enforce>(&self, rvals: &[S]) -> Result { + async fn enforce + Send + Sync>(&mut self, rvals: &[S]) -> Result { if !self.enabled { return Ok(true); } @@ -259,13 +274,13 @@ impl Enforcer { Ok(self.eft.merge_effects(&e_ast.value, policy_effects)) } - pub fn build_role_links(&mut self) -> Result<()> { + fn build_role_links(&mut self) -> Result<()> { self.rm.write().unwrap().clear(); self.model.build_role_links(Arc::clone(&self.rm))?; Ok(()) } - pub async fn load_policy(&mut self) -> Result<()> { + async fn load_policy(&mut self) -> Result<()> { self.model.clear_policy(); self.adapter.load_policy(&mut *self.model).await?; @@ -275,32 +290,42 @@ impl Enforcer { Ok(()) } - pub async fn save_policy(&mut self) -> Result<()> { - self.adapter.save_policy(&mut *self.model).await + async fn save_policy(&mut self) -> Result<()> { + self.adapter.save_policy(&mut *self.model).await?; + EMITTER.lock().unwrap().emit(Event::PolicyChange, self); + Ok(()) } - pub fn clear_policy(&mut self) { + #[inline] + fn clear_policy(&mut self) { self.model.clear_policy(); } - pub fn enable_enforce(&mut self, enabled: bool) { + #[inline] + fn enable_enforce(&mut self, enabled: bool) { self.enabled = enabled; } - pub fn enable_auto_save(&mut self, auto_save: bool) { + #[inline] + fn enable_auto_save(&mut self, auto_save: bool) { self.auto_save = auto_save; } - pub fn enable_auto_build_role_links(&mut self, auto_build_role_links: bool) { + #[inline] + fn enable_auto_build_role_links(&mut self, auto_build_role_links: bool) { self.auto_build_role_links = auto_build_role_links; } + + #[inline] + fn has_auto_save_enabled(&self) -> bool { + self.auto_save + } } #[cfg(test)] mod tests { use super::*; - use crate::adapter::{FileAdapter, MemoryAdapter}; - use crate::model::DefaultModel; + use crate::prelude::*; fn is_send() -> bool { true @@ -361,100 +386,122 @@ mod tests { ); let adapter = FileAdapter::new("examples/keymatch_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!( true, e.enforce(&vec!["alice", "/alice_data/resource1", "GET"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["alice", "/alice_data/resource1", "POST"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["alice", "/alice_data/resource2", "GET"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "/alice_data/resource2", "POST"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "/bob_data/resource1", "GET"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "/bob_data/resource1", "POST"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "/bob_data/resource2", "GET"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "/bob_data/resource2", "POST"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "/alice_data/resource1", "GET"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "/alice_data/resource1", "POST"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "/alice_data/resource2", "GET"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "/alice_data/resource2", "POST"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "/bob_data/resource1", "GET"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "/bob_data/resource1", "POST"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "/bob_data/resource2", "GET"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "/bob_data/resource2", "POST"]) + .await .unwrap() ); assert_eq!( true, - e.enforce(&vec!["cathy", "/cathy_data", "GET"]).unwrap() + e.enforce(&vec!["cathy", "/cathy_data", "GET"]) + .await + .unwrap() ); assert_eq!( true, - e.enforce(&vec!["cathy", "/cathy_data", "POST"]).unwrap() + e.enforce(&vec!["cathy", "/cathy_data", "POST"]) + .await + .unwrap() ); assert_eq!( false, - e.enforce(&vec!["cathy", "/cathy_data", "DELETE"]).unwrap() + e.enforce(&vec!["cathy", "/cathy_data", "DELETE"]) + .await + .unwrap() ); } @@ -472,10 +519,11 @@ mod tests { ); let adapter = FileAdapter::new("examples/keymatch_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!( true, e.enforce(&vec!["alice", "/alice_data/resource2", "POST"]) + .await .unwrap() ); } @@ -506,7 +554,10 @@ mod tests { ) .await .unwrap(); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -565,14 +616,38 @@ mod tests { .await .unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -610,14 +685,38 @@ mod tests { .await .unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -628,29 +727,71 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/ipmatch_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert!(e.enforce(&vec!["192.168.2.123", "data1", "read"]).unwrap()); + assert!(e + .enforce(&vec!["192.168.2.123", "data1", "read"]) + .await + .unwrap()); - assert!(e.enforce(&vec!["10.0.0.5", "data2", "write"]).unwrap()); + assert!(e + .enforce(&vec!["10.0.0.5", "data2", "write"]) + .await + .unwrap()); - assert!(!e.enforce(&vec!["192.168.2.123", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["192.168.2.123", "data2", "read"]).unwrap()); - assert!(!e.enforce(&vec!["192.168.2.123", "data2", "write"]).unwrap()); + assert!(!e + .enforce(&vec!["192.168.2.123", "data1", "write"]) + .await + .unwrap()); + assert!(!e + .enforce(&vec!["192.168.2.123", "data2", "read"]) + .await + .unwrap()); + assert!(!e + .enforce(&vec!["192.168.2.123", "data2", "write"]) + .await + .unwrap()); - assert!(!e.enforce(&vec!["192.168.0.123", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["192.168.0.123", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["192.168.0.123", "data2", "read"]).unwrap()); - assert!(!e.enforce(&vec!["192.168.0.123", "data2", "write"]).unwrap()); + assert!(!e + .enforce(&vec!["192.168.0.123", "data1", "read"]) + .await + .unwrap()); + assert!(!e + .enforce(&vec!["192.168.0.123", "data1", "write"]) + .await + .unwrap()); + assert!(!e + .enforce(&vec!["192.168.0.123", "data2", "read"]) + .await + .unwrap()); + assert!(!e + .enforce(&vec!["192.168.0.123", "data2", "write"]) + .await + .unwrap()); - assert!(!e.enforce(&vec!["10.0.0.5", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["10.0.0.5", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["10.0.0.5", "data2", "read"]).unwrap()); + assert!(!e.enforce(&vec!["10.0.0.5", "data1", "read"]).await.unwrap()); + assert!(!e + .enforce(&vec!["10.0.0.5", "data1", "write"]) + .await + .unwrap()); + assert!(!e.enforce(&vec!["10.0.0.5", "data2", "read"]).await.unwrap()); - assert!(!e.enforce(&vec!["192.168.0.1", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["192.168.0.1", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["192.168.0.1", "data2", "read"]).unwrap()); - assert!(!e.enforce(&vec!["192.168.0.1", "data2", "write"]).unwrap()); + assert!(!e + .enforce(&vec!["192.168.0.1", "data1", "read"]) + .await + .unwrap()); + assert!(!e + .enforce(&vec!["192.168.0.1", "data1", "write"]) + .await + .unwrap()); + assert!(!e + .enforce(&vec!["192.168.0.1", "data2", "read"]) + .await + .unwrap()); + assert!(!e + .enforce(&vec!["192.168.0.1", "data2", "write"]) + .await + .unwrap()); } use crate::MgmtApi; @@ -674,14 +815,38 @@ mod tests { .unwrap(); e.load_policy().await.unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); e.enable_auto_save(true); e.remove_policy( @@ -693,14 +858,38 @@ mod tests { .await .unwrap(); e.load_policy().await.unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -714,7 +903,10 @@ mod tests { let mut e = Enforcer::new(m, adapter).await.unwrap(); e.enable_auto_build_role_links(false); e.build_role_links().unwrap(); - assert_eq!(false, e.enforce(&vec!["user501", "data9", "read"]).unwrap()); + assert_eq!( + false, + e.enforce(&vec!["user501", "data9", "read"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -726,7 +918,10 @@ mod tests { let adapter1 = FileAdapter::new("examples/basic_policy.csv"); let mut e = Enforcer::new(m1, adapter1).await.unwrap(); - assert_eq!(false, e.enforce(&vec!["root", "data1", "read"]).unwrap()); + assert_eq!( + false, + e.enforce(&vec!["root", "data1", "read"]).await.unwrap() + ); let m2 = DefaultModel::from_file("examples/basic_with_root_model.conf") .await @@ -735,7 +930,10 @@ mod tests { let e2 = Enforcer::new(m2, adapter2).await.unwrap(); e.model = e2.model; - assert_eq!(true, e.enforce(&vec!["root", "data1", "read"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["root", "data1", "read"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -747,8 +945,14 @@ mod tests { let adapter1 = FileAdapter::new("examples/basic_policy.csv"); let mut e = Enforcer::new(m1, adapter1).await.unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); let m2 = DefaultModel::from_file("examples/basic_model.conf") .await @@ -758,8 +962,14 @@ mod tests { e.adapter = e2.adapter; e.load_policy().await.unwrap(); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -777,33 +987,42 @@ mod tests { assert_eq!( true, - e.enforce(&vec!["alice", "/alice_data/123", "GET"]).unwrap() + e.enforce(&vec!["alice", "/alice_data/123", "GET"]) + .await + .unwrap() ); assert_eq!( true, e.enforce(&vec!["alice", "/alice_data/resource1", "POST"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "/alice_data/resource2", "GET"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "/bob_data/resource1", "POST"]) + .await .unwrap() ); assert_eq!( true, - e.enforce(&vec!["cathy", "/cathy_data", "GET"]).unwrap() + e.enforce(&vec!["cathy", "/cathy_data", "GET"]) + .await + .unwrap() ); assert_eq!( true, - e.enforce(&vec!["cathy", "/cathy_data", "POST"]).unwrap() + e.enforce(&vec!["cathy", "/cathy_data", "POST"]) + .await + .unwrap() ); } } diff --git a/src/internal_api.rs b/src/internal_api.rs index e0abbd10..da9ec6c1 100644 --- a/src/internal_api.rs +++ b/src/internal_api.rs @@ -1,13 +1,16 @@ -use crate::cached_enforcer::CachedEnforcer; -use crate::emitter::{Event, CACHED_EMITTER, EMITTER}; -use crate::enforcer::Enforcer; -use crate::Result; +use crate::{ + cached_enforcer::CachedEnforcer, + core_api::CoreApi, + emitter::{Event, CACHED_EMITTER, EMITTER}, + enforcer::Enforcer, + Result, +}; use async_trait::async_trait; use emitbrown::Events; #[async_trait] -pub trait InternalApi { +pub trait InternalApi: CoreApi { async fn add_policy_internal( &mut self, sec: &str, @@ -49,11 +52,16 @@ impl InternalApi for Enforcer { ptype: &str, rule: Vec, ) -> Result { - if self.auto_save && !self.adapter.add_policy(sec, ptype, rule.clone()).await? { + if self.has_auto_save_enabled() + && !self + .get_mut_adapter() + .add_policy(sec, ptype, rule.clone()) + .await? + { return Ok(false); } - let rule_added = self.model.add_policy(sec, ptype, rule); + let rule_added = self.get_mut_model().add_policy(sec, ptype, rule); if rule_added { EMITTER.lock().unwrap().emit(Event::PolicyChange, self); } @@ -67,11 +75,16 @@ impl InternalApi for Enforcer { ptype: &str, rules: Vec>, ) -> Result { - if self.auto_save && !self.adapter.add_policies(sec, ptype, rules.clone()).await? { + if self.has_auto_save_enabled() + && !self + .get_mut_adapter() + .add_policies(sec, ptype, rules.clone()) + .await? + { return Ok(false); } - let rules_added = self.model.add_policies(sec, ptype, rules); + let rules_added = self.get_mut_model().add_policies(sec, ptype, rules); if rules_added { EMITTER.lock().unwrap().emit(Event::PolicyChange, self); } @@ -85,11 +98,16 @@ impl InternalApi for Enforcer { ptype: &str, rule: Vec, ) -> Result { - if self.auto_save && !self.adapter.remove_policy(sec, ptype, rule.clone()).await? { + if self.has_auto_save_enabled() + && !self + .get_mut_adapter() + .remove_policy(sec, ptype, rule.clone()) + .await? + { return Ok(false); } - let rule_removed = self.model.remove_policy(sec, ptype, rule); + let rule_removed = self.get_mut_model().remove_policy(sec, ptype, rule); if rule_removed { EMITTER.lock().unwrap().emit(Event::PolicyChange, self); } @@ -103,16 +121,16 @@ impl InternalApi for Enforcer { ptype: &str, rules: Vec>, ) -> Result { - if self.auto_save + if self.has_auto_save_enabled() && !self - .adapter + .get_mut_adapter() .remove_policies(sec, ptype, rules.clone()) .await? { return Ok(false); } - let rules_removed = self.model.remove_policies(sec, ptype, rules); + let rules_removed = self.get_mut_model().remove_policies(sec, ptype, rules); if rules_removed { EMITTER.lock().unwrap().emit(Event::PolicyChange, self); } @@ -127,9 +145,9 @@ impl InternalApi for Enforcer { field_index: usize, field_values: Vec, ) -> Result { - if self.auto_save + if self.has_auto_save_enabled() && !self - .adapter + .get_mut_adapter() .remove_filtered_policy(sec, ptype, field_index, field_values.clone()) .await? { @@ -137,7 +155,7 @@ impl InternalApi for Enforcer { } let rules_removed = - self.model + self.get_mut_model() .remove_filtered_policy(sec, ptype, field_index, field_values); if rules_removed { EMITTER.lock().unwrap().emit(Event::PolicyChange, self); diff --git a/src/lib.rs b/src/lib.rs index 12bece98..630b1318 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,10 @@ mod adapter; mod cache; +mod cached_api; mod cached_enforcer; mod config; mod convert; +mod core_api; mod effector; mod emitter; mod enforcer; @@ -18,14 +20,18 @@ pub mod error; pub mod prelude; pub use adapter::{Adapter, FileAdapter, MemoryAdapter}; -pub use cache::Cache; +pub use cache::{Cache, DefaultCache}; +pub use cached_api::CachedApi; pub use cached_enforcer::CachedEnforcer; pub use convert::{TryIntoAdapter, TryIntoModel}; +pub use core_api::CoreApi; +pub use effector::{DefaultEffector, EffectKind, Effector}; pub use enforcer::Enforcer; pub use error::Error; pub use internal_api::InternalApi; pub use management_api::MgmtApi; pub use model::{DefaultModel, Model}; +pub use rbac::{DefaultRoleManager, RoleManager}; pub use rbac_api::RbacApi; pub use watcher::Watcher; diff --git a/src/management_api.rs b/src/management_api.rs index 723c5af3..cbf28aaa 100644 --- a/src/management_api.rs +++ b/src/management_api.rs @@ -1,109 +1,9 @@ -use crate::cached_enforcer::CachedEnforcer; -use crate::enforcer::Enforcer; -use crate::InternalApi; -use crate::Result; +use crate::{InternalApi, Result}; use async_trait::async_trait; #[async_trait] -pub trait MgmtApi { - async fn add_policy(&mut self, params: Vec) -> Result; - async fn add_policies(&mut self, paramss: Vec>) -> Result; - async fn remove_policy(&mut self, params: Vec) -> Result; - async fn remove_policies(&mut self, paramss: Vec>) -> Result; - async fn add_named_policy(&mut self, ptype: &str, params: Vec) -> Result; - async fn add_named_policies(&mut self, ptype: &str, paramss: Vec>) -> Result; - async fn remove_named_policy(&mut self, ptype: &str, params: Vec) -> Result; - async fn remove_named_policies( - &mut self, - ptype: &str, - paramss: Vec>, - ) -> Result; - async fn add_grouping_policy(&mut self, params: Vec) -> Result; - async fn add_grouping_policies(&mut self, paramss: Vec>) -> Result; - async fn remove_grouping_policy(&mut self, params: Vec) -> Result; - async fn remove_grouping_policies(&mut self, paramss: Vec>) -> Result; - async fn add_named_grouping_policy(&mut self, ptype: &str, params: Vec) - -> Result; - async fn add_named_grouping_policies( - &mut self, - ptype: &str, - paramss: Vec>, - ) -> Result; - async fn remove_named_grouping_policy( - &mut self, - ptype: &str, - params: Vec, - ) -> Result; - async fn remove_named_grouping_policies( - &mut self, - ptype: &str, - paramss: Vec>, - ) -> Result; - async fn remove_filtered_policy( - &mut self, - field_index: usize, - field_values: Vec, - ) -> Result; - async fn remove_filtered_grouping_policy( - &mut self, - field_index: usize, - field_values: Vec, - ) -> Result; - async fn remove_filtered_named_policy( - &mut self, - ptype: &str, - field_index: usize, - field_values: Vec, - ) -> Result; - async fn remove_filtered_named_grouping_policy( - &mut self, - ptype: &str, - field_index: usize, - field_values: Vec, - ) -> Result; - fn get_policy(&self) -> Vec>; - fn get_named_policy(&self, ptype: &str) -> Vec>; - fn get_filtered_policy( - &self, - field_index: usize, - field_values: Vec, - ) -> Vec>; - fn get_filtered_named_policy( - &self, - ptype: &str, - field_index: usize, - field_values: Vec, - ) -> Vec>; - fn has_policy(&self, params: Vec) -> bool; - fn has_named_policy(&self, ptype: &str, params: Vec) -> bool; - fn get_grouping_policy(&self) -> Vec>; - fn get_named_grouping_policy(&self, ptype: &str) -> Vec>; - fn get_filtered_grouping_policy( - &self, - field_index: usize, - field_values: Vec, - ) -> Vec>; - fn get_filtered_named_grouping_policy( - &self, - ptype: &str, - field_index: usize, - field_values: Vec, - ) -> Vec>; - fn has_grouping_policy(&self, params: Vec) -> bool; - fn has_grouping_named_policy(&self, ptype: &str, params: Vec) -> bool; - fn get_all_subjects(&self) -> Vec; - fn get_all_named_subjects(&self, ptype: &str) -> Vec; - fn get_all_objects(&self) -> Vec; - fn get_all_named_objects(&self, ptype: &str) -> Vec; - fn get_all_actions(&self) -> Vec; - fn get_all_named_actions(&self, ptype: &str) -> Vec; - fn get_all_roles(&self) -> Vec; - fn get_all_named_roles(&self, ptype: &str) -> Vec; -} - -#[async_trait] -impl MgmtApi for Enforcer { +pub trait MgmtApi: InternalApi { async fn add_policy(&mut self, params: Vec) -> Result { self.add_named_policy("p", params).await } @@ -120,25 +20,14 @@ impl MgmtApi for Enforcer { self.remove_named_policies("p", paramss).await } - async fn add_named_policy(&mut self, ptype: &str, params: Vec) -> Result { - self.add_policy_internal("p", ptype, params).await - } - - async fn add_named_policies(&mut self, ptype: &str, paramss: Vec>) -> Result { - self.add_policies_internal("p", ptype, paramss).await - } - - async fn remove_named_policy(&mut self, ptype: &str, params: Vec) -> Result { - self.remove_policy_internal("p", ptype, params).await - } - + async fn add_named_policy(&mut self, ptype: &str, params: Vec) -> Result; + async fn add_named_policies(&mut self, ptype: &str, paramss: Vec>) -> Result; + async fn remove_named_policy(&mut self, ptype: &str, params: Vec) -> Result; async fn remove_named_policies( &mut self, ptype: &str, paramss: Vec>, - ) -> Result { - self.remove_policies_internal("p", ptype, paramss).await - } + ) -> Result; async fn add_grouping_policy(&mut self, params: Vec) -> Result { self.add_named_grouping_policy("g", params).await @@ -148,26 +37,6 @@ impl MgmtApi for Enforcer { self.add_named_grouping_policies("g", paramss).await } - async fn add_named_grouping_policy( - &mut self, - ptype: &str, - params: Vec, - ) -> Result { - let rule_added = self.add_policy_internal("g", ptype, params).await?; - self.build_role_links()?; - Ok(rule_added) - } - - async fn add_named_grouping_policies( - &mut self, - ptype: &str, - paramss: Vec>, - ) -> Result { - let all_added = self.add_policies_internal("g", ptype, paramss).await?; - self.build_role_links()?; - Ok(all_added) - } - async fn remove_grouping_policy(&mut self, params: Vec) -> Result { self.remove_named_grouping_policy("g", params).await } @@ -176,74 +45,60 @@ impl MgmtApi for Enforcer { self.remove_named_grouping_policies("g", paramss).await } + async fn add_named_grouping_policy(&mut self, ptype: &str, params: Vec) + -> Result; + async fn add_named_grouping_policies( + &mut self, + ptype: &str, + paramss: Vec>, + ) -> Result; async fn remove_named_grouping_policy( &mut self, ptype: &str, params: Vec, - ) -> Result { - let rule_removed = self.remove_policy_internal("g", ptype, params).await?; - self.build_role_links()?; - Ok(rule_removed) - } - + ) -> Result; async fn remove_named_grouping_policies( &mut self, ptype: &str, paramss: Vec>, - ) -> Result { - let all_removed = self.remove_policies_internal("g", ptype, paramss).await?; - self.build_role_links()?; - Ok(all_removed) - } + ) -> Result; - async fn remove_filtered_grouping_policy( + async fn remove_filtered_policy( &mut self, field_index: usize, field_values: Vec, ) -> Result { - self.remove_filtered_named_grouping_policy("g", field_index, field_values) + self.remove_filtered_named_policy("p", field_index, field_values) .await } - async fn remove_filtered_named_grouping_policy( + async fn remove_filtered_grouping_policy( &mut self, - ptype: &str, field_index: usize, field_values: Vec, ) -> Result { - let rule_removed = self - .remove_filtered_policy_internal("g", ptype, field_index, field_values) - .await?; - self.build_role_links()?; - Ok(rule_removed) + self.remove_filtered_named_grouping_policy("g", field_index, field_values) + .await } - async fn remove_filtered_policy( + async fn remove_filtered_named_policy( &mut self, + ptype: &str, field_index: usize, field_values: Vec, - ) -> Result { - self.remove_filtered_named_policy("p", field_index, field_values) - .await - } - - async fn remove_filtered_named_policy( + ) -> Result; + async fn remove_filtered_named_grouping_policy( &mut self, ptype: &str, field_index: usize, field_values: Vec, - ) -> Result { - self.remove_filtered_policy_internal("p", ptype, field_index, field_values) - .await - } + ) -> Result; fn get_policy(&self) -> Vec> { self.get_named_policy("p") } - fn get_named_policy(&self, ptype: &str) -> Vec> { - self.model.get_policy("p", ptype) - } + fn get_named_policy(&self, ptype: &str) -> Vec>; fn get_filtered_policy( &self, @@ -258,25 +113,19 @@ impl MgmtApi for Enforcer { ptype: &str, field_index: usize, field_values: Vec, - ) -> Vec> { - self.model - .get_filtered_policy("p", ptype, field_index, field_values) - } + ) -> Vec>; fn has_policy(&self, params: Vec) -> bool { self.has_named_policy("p", params) } - fn has_named_policy(&self, ptype: &str, params: Vec) -> bool { - self.model.has_policy("p", ptype, params) - } + fn has_named_policy(&self, ptype: &str, params: Vec) -> bool; fn get_grouping_policy(&self) -> Vec> { self.get_named_grouping_policy("g") } - fn get_named_grouping_policy(&self, ptype: &str) -> Vec> { - self.model.get_policy("g", ptype) - } + + fn get_named_grouping_policy(&self, ptype: &str) -> Vec>; fn get_filtered_grouping_policy( &self, @@ -285,85 +134,58 @@ impl MgmtApi for Enforcer { ) -> Vec> { 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, - ) -> Vec> { - self.model - .get_filtered_policy("g", ptype, field_index, field_values) - } - + ) -> Vec>; fn has_grouping_policy(&self, params: Vec) -> bool { self.has_grouping_named_policy("g", params) } - - fn has_grouping_named_policy(&self, ptype: &str, params: Vec) -> bool { - self.model.has_policy("g", ptype, params) - } + fn has_grouping_named_policy(&self, ptype: &str, params: Vec) -> bool; fn get_all_subjects(&self) -> Vec { self.get_all_named_subjects("p") } - fn get_all_named_subjects(&self, ptype: &str) -> Vec { - self.model.get_values_for_field_in_policy("p", ptype, 0) - } + fn get_all_named_subjects(&self, ptype: &str) -> Vec; fn get_all_objects(&self) -> Vec { self.get_all_named_objects("p") } - fn get_all_named_objects(&self, ptype: &str) -> Vec { - self.model.get_values_for_field_in_policy("p", ptype, 1) - } + fn get_all_named_objects(&self, ptype: &str) -> Vec; fn get_all_actions(&self) -> Vec { self.get_all_named_actions("p") } - fn get_all_named_actions(&self, ptype: &str) -> Vec { - self.model.get_values_for_field_in_policy("p", ptype, 2) - } - fn get_all_roles(&self) -> Vec { self.get_all_named_roles("g") } - fn get_all_named_roles(&self, ptype: &str) -> Vec { - self.model.get_values_for_field_in_policy("g", ptype, 1) - } + fn get_all_named_actions(&self, ptype: &str) -> Vec; + + fn get_all_named_roles(&self, ptype: &str) -> Vec; } #[async_trait] -impl MgmtApi for CachedEnforcer { - async fn add_policy(&mut self, params: Vec) -> Result { - self.enforcer.add_policy(params).await - } - - async fn add_policies(&mut self, paramss: Vec>) -> Result { - self.enforcer.add_policies(paramss).await - } - - async fn remove_policy(&mut self, params: Vec) -> Result { - self.enforcer.remove_policy(params).await - } - - async fn remove_policies(&mut self, paramss: Vec>) -> Result { - self.enforcer.remove_policies(paramss).await - } - +impl MgmtApi for T +where + T: InternalApi, +{ async fn add_named_policy(&mut self, ptype: &str, params: Vec) -> Result { - self.enforcer.add_named_policy(ptype, params).await + self.add_policy_internal("p", ptype, params).await } async fn add_named_policies(&mut self, ptype: &str, paramss: Vec>) -> Result { - self.enforcer.add_named_policies(ptype, paramss).await + self.add_policies_internal("p", ptype, paramss).await } async fn remove_named_policy(&mut self, ptype: &str, params: Vec) -> Result { - self.enforcer.remove_named_policy(ptype, params).await + self.remove_policy_internal("p", ptype, params).await } async fn remove_named_policies( @@ -371,23 +193,7 @@ impl MgmtApi for CachedEnforcer { ptype: &str, paramss: Vec>, ) -> Result { - self.enforcer.remove_named_policies(ptype, paramss).await - } - - async fn add_grouping_policy(&mut self, params: Vec) -> Result { - self.enforcer.add_grouping_policy(params).await - } - - async fn add_grouping_policies(&mut self, paramss: Vec>) -> Result { - self.enforcer.add_grouping_policies(paramss).await - } - - async fn remove_grouping_policy(&mut self, params: Vec) -> Result { - self.enforcer.remove_grouping_policy(params).await - } - - async fn remove_grouping_policies(&mut self, paramss: Vec>) -> Result { - self.enforcer.remove_grouping_policies(paramss).await + self.remove_policies_internal("p", ptype, paramss).await } async fn add_named_grouping_policy( @@ -395,7 +201,9 @@ impl MgmtApi for CachedEnforcer { ptype: &str, params: Vec, ) -> Result { - self.enforcer.add_named_grouping_policy(ptype, params).await + let rule_added = self.add_policy_internal("g", ptype, params).await?; + self.build_role_links()?; + Ok(rule_added) } async fn add_named_grouping_policies( @@ -403,9 +211,9 @@ impl MgmtApi for CachedEnforcer { ptype: &str, paramss: Vec>, ) -> Result { - self.enforcer - .add_named_grouping_policies(ptype, paramss) - .await + let all_added = self.add_policies_internal("g", ptype, paramss).await?; + self.build_role_links()?; + Ok(all_added) } async fn remove_named_grouping_policy( @@ -413,9 +221,9 @@ impl MgmtApi for CachedEnforcer { ptype: &str, params: Vec, ) -> Result { - self.enforcer - .remove_named_grouping_policy(ptype, params) - .await + let rule_removed = self.remove_policy_internal("g", ptype, params).await?; + self.build_role_links()?; + Ok(rule_removed) } async fn remove_named_grouping_policies( @@ -423,67 +231,36 @@ impl MgmtApi for CachedEnforcer { ptype: &str, paramss: Vec>, ) -> Result { - self.enforcer - .remove_named_grouping_policies(ptype, paramss) - .await - } - - async fn remove_filtered_policy( - &mut self, - field_index: usize, - field_values: Vec, - ) -> Result { - self.enforcer - .remove_filtered_policy(field_index, field_values) - .await - } - - async fn remove_filtered_grouping_policy( - &mut self, - field_index: usize, - field_values: Vec, - ) -> Result { - self.enforcer - .remove_filtered_grouping_policy(field_index, field_values) - .await + let all_removed = self.remove_policies_internal("g", ptype, paramss).await?; + self.build_role_links()?; + Ok(all_removed) } - async fn remove_filtered_named_policy( + async fn remove_filtered_named_grouping_policy( &mut self, ptype: &str, field_index: usize, field_values: Vec, ) -> Result { - self.enforcer - .remove_filtered_named_policy(ptype, field_index, field_values) - .await + let rule_removed = self + .remove_filtered_policy_internal("g", ptype, field_index, field_values) + .await?; + self.build_role_links()?; + Ok(rule_removed) } - async fn remove_filtered_named_grouping_policy( + async fn remove_filtered_named_policy( &mut self, ptype: &str, field_index: usize, field_values: Vec, ) -> Result { - self.enforcer - .remove_filtered_named_grouping_policy(ptype, field_index, field_values) + self.remove_filtered_policy_internal("p", ptype, field_index, field_values) .await } - fn get_policy(&self) -> Vec> { - self.enforcer.get_policy() - } - fn get_named_policy(&self, ptype: &str) -> Vec> { - self.enforcer.get_named_policy(ptype) - } - - fn get_filtered_policy( - &self, - field_index: usize, - field_values: Vec, - ) -> Vec> { - self.enforcer.get_filtered_policy(field_index, field_values) + self.get_model().get_policy("p", ptype) } fn get_filtered_named_policy( @@ -492,33 +269,16 @@ impl MgmtApi for CachedEnforcer { field_index: usize, field_values: Vec, ) -> Vec> { - self.enforcer - .get_filtered_named_policy(ptype, field_index, field_values) - } - - fn has_policy(&self, params: Vec) -> bool { - self.enforcer.has_policy(params) + self.get_model() + .get_filtered_policy("p", ptype, field_index, field_values) } fn has_named_policy(&self, ptype: &str, params: Vec) -> bool { - self.enforcer.has_named_policy(ptype, params) - } - - fn get_grouping_policy(&self) -> Vec> { - self.enforcer.get_grouping_policy() + self.get_model().has_policy("p", ptype, params) } fn get_named_grouping_policy(&self, ptype: &str) -> Vec> { - self.enforcer.get_named_grouping_policy(ptype) - } - - fn get_filtered_grouping_policy( - &self, - field_index: usize, - field_values: Vec, - ) -> Vec> { - self.enforcer - .get_filtered_grouping_policy(field_index, field_values) + self.get_model().get_policy("g", ptype) } fn get_filtered_named_grouping_policy( @@ -527,58 +287,38 @@ impl MgmtApi for CachedEnforcer { field_index: usize, field_values: Vec, ) -> Vec> { - self.enforcer - .get_filtered_named_grouping_policy(ptype, field_index, field_values) - } - - fn has_grouping_policy(&self, params: Vec) -> bool { - self.enforcer.has_grouping_policy(params) + self.get_model() + .get_filtered_policy("g", ptype, field_index, field_values) } fn has_grouping_named_policy(&self, ptype: &str, params: Vec) -> bool { - self.enforcer.has_grouping_named_policy(ptype, params) - } - - fn get_all_subjects(&self) -> Vec { - self.enforcer.get_all_subjects() + self.get_model().has_policy("g", ptype, params) } fn get_all_named_subjects(&self, ptype: &str) -> Vec { - self.enforcer.get_all_named_subjects(ptype) - } - - fn get_all_objects(&self) -> Vec { - self.enforcer.get_all_objects() + self.get_model() + .get_values_for_field_in_policy("p", ptype, 0) } fn get_all_named_objects(&self, ptype: &str) -> Vec { - self.enforcer.get_all_named_objects(ptype) - } - - fn get_all_actions(&self) -> Vec { - self.enforcer.get_all_actions() + self.get_model() + .get_values_for_field_in_policy("p", ptype, 1) } fn get_all_named_actions(&self, ptype: &str) -> Vec { - self.enforcer.get_all_named_actions(ptype) - } - - fn get_all_roles(&self) -> Vec { - self.enforcer.get_all_roles() + self.get_model() + .get_values_for_field_in_policy("p", ptype, 2) } fn get_all_named_roles(&self, ptype: &str) -> Vec { - self.enforcer.get_all_named_roles(ptype) + self.get_model() + .get_values_for_field_in_policy("g", ptype, 1) } } #[cfg(test)] mod tests { - use super::*; - use crate::adapter::FileAdapter; - use crate::enforcer::Enforcer; - use crate::model::DefaultModel; - use crate::RbacApi; + use crate::prelude::*; fn sort_unstable(mut v: Vec) -> Vec { v.sort_unstable(); diff --git a/src/model/assertion.rs b/src/model/assertion.rs index 2be08aad..7b6771d3 100644 --- a/src/model/assertion.rs +++ b/src/model/assertion.rs @@ -1,11 +1,15 @@ -use crate::error::{ModelError, PolicyError}; -use crate::rbac::{DefaultRoleManager, RoleManager}; -use crate::Result; +use crate::{ + error::{ModelError, PolicyError}, + rbac::{DefaultRoleManager, RoleManager}, + Result, +}; use indexmap::IndexSet; -use std::collections::HashMap; -use std::sync::{Arc, RwLock}; +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, +}; pub(crate) type AssertionMap = HashMap; diff --git a/src/model/default_model.rs b/src/model/default_model.rs index f87f2757..e8f8a260 100644 --- a/src/model/default_model.rs +++ b/src/model/default_model.rs @@ -1,19 +1,24 @@ -use crate::config::Config; -use crate::error::ModelError; -use crate::model::{Assertion, AssertionMap, Model}; -use crate::rbac::RoleManager; -use crate::util::*; -use crate::Result; +use crate::{ + config::Config, + error::ModelError, + model::{Assertion, AssertionMap, Model}, + rbac::RoleManager, + util::*, + Result, +}; + +use indexmap::IndexSet; #[cfg(feature = "runtime-async-std")] use async_std::path::Path; -use indexmap::IndexSet; -use std::collections::HashMap; -use std::convert::AsRef; #[cfg(feature = "runtime-tokio")] use std::path::Path; -use std::sync::{Arc, RwLock}; + +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, +}; #[derive(Clone, Default)] pub struct DefaultModel { @@ -123,10 +128,12 @@ impl Model for DefaultModel { true } + #[inline] fn get_model(&self) -> &HashMap { &self.model } + #[inline] fn get_mut_model(&mut self) -> &mut HashMap { &mut self.model } @@ -308,10 +315,8 @@ impl Model for DefaultModel { #[cfg(test)] mod tests { - use super::*; + use crate::prelude::*; - use crate::adapter::{FileAdapter, MemoryAdapter}; - use crate::enforcer::Enforcer; #[cfg_attr(feature = "runtime-async-std", async_std::test)] #[cfg_attr(feature = "runtime-tokio", tokio::test)] async fn test_basic_model() { @@ -320,16 +325,16 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/basic_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert!(e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert!(e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert!(e.enforce(&vec!["alice", "data1", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data2", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data2", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data1", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data2", "read"]).await.unwrap()); + assert!(e.enforce(&vec!["bob", "data2", "write"]).await.unwrap()); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -340,16 +345,16 @@ mod tests { .unwrap(); let adapter = MemoryAdapter::default(); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert!(!e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert!(!e.enforce(&vec!["alice", "data1", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data2", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data2", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data1", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data2", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data2", "write"]).await.unwrap()); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -360,20 +365,20 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/basic_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); - - assert!(e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert!(e.enforce(&vec!["bob", "data2", "write"]).unwrap()); - assert!(e.enforce(&vec!["root", "data1", "read"]).unwrap()); - assert!(e.enforce(&vec!["root", "data1", "write"]).unwrap()); - assert!(e.enforce(&vec!["root", "data2", "read"]).unwrap()); - assert!(e.enforce(&vec!["root", "data2", "write"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data2", "read"]).unwrap()); + let mut e = Enforcer::new(m, adapter).await.unwrap(); + + assert!(e.enforce(&vec!["alice", "data1", "read"]).await.unwrap()); + assert!(e.enforce(&vec!["bob", "data2", "write"]).await.unwrap()); + assert!(e.enforce(&vec!["root", "data1", "read"]).await.unwrap()); + assert!(e.enforce(&vec!["root", "data1", "write"]).await.unwrap()); + assert!(e.enforce(&vec!["root", "data2", "read"]).await.unwrap()); + assert!(e.enforce(&vec!["root", "data2", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data2", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data2", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data1", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data2", "read"]).await.unwrap()); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -384,20 +389,20 @@ mod tests { .unwrap(); let adapter = MemoryAdapter::default(); - let e = Enforcer::new(m, adapter).await.unwrap(); - - assert!(!e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data2", "write"]).unwrap()); - assert!(e.enforce(&vec!["root", "data1", "read"]).unwrap()); - assert!(e.enforce(&vec!["root", "data1", "write"]).unwrap()); - assert!(e.enforce(&vec!["root", "data2", "read"]).unwrap()); - assert!(e.enforce(&vec!["root", "data2", "write"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "data2", "read"]).unwrap()); + let mut e = Enforcer::new(m, adapter).await.unwrap(); + + assert!(!e.enforce(&vec!["alice", "data1", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data2", "write"]).await.unwrap()); + assert!(e.enforce(&vec!["root", "data1", "read"]).await.unwrap()); + assert!(e.enforce(&vec!["root", "data1", "write"]).await.unwrap()); + assert!(e.enforce(&vec!["root", "data2", "read"]).await.unwrap()); + assert!(e.enforce(&vec!["root", "data2", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data2", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "data2", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data1", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "data2", "read"]).await.unwrap()); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -408,12 +413,12 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/basic_without_users_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert!(e.enforce(&vec!["data1", "read"]).unwrap()); - assert!(!e.enforce(&vec!["data1", "write"]).unwrap()); - assert!(!e.enforce(&vec!["data2", "read"]).unwrap()); - assert!(e.enforce(&vec!["data2", "write"]).unwrap()); + assert!(e.enforce(&vec!["data1", "read"]).await.unwrap()); + assert!(!e.enforce(&vec!["data1", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["data2", "read"]).await.unwrap()); + assert!(e.enforce(&vec!["data2", "write"]).await.unwrap()); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -424,12 +429,12 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/basic_without_resources_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert!(e.enforce(&vec!["alice", "read"]).unwrap()); - assert!(e.enforce(&vec!["bob", "write"]).unwrap()); - assert!(!e.enforce(&vec!["alice", "write"]).unwrap()); - assert!(!e.enforce(&vec!["bob", "read"]).unwrap()); + assert!(e.enforce(&vec!["alice", "read"]).await.unwrap()); + assert!(e.enforce(&vec!["bob", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["alice", "write"]).await.unwrap()); + assert!(!e.enforce(&vec!["bob", "read"]).await.unwrap()); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -440,16 +445,40 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -460,16 +489,40 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/rbac_with_resource_roles_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -480,44 +533,54 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/rbac_with_domains_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!( true, e.enforce(&vec!["alice", "domain1", "data1", "read"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["alice", "domain1", "data1", "write"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data2", "read"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data2", "write"]) + .await .unwrap() ); assert_eq!( false, - e.enforce(&vec!["bob", "domain2", "data1", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data1", "read"]) + .await + .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "domain2", "data1", "write"]) + .await .unwrap() ); assert_eq!( true, - e.enforce(&vec!["bob", "domain2", "data2", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data2", "read"]) + .await + .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "domain2", "data2", "write"]) + .await .unwrap() ); } @@ -585,39 +648,49 @@ mod tests { assert_eq!( true, e.enforce(&vec!["alice", "domain1", "data1", "read"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["alice", "domain1", "data1", "write"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data2", "read"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data2", "write"]) + .await .unwrap() ); assert_eq!( false, - e.enforce(&vec!["bob", "domain2", "data1", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data1", "read"]) + .await + .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "domain2", "data1", "write"]) + .await .unwrap() ); assert_eq!( true, - e.enforce(&vec!["bob", "domain2", "data2", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data2", "read"]) + .await + .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "domain2", "data2", "write"]) + .await .unwrap() ); @@ -637,39 +710,49 @@ mod tests { assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data1", "read"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data1", "write"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data2", "read"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data2", "write"]) + .await .unwrap() ); assert_eq!( false, - e.enforce(&vec!["bob", "domain2", "data1", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data1", "read"]) + .await + .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "domain2", "data1", "write"]) + .await .unwrap() ); assert_eq!( true, - e.enforce(&vec!["bob", "domain2", "data2", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data2", "read"]) + .await + .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "domain2", "data2", "write"]) + .await .unwrap() ); @@ -688,39 +771,49 @@ mod tests { assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data1", "read"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data1", "write"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data2", "read"]) + .await .unwrap() ); assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data2", "write"]) + .await .unwrap() ); assert_eq!( false, - e.enforce(&vec!["bob", "domain2", "data1", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data1", "read"]) + .await + .unwrap() ); assert_eq!( false, e.enforce(&vec!["bob", "domain2", "data1", "write"]) + .await .unwrap() ); assert_eq!( false, - e.enforce(&vec!["bob", "domain2", "data2", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data2", "read"]) + .await + .unwrap() ); assert_eq!( true, e.enforce(&vec!["bob", "domain2", "data2", "write"]) + .await .unwrap() ); } @@ -755,11 +848,13 @@ mod tests { assert_eq!( true, e.enforce(&vec!["alice", "domain3", "data1", "read"]) + .await .unwrap() ); assert_eq!( true, e.enforce(&vec!["alice", "domain1", "data1", "read"]) + .await .unwrap() ); @@ -775,11 +870,14 @@ mod tests { assert_eq!( false, e.enforce(&vec!["alice", "domain1", "data1", "read"]) + .await .unwrap() ); assert_eq!( true, - e.enforce(&vec!["bob", "domain2", "data2", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data2", "read"]) + .await + .unwrap() ); e.remove_policy( @@ -792,7 +890,9 @@ mod tests { .unwrap(); assert_eq!( false, - e.enforce(&vec!["bob", "domain2", "data2", "read"]).unwrap() + e.enforce(&vec!["bob", "domain2", "data2", "read"]) + .await + .unwrap() ); } @@ -804,16 +904,40 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/rbac_with_deny_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -824,9 +948,12 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/rbac_with_deny_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -848,14 +975,38 @@ mod tests { .await .unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); e.remove_grouping_policy( vec!["bob", "data2_admin", "custom_data"] @@ -866,14 +1017,38 @@ mod tests { .await .unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -884,15 +1059,39 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); - - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["guest", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data3", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data3", "read"]).unwrap()); + let mut e = Enforcer::new(m, adapter).await.unwrap(); + + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["guest", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data3", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data3", "read"]).await.unwrap() + ); } } diff --git a/src/model/function_map.rs b/src/model/function_map.rs index 2c3de585..1e4d901b 100644 --- a/src/model/function_map.rs +++ b/src/model/function_map.rs @@ -1,13 +1,14 @@ #[cfg(feature = "runtime-async-std")] use async_std::net::IpAddr; -use globset::GlobBuilder; +#[cfg(feature = "runtime-tokio")] +use std::net::IpAddr; + +use globset::GlobBuilder; use ip_network::IpNetwork; use regex::Regex; use std::collections::HashMap; -#[cfg(feature = "runtime-tokio")] -use std::net::IpAddr; pub struct FunctionMap { pub(crate) fm: HashMap bool>, diff --git a/src/prelude.rs b/src/prelude.rs index 99770551..ee2e8e43 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,3 +1,4 @@ pub use crate::{ - CachedEnforcer, DefaultModel, Enforcer, FileAdapter, InternalApi, MgmtApi, Model, RbacApi, + CachedApi, CachedEnforcer, CoreApi, DefaultModel, Enforcer, FileAdapter, InternalApi, + MemoryAdapter, MgmtApi, Model, RbacApi, }; diff --git a/src/rbac/default_role_manager.rs b/src/rbac/default_role_manager.rs index 7d0fec84..d8b3a1b6 100644 --- a/src/rbac/default_role_manager.rs +++ b/src/rbac/default_role_manager.rs @@ -1,8 +1,9 @@ -use crate::error::RbacError; -use crate::rbac::RoleManager; -use crate::Result; -use std::collections::HashMap; -use std::sync::{Arc, RwLock}; +use crate::{error::RbacError, rbac::RoleManager, Result}; + +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, +}; #[derive(Clone)] pub struct DefaultRoleManager { diff --git a/src/rbac_api.rs b/src/rbac_api.rs index c9764578..4d4ea9a6 100644 --- a/src/rbac_api.rs +++ b/src/rbac_api.rs @@ -1,14 +1,11 @@ -use crate::cached_enforcer::CachedEnforcer; -use crate::enforcer::Enforcer; -use crate::MgmtApi; -use crate::Result; +use crate::{MgmtApi, Result}; use async_trait::async_trait; use std::collections::HashSet; #[async_trait] -pub trait RbacApi { +pub trait RbacApi: MgmtApi { async fn add_permission_for_user( &mut self, user: &str, @@ -40,13 +37,21 @@ pub trait RbacApi { async fn delete_roles_for_user(&mut self, user: &str, domain: Option<&str>) -> Result; async fn delete_user(&mut self, name: &str) -> Result; async fn delete_role(&mut self, name: &str) -> Result; - async fn delete_permission(&mut self, permission: Vec) -> Result; + + async fn delete_permission(&mut self, permission: Vec) -> Result { + self.remove_filtered_policy(1, permission).await + } async fn delete_permission_for_user( &mut self, user: &str, permission: Vec, ) -> Result; - async fn delete_permissions_for_user(&mut self, user: &str) -> Result; + + async fn delete_permissions_for_user(&mut self, user: &str) -> Result { + self.remove_filtered_policy(0, vec![user].iter().map(|s| (*s).to_string()).collect()) + .await + } + fn get_roles_for_user(&mut self, name: &str, domain: Option<&str>) -> Vec; fn get_users_for_role(&self, name: &str, domain: Option<&str>) -> Vec; fn has_role_for_user(&mut self, name: &str, role: &str, domain: Option<&str>) -> bool; @@ -58,11 +63,14 @@ pub trait RbacApi { name: &str, domain: Option<&str>, ) -> Vec>; - fn get_implicit_users_for_permission(&self, permission: Vec) -> Vec; + async fn get_implicit_users_for_permission(&mut self, permission: Vec) -> Vec; } #[async_trait] -impl RbacApi for Enforcer { +impl RbacApi for T +where + T: MgmtApi, +{ async fn add_permission_for_user( &mut self, user: &str, @@ -160,7 +168,7 @@ impl RbacApi for Enforcer { fn get_roles_for_user(&mut self, name: &str, domain: Option<&str>) -> Vec { let mut roles = vec![]; - if let Some(t1) = self.model.get_mut_model().get_mut("g") { + if let Some(t1) = self.get_mut_model().get_mut_model().get_mut("g") { if let Some(t2) = t1.get_mut("g") { roles = t2.rm.write().unwrap().get_roles(name, domain); } @@ -170,7 +178,7 @@ impl RbacApi for Enforcer { } fn get_users_for_role(&self, name: &str, domain: Option<&str>) -> Vec { - if let Some(t1) = self.model.get_model().get("g") { + if let Some(t1) = self.get_model().get_model().get("g") { if let Some(t2) = t1.get("g") { return t2.rm.read().unwrap().get_users(name, domain); } @@ -211,10 +219,6 @@ impl RbacApi for Enforcer { Ok(res1 || res2) } - async fn delete_permission(&mut self, permission: Vec) -> Result { - self.remove_filtered_policy(1, permission).await - } - async fn delete_permission_for_user( &mut self, user: &str, @@ -225,11 +229,6 @@ impl RbacApi for Enforcer { self.remove_policy(permission).await } - async fn delete_permissions_for_user(&mut self, user: &str) -> Result { - self.remove_filtered_policy(0, vec![user].iter().map(|s| (*s).to_string()).collect()) - .await - } - fn get_permissions_for_user(&self, user: &str, domain: Option<&str>) -> Vec> { self.get_filtered_policy(0, { if let Some(domain) = domain { @@ -251,7 +250,11 @@ impl RbacApi for Enforcer { fn get_implicit_roles_for_user(&mut self, name: &str, domain: Option<&str>) -> Vec { let mut res: HashSet = HashSet::new(); - let roles = self.rm.write().unwrap().get_roles(name, domain); + let roles = self + .get_role_manager() + .write() + .unwrap() + .get_roles(name, domain); res.extend(roles.clone()); roles.iter().for_each(|role| { @@ -278,7 +281,7 @@ impl RbacApi for Enforcer { res } - fn get_implicit_users_for_permission(&self, permission: Vec) -> Vec { + async fn get_implicit_users_for_permission(&mut self, permission: Vec) -> Vec { let subjects = self.get_all_subjects(); let roles = self.get_all_roles(); @@ -292,7 +295,7 @@ impl RbacApi for Enforcer { for user in users.iter() { let mut req = permission.clone(); req.insert(0, user.to_string()); - if let Ok(r) = self.enforce(&req) { + if let Ok(r) = self.enforce(&req).await { if r { res.push(user.to_owned()); } @@ -302,130 +305,9 @@ impl RbacApi for Enforcer { } } -#[async_trait] -impl RbacApi for CachedEnforcer { - async fn add_permission_for_user( - &mut self, - user: &str, - permission: Vec, - ) -> Result { - self.enforcer - .add_permission_for_user(user, permission) - .await - } - - async fn add_permissions_for_user( - &mut self, - user: &str, - permissions: Vec>, - ) -> Result { - self.enforcer - .add_permissions_for_user(user, permissions) - .await - } - - async fn add_role_for_user( - &mut self, - user: &str, - role: &str, - domain: Option<&str>, - ) -> Result { - self.enforcer.add_role_for_user(user, role, domain).await - } - - async fn add_roles_for_user( - &mut self, - user: &str, - roles: Vec, - domain: Option<&str>, - ) -> Result { - self.enforcer.add_roles_for_user(user, roles, domain).await - } - - async fn delete_role_for_user( - &mut self, - user: &str, - role: &str, - domain: Option<&str>, - ) -> Result { - self.enforcer.delete_role_for_user(user, role, domain).await - } - - async fn delete_roles_for_user(&mut self, user: &str, domain: Option<&str>) -> Result { - self.enforcer.delete_roles_for_user(user, domain).await - } - - fn get_roles_for_user(&mut self, name: &str, domain: Option<&str>) -> Vec { - self.enforcer.get_roles_for_user(name, domain) - } - - fn get_users_for_role(&self, name: &str, domain: Option<&str>) -> Vec { - self.enforcer.get_users_for_role(name, domain) - } - - fn has_role_for_user(&mut self, name: &str, role: &str, domain: Option<&str>) -> bool { - self.enforcer.has_role_for_user(name, role, domain) - } - - async fn delete_user(&mut self, name: &str) -> Result { - self.enforcer.delete_user(name).await - } - - async fn delete_role(&mut self, name: &str) -> Result { - self.enforcer.delete_role(name).await - } - - async fn delete_permission(&mut self, permission: Vec) -> Result { - self.enforcer.delete_permission(permission).await - } - - async fn delete_permission_for_user( - &mut self, - user: &str, - permission: Vec, - ) -> Result { - self.enforcer - .delete_permission_for_user(user, permission) - .await - } - - async fn delete_permissions_for_user(&mut self, user: &str) -> Result { - self.enforcer.delete_permissions_for_user(user).await - } - - fn get_permissions_for_user(&self, user: &str, domain: Option<&str>) -> Vec> { - self.enforcer.get_permissions_for_user(user, domain) - } - - fn has_permission_for_user(&self, user: &str, permission: Vec) -> bool { - self.enforcer.has_permission_for_user(user, permission) - } - - fn get_implicit_roles_for_user(&mut self, name: &str, domain: Option<&str>) -> Vec { - self.enforcer.get_implicit_roles_for_user(name, domain) - } - - fn get_implicit_permissions_for_user( - &mut self, - name: &str, - domain: Option<&str>, - ) -> Vec> { - self.enforcer - .get_implicit_permissions_for_user(name, domain) - } - - fn get_implicit_users_for_permission(&self, permission: Vec) -> Vec { - self.enforcer.get_implicit_users_for_permission(permission) - } -} - #[cfg(test)] mod tests { - use super::*; - - use crate::adapter::FileAdapter; - use crate::enforcer::Enforcer; - use crate::model::DefaultModel; + use crate::prelude::*; fn sort_unstable(mut v: Vec) -> Vec { v.sort_unstable(); @@ -521,24 +403,72 @@ mod tests { e.add_role_for_user("alice", "data2_admin", None) .await .unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); e.delete_role("data2_admin").await.unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "data2", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data1", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "data2", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "data2", "write"]).unwrap()); + assert_eq!( + true, + e.enforce(&vec!["alice", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["alice", "data2", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "read"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data1", "write"]).await.unwrap() + ); + assert_eq!( + false, + e.enforce(&vec!["bob", "data2", "read"]).await.unwrap() + ); + assert_eq!( + true, + e.enforce(&vec!["bob", "data2", "write"]).await.unwrap() + ); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -749,116 +679,132 @@ mod tests { .unwrap(); assert_eq!( true, - e.read() + e.write() .unwrap() .enforce(&vec!["alice", "data1", "read"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["alice", "data1", "write"]) + .await .unwrap() ); assert_eq!( true, - e.read() + e.write() .unwrap() .enforce(&vec!["alice", "data2", "read"]) + .await .unwrap() ); assert_eq!( true, - e.read() + e.write() .unwrap() .enforce(&vec!["alice", "data2", "write"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["bob", "data1", "read"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["bob", "data1", "write"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["bob", "data2", "read"]) + .await .unwrap() ); assert_eq!( true, - e.read() + e.write() .unwrap() .enforce(&vec!["bob", "data2", "write"]) + .await .unwrap() ); e.write().unwrap().delete_role("data2_admin").await.unwrap(); assert_eq!( true, - e.read() + e.write() .unwrap() .enforce(&vec!["alice", "data1", "read"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["alice", "data1", "write"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["alice", "data2", "read"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["alice", "data2", "write"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["bob", "data1", "read"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["bob", "data1", "write"]) + .await .unwrap() ); assert_eq!( false, - e.read() + e.write() .unwrap() .enforce(&vec!["bob", "data2", "read"]) + .await .unwrap() ); assert_eq!( true, - e.read() + e.write() .unwrap() .enforce(&vec!["bob", "data2", "write"]) + .await .unwrap() ); } @@ -873,10 +819,10 @@ mod tests { let adapter = FileAdapter::new("examples/basic_without_resources_policy.csv"); let mut e = Enforcer::new(m, adapter).await.unwrap(); - assert_eq!(true, e.enforce(&vec!["alice", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "write"]).unwrap()); + assert_eq!(true, e.enforce(&vec!["alice", "read"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "write"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["bob", "read"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["bob", "write"]).await.unwrap()); assert_eq!( vec![vec!["alice", "read"]], @@ -914,10 +860,10 @@ mod tests { .await .unwrap(); - assert_eq!(false, e.enforce(&vec!["alice", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "write"]).unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "read"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "write"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["bob", "read"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["bob", "write"]).await.unwrap()); e.add_permission_for_user("bob", vec!["read"].iter().map(|s| s.to_string()).collect()) .await @@ -932,33 +878,33 @@ mod tests { .await .unwrap(); - assert_eq!(false, e.enforce(&vec!["alice", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["eve", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["eve", "write"]).unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "read"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "write"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["bob", "read"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["bob", "write"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["eve", "read"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["eve", "write"]).await.unwrap()); e.delete_permission_for_user("bob", vec!["read"].iter().map(|s| s.to_string()).collect()) .await .unwrap(); - assert_eq!(false, e.enforce(&vec!["alice", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["bob", "write"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["eve", "read"]).unwrap()); - assert_eq!(true, e.enforce(&vec!["eve", "write"]).unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "read"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "write"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["bob", "read"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["bob", "write"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["eve", "read"]).await.unwrap()); + assert_eq!(true, e.enforce(&vec!["eve", "write"]).await.unwrap()); e.delete_permissions_for_user("bob").await.unwrap(); e.delete_permissions_for_user("eve").await.unwrap(); - assert_eq!(false, e.enforce(&vec!["alice", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["alice", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["bob", "write"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["eve", "read"]).unwrap()); - assert_eq!(false, e.enforce(&vec!["eve", "write"]).unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "read"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["alice", "write"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["bob", "read"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["bob", "write"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["eve", "read"]).await.unwrap()); + assert_eq!(false, e.enforce(&vec!["eve", "write"]).await.unwrap()); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] @@ -1033,7 +979,7 @@ mod tests { .unwrap(); let adapter = FileAdapter::new("examples/rbac_with_hierarchy_policy.csv"); - let e = Enforcer::new(m, adapter).await.unwrap(); + let mut e = Enforcer::new(m, adapter).await.unwrap(); assert_eq!( vec!["alice"], @@ -1043,6 +989,7 @@ mod tests { .map(|s| s.to_string()) .collect() ) + .await ); assert_eq!( vec!["alice"], @@ -1052,6 +999,7 @@ mod tests { .map(|s| s.to_string()) .collect() ) + .await ); assert_eq!( vec!["alice"], @@ -1061,6 +1009,7 @@ mod tests { .map(|s| s.to_string()) .collect() ) + .await ); assert_eq!( vec!["alice", "bob"], @@ -1071,6 +1020,7 @@ mod tests { .map(|s| s.to_string()) .collect() ) + .await ) ); } @@ -1109,16 +1059,16 @@ mod tests { e.add_matching_fn(key_match2).unwrap(); - assert!(e.enforce(&["alice", "/pen/1", "GET"]).unwrap()); - assert!(e.enforce(&["alice", "/pen2/1", "GET"]).unwrap()); - assert!(e.enforce(&["alice", "/book/1", "GET"]).unwrap()); - assert!(e.enforce(&["alice", "/book/2", "GET"]).unwrap()); - assert!(e.enforce(&["alice", "/pen/1", "GET"]).unwrap()); - assert!(!e.enforce(&["alice", "/pen/2", "GET"]).unwrap()); - assert!(!e.enforce(&["bob", "/book/1", "GET"]).unwrap()); - assert!(!e.enforce(&["bob", "/book/2", "GET"]).unwrap()); - assert!(e.enforce(&["bob", "/pen/1", "GET"]).unwrap()); - assert!(e.enforce(&["bob", "/pen/2", "GET"]).unwrap()); + assert!(e.enforce(&["alice", "/pen/1", "GET"]).await.unwrap()); + assert!(e.enforce(&["alice", "/pen2/1", "GET"]).await.unwrap()); + assert!(e.enforce(&["alice", "/book/1", "GET"]).await.unwrap()); + assert!(e.enforce(&["alice", "/book/2", "GET"]).await.unwrap()); + assert!(e.enforce(&["alice", "/pen/1", "GET"]).await.unwrap()); + assert!(!e.enforce(&["alice", "/pen/2", "GET"]).await.unwrap()); + assert!(!e.enforce(&["bob", "/book/1", "GET"]).await.unwrap()); + assert!(!e.enforce(&["bob", "/book/2", "GET"]).await.unwrap()); + assert!(e.enforce(&["bob", "/pen/1", "GET"]).await.unwrap()); + assert!(e.enforce(&["bob", "/pen/2", "GET"]).await.unwrap()); assert_eq!( vec!["/book/:id", "book_group"],