From fe1b5665254e22142b699e9a0e1cae9ec00d0aec Mon Sep 17 00:00:00 2001 From: Cheng JIANG Date: Tue, 21 Jan 2020 01:36:10 +0800 Subject: [PATCH 1/3] replace Box by Arc && add get_model, get_mut_model for Model. get_policy, get_mut_policy for Assertion --- src/adapter/file_adapter.rs | 25 +++++++++------ src/enforcer.rs | 21 +++++++------ src/model.rs | 52 +++++++++++++++++++++----------- src/rbac/default_role_manager.rs | 19 +++++++----- src/rbac_api.rs | 6 ++-- 5 files changed, 76 insertions(+), 47 deletions(-) diff --git a/src/adapter/file_adapter.rs b/src/adapter/file_adapter.rs index c896a91d..7e32e0a9 100644 --- a/src/adapter/file_adapter.rs +++ b/src/adapter/file_adapter.rs @@ -1,14 +1,13 @@ use crate::adapter::Adapter; -use crate::error::Error; +use crate::error::{Error, ModelError}; use crate::model::Model; +use crate::Result; use std::fs::File; use std::io::prelude::*; use std::io::BufReader; use std::io::{Error as IoError, ErrorKind}; -use crate::Result; - pub struct FileAdapter { pub file_path: String, } @@ -54,21 +53,27 @@ impl Adapter for FileAdapter { } let mut tmp = String::new(); - let ast_map1 = m.model.get("p").unwrap(); + let ast_map1 = m.get_model().get("p").ok_or_else(|| { + Error::ModelError(ModelError::P( + "Missing policy definition in conf file".to_owned(), + )) + })?; for (ptype, ast) in ast_map1 { - for rule in &ast.policy { + for rule in ast.get_policy() { let s1 = format!("{}, {}\n", ptype, rule.join(",")); tmp += s1.as_str(); } } - let ast_map2 = m.model.get("g").unwrap(); - for (ptype, ast) in ast_map2 { - for rule in &ast.policy { - let s1 = format!("{}, {}\n", ptype, rule.join(",")); - tmp += s1.as_str(); + if let Some(ast_map2) = m.get_model().get("g") { + for (ptype, ast) in ast_map2 { + for rule in ast.get_policy() { + let s1 = format!("{}, {}\n", ptype, rule.join(",")); + tmp += s1.as_str(); + } } } + self.save_policy_file(tmp)?; Ok(()) } diff --git a/src/enforcer.rs b/src/enforcer.rs index 89479be2..3767a4b7 100644 --- a/src/enforcer.rs +++ b/src/enforcer.rs @@ -8,6 +8,8 @@ use crate::Result; use rhai::{Any, Engine, RegisterFn, Scope}; +use std::sync::{Arc, RwLock}; + pub trait MatchFnClone: Fn(Vec>) -> bool { fn clone_box(&self) -> Box; } @@ -27,7 +29,7 @@ impl Clone for Box { } } -pub fn generate_g_function(rm: Box) -> Box { +pub fn generate_g_function(rm: Arc>) -> Box { let cb = move |args: Vec>| -> bool { let args = args .into_iter() @@ -35,11 +37,11 @@ pub fn generate_g_function(rm: Box) -> Box { .collect::>(); if args.len() == 3 { - let mut rm = rm.clone(); - rm.has_link(&args[0], &args[1], Some(&args[2])) + rm.write() + .unwrap() + .has_link(&args[0], &args[1], Some(&args[2])) } else if args.len() == 2 { - let mut rm = rm.clone(); - rm.has_link(&args[0], &args[1], None) + rm.write().unwrap().has_link(&args[0], &args[1], None) } else { unreachable!() } @@ -53,7 +55,7 @@ pub struct Enforcer { pub(crate) adapter: A, pub(crate) fm: FunctionMap, pub(crate) eft: Box, - pub(crate) rm: Box, + pub(crate) rm: Arc>, pub(crate) auto_save: bool, pub(crate) auto_build_role_links: bool, } @@ -64,7 +66,7 @@ impl Enforcer { let m = m; let fm = FunctionMap::default(); let eft = Box::new(DefaultEffector::default()); - let rm = Box::new(DefaultRoleManager::new(10)); + let rm = Arc::new(RwLock::new(DefaultRoleManager::new(10))); let mut e = Self { model: m, @@ -75,6 +77,7 @@ impl Enforcer { auto_save: true, auto_build_role_links: true, }; + // TODO: check filtered adapter, match over a implementor? e.load_policy().unwrap(); e @@ -243,8 +246,8 @@ impl Enforcer { } pub fn build_role_links(&mut self) -> Result<()> { - self.rm.clear(); - self.model.build_role_links(&mut self.rm)?; + self.rm.write().unwrap().clear(); + self.model.build_role_links(Arc::clone(&self.rm))?; Ok(()) } diff --git a/src/model.rs b/src/model.rs index dbaa79cc..39086cb4 100644 --- a/src/model.rs +++ b/src/model.rs @@ -11,6 +11,7 @@ use std::collections::HashMap; use std::convert::AsRef; use std::net::IpAddr; use std::path::Path; +use std::sync::{Arc, RwLock}; fn escape_assertion(s: String) -> String { let re = Regex::new(r#"(r|p)\."#).unwrap(); @@ -37,23 +38,31 @@ pub struct Assertion { pub(crate) value: String, pub(crate) tokens: Vec, pub(crate) policy: Vec>, - pub(crate) rm: Box, + pub(crate) rm: Arc>, } -impl Assertion { - #[allow(clippy::new_without_default)] - pub fn new() -> Self { +impl Default for Assertion { + fn default() -> Self { Assertion { key: String::new(), value: String::new(), tokens: vec![], policy: vec![], - rm: Box::new(DefaultRoleManager::new(0)), + rm: Arc::new(RwLock::new(DefaultRoleManager::new(0))), } } +} + +impl Assertion { + pub fn get_policy(&self) -> &Vec> { + &self.policy + } - #[allow(clippy::borrowed_box)] - pub fn build_role_links(&mut self, rm: &mut Box) -> Result<()> { + pub fn get_mut_policy(&mut self) -> &mut Vec> { + &mut self.policy + } + + pub fn build_role_links(&mut self, rm: Arc>) -> Result<()> { let count = self.value.chars().filter(|&c| c == '_').count(); for rule in &self.policy { if count < 2 { @@ -66,9 +75,11 @@ impl Assertion { return Err(Error::PolicyError(PolicyError::UnmatchPolicyDefinition).into()); } if count == 2 { - rm.add_link(&rule[0], &rule[1], None); + rm.write().unwrap().add_link(&rule[0], &rule[1], None); } else if count == 3 { - rm.add_link(&rule[0], &rule[1], Some(&rule[2])); + rm.write() + .unwrap() + .add_link(&rule[0], &rule[1], Some(&rule[2])); } else if count >= 4 { return Err(Error::ModelError(ModelError::P( "Multiple domains are not supported".to_owned(), @@ -76,7 +87,7 @@ impl Assertion { .into()); } } - self.rm = rm.clone(); + self.rm = Arc::clone(&rm); // self.rm.print_roles(); Ok(()) } @@ -119,7 +130,7 @@ impl Model { } pub fn add_def(&mut self, sec: &str, key: &str, value: &str) -> bool { - let mut ast = Assertion::new(); + let mut ast = Assertion::default(); ast.key = key.to_owned(); ast.value = value.to_owned(); @@ -154,7 +165,7 @@ impl Model { let mut i = 1; loop { - if !self.load_assersion(cfg, sec, &format!("{}{}", sec, self.get_key_suffix(i)))? { + if !self.load_assertion(cfg, sec, &format!("{}{}", sec, self.get_key_suffix(i)))? { break Ok(()); } else { i += 1; @@ -162,7 +173,15 @@ impl Model { } } - fn load_assersion(&mut self, cfg: &Config, sec: &str, key: &str) -> Result { + pub fn get_model(&self) -> &HashMap { + &self.model + } + + pub fn get_mut_model(&mut self) -> &mut HashMap { + &mut self.model + } + + fn load_assertion(&mut self, cfg: &Config, sec: &str, key: &str) -> Result { let sec_name = match sec { "r" => "request_definition", "p" => "policy_definition", @@ -189,11 +208,10 @@ impl Model { } } - #[allow(clippy::borrowed_box)] - pub fn build_role_links(&mut self, rm: &mut Box) -> Result<()> { + pub fn build_role_links(&mut self, rm: Arc>) -> Result<()> { if let Some(asts) = self.model.get_mut("g") { - for (_key, ast) in asts.iter_mut() { - ast.build_role_links(rm)?; + for ast in asts.values_mut() { + ast.build_role_links(Arc::clone(&rm))?; } } Ok(()) diff --git a/src/rbac/default_role_manager.rs b/src/rbac/default_role_manager.rs index 3307c081..ad49575f 100644 --- a/src/rbac/default_role_manager.rs +++ b/src/rbac/default_role_manager.rs @@ -4,14 +4,19 @@ use crate::Result; use std::collections::HashMap; use std::sync::{Arc, RwLock}; -type MatchingFunc = fn(&str, &str) -> bool; - #[derive(Clone)] pub struct DefaultRoleManager { - pub all_roles: Arc>>>>, - pub max_hierarchy_level: usize, - pub has_pattern: bool, - pub matching_func: Option, + all_roles: Arc>>>>, + max_hierarchy_level: usize, +} + +impl Default for DefaultRoleManager { + fn default() -> Self { + DefaultRoleManager { + all_roles: Arc::new(RwLock::new(HashMap::new())), + max_hierarchy_level: 0, + } + } } impl DefaultRoleManager { @@ -19,8 +24,6 @@ impl DefaultRoleManager { DefaultRoleManager { all_roles: Arc::new(RwLock::new(HashMap::new())), max_hierarchy_level, - has_pattern: false, - matching_func: None, } } diff --git a/src/rbac_api.rs b/src/rbac_api.rs index a7d1dff7..cc07d1be 100644 --- a/src/rbac_api.rs +++ b/src/rbac_api.rs @@ -52,7 +52,7 @@ impl RbacApi for Enforcer { let mut roles = vec![]; if let Some(t1) = self.model.model.get_mut("g") { if let Some(t2) = t1.get_mut("g") { - roles = t2.rm.get_roles(name, None); + roles = t2.rm.write().unwrap().get_roles(name, None); } } @@ -62,7 +62,7 @@ impl RbacApi for Enforcer { fn get_users_for_role(&self, name: &str) -> Vec { if let Some(t1) = self.model.model.get("g") { if let Some(t2) = t1.get("g") { - return t2.rm.get_users(name, None); + return t2.rm.read().unwrap().get_users(name, None); } } return vec![]; @@ -125,7 +125,7 @@ impl RbacApi for Enforcer { let name1 = q[0].clone(); name = &name1; q = q[1..].to_vec(); - let roles = self.rm.get_roles(name, domain); + let roles = self.rm.write().unwrap().get_roles(name, domain); for r in roles.iter().cloned() { if !role_set.contains_key(&r) { q.push(r.clone()); From fd23588fc3e46117e90841c687522ff1432ec5d6 Mon Sep 17 00:00:00 2001 From: Cheng JIANG Date: Tue, 21 Jan 2020 02:00:00 +0800 Subject: [PATCH 2/3] dump: 0.1.3 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index eddc81c6..0b4959f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "casbin" -version = "0.1.2" +version = "0.1.3" authors = ["Joey "] edition = "2018" license = "Apache-2.0" From 65d2ed7c18ac5807d530dc5a1f136061751d581d Mon Sep 17 00:00:00 2001 From: Cheng JIANG Date: Tue, 21 Jan 2020 02:07:50 +0800 Subject: [PATCH 3/3] resolve clippy warnings --- src/adapter/file_adapter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapter/file_adapter.rs b/src/adapter/file_adapter.rs index 7e32e0a9..77840cbc 100644 --- a/src/adapter/file_adapter.rs +++ b/src/adapter/file_adapter.rs @@ -107,7 +107,7 @@ fn load_policy_line(line: String, m: &mut Model) { let tokens: Vec = line.split(',').map(|x| x.trim().to_string()).collect(); let key = tokens[0].clone(); - if let Some(sec) = key.chars().nth(0).map(|x| x.to_string()) { + if let Some(sec) = key.chars().next().map(|x| x.to_string()) { if let Some(t1) = m.model.get_mut(&sec) { if let Some(t2) = t1.get_mut(&key) { t2.policy.push(tokens[1..].to_vec());