From 5dbacea4d43573e76051d9841e8d64e89e5ae11c Mon Sep 17 00:00:00 2001 From: Cheng JIANG Date: Fri, 3 Jan 2020 01:18:19 +0800 Subject: [PATCH 1/2] apply new error type to enforcer,model,config... --- src/adapter/file_adapter.rs | 13 +- src/config.rs | 51 ++-- src/enforcer.rs | 382 ++++++++++++------------ src/error.rs | 87 ++++++ src/errors.rs | 21 -- src/lib.rs | 2 +- src/management_api.rs | 8 +- src/model.rs | 498 +++++++++++++++++++------------ src/rbac/default_role_manager.rs | 6 +- src/rbac_api.rs | 172 +++++++---- 10 files changed, 742 insertions(+), 498 deletions(-) create mode 100644 src/error.rs delete mode 100644 src/errors.rs diff --git a/src/adapter/file_adapter.rs b/src/adapter/file_adapter.rs index 2061f6fc..5c4d4968 100644 --- a/src/adapter/file_adapter.rs +++ b/src/adapter/file_adapter.rs @@ -1,10 +1,11 @@ use crate::adapter::Adapter; -use crate::errors::CasbinError; +use crate::error::Error; use crate::model::Model; use std::fs::File; use std::io::prelude::*; use std::io::BufReader; +use std::io::{Error as IoError, ErrorKind}; use crate::Result; @@ -44,8 +45,12 @@ impl Adapter for FileAdapter { } fn save_policy(&self, m: &mut Model) -> Result<()> { - if self.file_path == "" { - return Err(CasbinError::new("save policy failed, file path is empty").into()); + if self.file_path.is_empty() { + return Err(Error::IoError(IoError::new( + ErrorKind::Other, + "save policy failed, file path is empty", + )) + .into()); } let mut tmp = String::new(); @@ -91,7 +96,7 @@ impl Adapter for FileAdapter { } fn load_policy_line(line: String, m: &mut Model) { - if line == "" || line.chars().nth(0).unwrap() == '#' { + if line.is_empty() || line.starts_with('#') { return; } let tokens: Vec = line.split(',').map(|x| x.trim().to_string()).collect(); diff --git a/src/config.rs b/src/config.rs index a5f736cb..d88a705d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,13 @@ +use crate::error::Error; +use crate::Result; + use std::collections::HashMap; +use std::convert::AsRef; use std::fs::File; use std::io::prelude::*; -use std::io::{BufReader, Cursor}; +use std::io::{BufReader, Cursor, Error as IoError, ErrorKind}; +use std::path::Path; const DEFAULT_SECTION: &str = "default"; const DEFAULT_COMMENT: &str = "#"; @@ -10,48 +15,46 @@ const DEFAULT_COMMENT_SEM: &str = ";"; const DEFAULT_MULTI_LINE_SEPARATOR: &str = "\\"; pub(crate) struct Config { - pub data: HashMap>, + data: HashMap>, } impl Config { - pub fn new(path: &str) -> Self { + pub(crate) fn from_file>(p: P) -> Result { let mut c = Config { data: HashMap::new(), }; - c.parse(path); - c + c.parse(p)?; + Ok(c) } - pub(crate) fn from_text(text: &str) -> Self { + pub(crate) fn from_str>(s: S) -> Result { let mut c = Config { data: HashMap::new(), }; - c.parse_buffer(&mut BufReader::new(Cursor::new(text.as_bytes()))); - c + c.parse_buffer(&mut BufReader::new(Cursor::new(s.as_ref().as_bytes())))?; + Ok(c) } - fn parse(&mut self, path: &str) { - let mut f = File::open(path).expect("read config failed"); + fn parse>(&mut self, p: P) -> Result<()> { + let mut f = File::open(p)?; let mut c = Vec::new(); - f.read_to_end(&mut c).expect("error while reading config"); + f.read_to_end(&mut c)?; let mut reader: BufReader> = BufReader::new(Cursor::new(&c)); - self.parse_buffer(&mut reader); + self.parse_buffer(&mut reader) } - fn parse_buffer(&mut self, reader: &mut BufReader>) { + fn parse_buffer(&mut self, reader: &mut BufReader>) -> Result<()> { let mut section = String::new(); loop { let mut line = String::new(); - let bytes = reader - .read_line(&mut line) - .expect("read config line failed"); + let bytes = reader.read_line(&mut line)?; if bytes == 0 { // EOF reached - break; + break Ok(()); } line = line.trim().to_string(); if line.is_empty() @@ -67,9 +70,7 @@ impl Config { line = line[..line.len() - 1].trim_end().to_string(); let mut inner_line = String::new(); - let inner_bytes = reader - .read_line(&mut inner_line) - .expect("read config line failed"); + let inner_bytes = reader.read_line(&mut inner_line)?; if inner_bytes == 0 { break; } @@ -99,7 +100,11 @@ impl Config { .collect(); if option_val.len() != 2 { - panic!("parse content error, line={}", line); + return Err(Error::IoError(IoError::new( + ErrorKind::Other, + format!("parse content error, line={}", line), + )) + .into()); } self.add_config( @@ -199,7 +204,7 @@ mod tests { #[test] fn test_get() { - let mut config = Config::new("examples/testini.ini"); + let mut config = Config::from_file("examples/testini.ini").unwrap(); assert_eq!(Some(true), config.get_bool("debug")); assert_eq!(Some(64), config.get_int("math::math.i64")); @@ -269,7 +274,7 @@ mod tests { math.f64 = 64.1 "#; - let mut config = Config::from_text(text); + let mut config = Config::from_str(text).unwrap(); assert_eq!(Some(true), config.get_bool("debug")); assert_eq!(Some(64), config.get_int("math::math.i64")); diff --git a/src/enforcer.rs b/src/enforcer.rs index fac8fb1d..3304139c 100644 --- a/src/enforcer.rs +++ b/src/enforcer.rs @@ -1,5 +1,6 @@ use crate::adapter::Adapter; use crate::effector::{DefaultEffector, EffectKind, Effector}; +use crate::error::{Error, ModelError}; use crate::model::Model; use crate::model::{load_function_map, FunctionMap}; use crate::rbac::{DefaultRoleManager, RoleManager}; @@ -7,6 +8,8 @@ use crate::Result; use rhai::{Engine, RegisterFn, Scope}; +// use std::collections::HashMap; + pub trait MatchFnClone2: Fn(String, String) -> bool { fn clone_box(&self) -> Box; } @@ -101,30 +104,62 @@ impl Enforcer { /// ``` /// use casbin::{Enforcer, Model, FileAdapter}; /// - /// let m = Model::new_from_file("examples/basic_model.conf"); + /// let m = Model::from_file("examples/basic_model.conf").unwrap(); /// let adapter = FileAdapter::new("examples/basic_policy.csv"); /// let e = Enforcer::new(m, adapter); - /// assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); + /// assert_eq!(true, e.enforce(vec!["alice", "data1", "read"]).unwrap()); /// ``` - pub fn enforce(&self, rvals: Vec<&str>) -> bool { + pub fn enforce(&self, rvals: Vec<&str>) -> Result { let mut engine = Engine::new(); let mut scope: Scope = Vec::new(); - for (i, token) in self + let r = self .model .model .get("r") - .unwrap() + .ok_or(Error::ModelError( + ModelError::R("Missing request definition in conf file".to_owned()).into(), + ))? .get("r") - .unwrap() - .tokens - .iter() - .enumerate() - { - // let r_sub = "alice"; or let r_obj = "resource1"; or let r_sub = "GET"; + .ok_or(Error::ModelError( + ModelError::R("Missing request secion in conf file".to_owned()).into(), + ))?; + let p = self + .model + .model + .get("p") + .ok_or(Error::ModelError( + ModelError::P("Missing policy definition in conf file".to_owned()).into(), + ))? + .get("p") + .ok_or(Error::ModelError( + ModelError::P("Missing policy section in conf file".to_owned()).into(), + ))?; + let m = self + .model + .model + .get("m") + .ok_or(Error::ModelError( + ModelError::M("Missing matcher definition in conf file".to_owned()).into(), + ))? + .get("m") + .ok_or(Error::ModelError( + ModelError::M("Missing matcher section in conf file".to_owned()).into(), + ))?; + let e = self + .model + .model + .get("e") + .ok_or(Error::ModelError( + ModelError::E("Missing effector definition in conf file".to_owned()).into(), + ))? + .get("e") + .ok_or(Error::ModelError( + ModelError::E("Missing effector section in conf file".to_owned()).into(), + ))?; + + for (i, token) in r.tokens.iter().enumerate() { let scope_exp = format!("let {} = \"{}\";", token.clone(), rvals[i]); - engine - .eval_with_scope::<()>(&mut scope, scope_exp.as_str()) - .expect("set rtoken scope failed"); + engine.eval_with_scope::<()>(&mut scope, scope_exp.as_str())?; } for (key, func) in self.fm.iter() { @@ -143,100 +178,30 @@ impl Enforcer { } } } - let expstring = self - .model - .model - .get("m") - .unwrap() - .get("m") - .unwrap() - .value - .clone(); + let expstring = m.value.clone(); let mut policy_effects: Vec = vec![]; - let policy_len = self - .model - .model - .get("p") - .unwrap() - .get("p") - .unwrap() - .policy - .len(); + let policy_len = p.policy.len(); if policy_len != 0 { policy_effects = vec![EffectKind::Allow; policy_len]; - if self - .model - .model - .get("r") - .unwrap() - .get("r") - .unwrap() - .tokens - .len() - != rvals.len() - { - return false; + if r.tokens.len() != rvals.len() { + return Ok(false); } - for (i, pvals) in self - .model - .model - .get("p") - .unwrap() - .get("p") - .unwrap() - .policy - .iter() - .enumerate() - { - if self - .model - .model - .get("p") - .unwrap() - .get("p") - .unwrap() - .tokens - .len() - != pvals.len() - { - return false; + for (i, pvals) in p.policy.iter().enumerate() { + if p.tokens.len() != pvals.len() { + return Ok(false); } - for (pi, ptoken) in self - .model - .model - .get("p") - .unwrap() - .get("p") - .unwrap() - .tokens - .iter() - .enumerate() - { + for (pi, ptoken) in p.tokens.iter().enumerate() { // let p_sub = "alice"; or let p_obj = "resource1"; or let p_sub = "GET"; let scope_exp = format!("let {} = \"{}\";", ptoken.clone(), pvals[pi]); - engine - .eval_with_scope::<()>(&mut scope, scope_exp.as_str()) - .expect("set ptoken scope failed"); + engine.eval_with_scope::<()>(&mut scope, scope_exp.as_str())?; } - let eval_result = engine - .eval_with_scope::(&mut scope, expstring.as_str()) - .expect("eval expression failed"); + let eval_result = engine.eval_with_scope::(&mut scope, expstring.as_str())?; if !eval_result { policy_effects[i] = EffectKind::Indeterminate; continue; } - if let Some(j) = self - .model - .model - .get("p") - .unwrap() - .get("p") - .unwrap() - .tokens - .iter() - .position(|x| x == &String::from("p_eft")) - { + if let Some(j) = p.tokens.iter().position(|x| x == &String::from("p_eft")) { let eft = &pvals[j]; if eft == "allow" { policy_effects[i] = EffectKind::Allow; @@ -255,24 +220,11 @@ impl Enforcer { } } } else { - for token in self - .model - .model - .get("p") - .unwrap() - .get("p") - .unwrap() - .tokens - .iter() - { + for token in p.tokens.iter() { let scope_exp = format!("let {} = \"{}\";", token.clone(), ""); - engine - .eval_with_scope::<()>(&mut scope, scope_exp.as_str()) - .expect("set ptoken in else scope failed"); + engine.eval_with_scope::<()>(&mut scope, scope_exp.as_str())?; } - let eval_result = engine - .eval_with_scope::(&mut scope, expstring.as_str()) - .expect("eval expression failed"); + let eval_result = engine.eval_with_scope::(&mut scope, expstring.as_str())?; if eval_result { policy_effects.push(EffectKind::Allow); } else { @@ -280,16 +232,9 @@ impl Enforcer { } } - let ee = self - .model - .model - .get("e") - .unwrap() - .get("e") - .unwrap() - .value - .clone(); - self.eft.merge_effects(ee, policy_effects, vec![]) + let ee = e.value.clone(); + + Ok(self.eft.merge_effects(ee, policy_effects, vec![])) } pub fn build_role_links(&mut self) -> Result<()> { @@ -328,7 +273,7 @@ mod tests { #[test] fn test_key_match_model_in_memory() { - let mut m = Model::new(); + let mut m = Model::default(); m.add_def("r", "r", "sub, obj, act"); m.add_def("p", "p", "sub, obj, act"); m.add_def("e", "e", "some(where (p.eft == allow))"); @@ -343,62 +288,102 @@ mod tests { assert_eq!( true, e.enforce(vec!["alice", "/alice_data/resource1", "GET"]) + .unwrap() ); assert_eq!( true, e.enforce(vec!["alice", "/alice_data/resource1", "POST"]) + .unwrap() ); assert_eq!( true, e.enforce(vec!["alice", "/alice_data/resource2", "GET"]) + .unwrap() ); assert_eq!( false, e.enforce(vec!["alice", "/alice_data/resource2", "POST"]) + .unwrap() ); assert_eq!( false, e.enforce(vec!["alice", "/bob_data/resource1", "GET"]) + .unwrap() ); assert_eq!( false, e.enforce(vec!["alice", "/bob_data/resource1", "POST"]) + .unwrap() ); assert_eq!( false, e.enforce(vec!["alice", "/bob_data/resource2", "GET"]) + .unwrap() ); assert_eq!( false, e.enforce(vec!["alice", "/bob_data/resource2", "POST"]) + .unwrap() ); assert_eq!( false, e.enforce(vec!["bob", "/alice_data/resource1", "GET"]) + .unwrap() ); assert_eq!( false, e.enforce(vec!["bob", "/alice_data/resource1", "POST"]) + .unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "/alice_data/resource2", "GET"]) + .unwrap() ); - assert_eq!(true, e.enforce(vec!["bob", "/alice_data/resource2", "GET"])); assert_eq!( false, e.enforce(vec!["bob", "/alice_data/resource2", "POST"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "/bob_data/resource1", "GET"]) + .unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "/bob_data/resource1", "POST"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "/bob_data/resource2", "GET"]) + .unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "/bob_data/resource2", "POST"]) + .unwrap() + ); + + assert_eq!( + true, + e.enforce(vec!["cathy", "/cathy_data", "GET"]).unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["cathy", "/cathy_data", "POST"]).unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["cathy", "/cathy_data", "DELETE"]).unwrap() ); - assert_eq!(false, e.enforce(vec!["bob", "/bob_data/resource1", "GET"])); - assert_eq!(true, e.enforce(vec!["bob", "/bob_data/resource1", "POST"])); - assert_eq!(false, e.enforce(vec!["bob", "/bob_data/resource2", "GET"])); - assert_eq!(true, e.enforce(vec!["bob", "/bob_data/resource2", "POST"])); - - assert_eq!(true, e.enforce(vec!["cathy", "/cathy_data", "GET"])); - assert_eq!(true, e.enforce(vec!["cathy", "/cathy_data", "POST"])); - assert_eq!(false, e.enforce(vec!["cathy", "/cathy_data", "DELETE"])); } #[test] fn test_key_match_model_in_memory_deny() { - let mut m = Model::new(); + let mut m = Model::default(); m.add_def("r", "r", "sub, obj, act"); m.add_def("p", "p", "sub, obj, act"); m.add_def("e", "e", "!some(where (p.eft == deny))"); @@ -413,13 +398,14 @@ mod tests { assert_eq!( true, e.enforce(vec!["alice", "/alice_data/resource2", "POST"]) + .unwrap() ); } use crate::RbacApi; #[test] fn test_rbac_model_in_memory_indeterminate() { - let mut m = Model::new(); + let mut m = Model::default(); m.add_def("r", "r", "sub, obj, act"); m.add_def("p", "p", "sub, obj, act"); m.add_def("g", "g", "_, _"); @@ -434,12 +420,12 @@ mod tests { let mut e = Enforcer::new(m, adapter); e.add_permission_for_user("alice", vec!["data1", "invalid"]) .unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "data1", "read"])); + assert_eq!(false, e.enforce(vec!["alice", "data1", "read"]).unwrap()); } #[test] fn test_rbac_model_in_memory() { - let mut m = Model::new(); + let mut m = Model::default(); m.add_def("r", "r", "sub, obj, act"); m.add_def("p", "p", "sub, obj, act"); m.add_def("g", "g", "_, _"); @@ -462,19 +448,19 @@ mod tests { .unwrap(); e.add_role_for_user("alice", "data2_admin").unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); } #[test] fn test_not_used_rbac_model_in_memory() { - let mut m = Model::new(); + let mut m = Model::default(); m.add_def("r", "r", "sub, obj, act"); m.add_def("p", "p", "sub, obj, act"); m.add_def("g", "g", "_, _"); @@ -492,50 +478,50 @@ mod tests { e.add_permission_for_user("bob", vec!["data2", "write"]) .unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); } #[test] fn test_ip_match_model() { - let m = Model::new_from_file("examples/ipmatch_model.conf"); + let m = Model::from_file("examples/ipmatch_model.conf").unwrap(); let adapter = FileAdapter::new("examples/ipmatch_policy.csv"); let e = Enforcer::new(m, adapter); - assert!(e.enforce(vec!["192.168.2.123", "data1", "read"])); + assert!(e.enforce(vec!["192.168.2.123", "data1", "read"]).unwrap()); - assert!(e.enforce(vec!["10.0.0.5", "data2", "write"])); + assert!(e.enforce(vec!["10.0.0.5", "data2", "write"]).unwrap()); - assert!(!e.enforce(vec!["192.168.2.123", "data1", "write"])); - assert!(!e.enforce(vec!["192.168.2.123", "data2", "read"])); - assert!(!e.enforce(vec!["192.168.2.123", "data2", "write"])); + 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.0.123", "data1", "read"])); - assert!(!e.enforce(vec!["192.168.0.123", "data1", "write"])); - assert!(!e.enforce(vec!["192.168.0.123", "data2", "read"])); - assert!(!e.enforce(vec!["192.168.0.123", "data2", "write"])); + 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!["10.0.0.5", "data1", "read"])); - assert!(!e.enforce(vec!["10.0.0.5", "data1", "write"])); - assert!(!e.enforce(vec!["10.0.0.5", "data2", "read"])); + 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!["192.168.0.1", "data1", "read"])); - assert!(!e.enforce(vec!["192.168.0.1", "data1", "write"])); - assert!(!e.enforce(vec!["192.168.0.1", "data2", "read"])); - assert!(!e.enforce(vec!["192.168.0.1", "data2", "write"])); + 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()); } use crate::MgmtApi; #[test] fn test_enable_auto_save() { - let m = Model::new_from_file("examples/basic_model.conf"); + let m = Model::from_file("examples/basic_model.conf").unwrap(); let adapter = FileAdapter::new("examples/basic_policy.csv"); let mut e = Enforcer::new(m, adapter); @@ -543,71 +529,71 @@ mod tests { e.remove_policy(vec!["alice", "data1", "read"]).unwrap(); e.load_policy().unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); e.enable_auto_save(true); e.remove_policy(vec!["alice", "data1", "read"]).unwrap(); e.load_policy().unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); } #[test] fn test_role_links() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = MemoryAdapter::default(); let mut e = Enforcer::new(m, adapter); e.enable_auto_build_role_links(false); e.build_role_links().unwrap(); - assert_eq!(false, e.enforce(vec!["user501", "data9", "read"])); + assert_eq!(false, e.enforce(vec!["user501", "data9", "read"]).unwrap()); } #[test] fn test_get_and_set_model() { - let m1 = Model::new_from_file("examples/basic_model.conf"); + let m1 = Model::from_file("examples/basic_model.conf").unwrap(); let adapter1 = FileAdapter::new("examples/basic_policy.csv"); let mut e = Enforcer::new(m1, adapter1); - assert_eq!(false, e.enforce(vec!["root", "data1", "read"])); + assert_eq!(false, e.enforce(vec!["root", "data1", "read"]).unwrap()); - let m2 = Model::new_from_file("examples/basic_with_root_model.conf"); + let m2 = Model::from_file("examples/basic_with_root_model.conf").unwrap(); let adapter2 = FileAdapter::new("examples/basic_policy.csv"); let e2 = Enforcer::new(m2, adapter2); e.model = e2.model; - assert_eq!(true, e.enforce(vec!["root", "data1", "read"])); + assert_eq!(true, e.enforce(vec!["root", "data1", "read"]).unwrap()); } #[test] fn test_get_and_set_adapter_in_mem() { - let m1 = Model::new_from_file("examples/basic_model.conf"); + let m1 = Model::from_file("examples/basic_model.conf").unwrap(); let adapter1 = FileAdapter::new("examples/basic_policy.csv"); let mut e = Enforcer::new(m1, adapter1); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); + assert_eq!(true, e.enforce(vec!["alice", "data1", "read"]).unwrap()); + assert_eq!(false, e.enforce(vec!["alice", "data1", "write"]).unwrap()); - let m2 = Model::new_from_file("examples/basic_model.conf"); + let m2 = Model::from_file("examples/basic_model.conf").unwrap(); let adapter2 = FileAdapter::new("examples/basic_inverse_policy.csv"); let e2 = Enforcer::new(m2, adapter2); e.adapter = e2.adapter; e.load_policy().unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "data1", "write"])); + assert_eq!(false, e.enforce(vec!["alice", "data1", "read"]).unwrap()); + assert_eq!(true, e.enforce(vec!["alice", "data1", "write"]).unwrap()); } } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000..60968479 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,87 @@ +use rhai::EvalAltResult; + +use std::error::Error as StdError; +use std::fmt::{Display, Formatter, Result as FmtResult}; +use std::io::Error as IoError; + +/// ModelError represents any type of errors in model.conf +#[derive(Debug)] +pub enum ModelError { + R(String), + P(String), + E(String), + M(String), + Other(String), +} +impl Display for ModelError { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + use ModelError::*; + + match self { + R(msg) => write!(f, "Invalid request definition: {}", msg), + P(msg) => write!(f, "Invalid policy definition: {}", msg), + E(msg) => write!(f, "Unsupported effect: {}", msg), + M(msg) => write!(f, "Invalid matcher: {}", msg), + Other(msg) => write!(f, "Invalid section: {}", msg), + } + } +} +impl StdError for ModelError {} + +/// PolicyError represents any type of errors in policy +#[derive(Debug)] +pub enum PolicyError { + UnmatchPolicyDefinition, +} +impl Display for PolicyError { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + use PolicyError::*; + match self { + UnmatchPolicyDefinition => write!(f, "Policy doesn't match its definition"), + } + } +} +impl StdError for PolicyError {} + +/// RBAC error +#[derive(Debug)] +pub enum RbacError { + NotFound(String), +} +impl Display for RbacError { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + use RbacError::*; + match self { + NotFound(msg) => write!(f, r#"Role "{}" not found"#, msg), + } + } +} +impl StdError for RbacError {} + +/// General casbin error +#[derive(Debug)] +pub enum Error { + IoError(IoError), + + ModelError(ModelError), + + PolicyError(PolicyError), + + RbacError(RbacError), + + RhaiError(EvalAltResult), +} +impl Display for Error { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + use Error::*; + + match self { + IoError(i_err) => i_err.fmt(f), + ModelError(m_err) => m_err.fmt(f), + PolicyError(p_err) => p_err.fmt(f), + RbacError(r_err) => r_err.fmt(f), + RhaiError(e_err) => e_err.fmt(f), + } + } +} +impl StdError for Error {} diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index 831be1bf..00000000 --- a/src/errors.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::error::Error; -use std::fmt::{Display, Formatter, Result as FmtResult}; - -#[derive(Debug, Clone)] -pub struct CasbinError { - msg: &'static str, -} - -impl CasbinError { - pub fn new(msg: &'static str) -> Self { - CasbinError { msg } - } -} - -impl Display for CasbinError { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - write!(f, "casbin error, msg={}", self.msg) - } -} - -impl Error for CasbinError {} diff --git a/src/lib.rs b/src/lib.rs index d157f3c3..fa7a736c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ mod model; mod rbac; mod rbac_api; -pub mod errors; +pub mod error; pub use adapter::{Adapter, FileAdapter}; pub use enforcer::Enforcer; pub use internal_api::InternalApi; diff --git a/src/management_api.rs b/src/management_api.rs index 4eb25a25..8a015bc8 100644 --- a/src/management_api.rs +++ b/src/management_api.rs @@ -249,7 +249,7 @@ mod tests { #[test] fn test_modify_grouping_policy_api() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let mut e = Enforcer::new(m, adapter); @@ -295,7 +295,7 @@ mod tests { #[test] fn test_modify_policy_api() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let mut e = Enforcer::new(m, adapter); @@ -335,7 +335,7 @@ mod tests { #[test] fn test_get_policy_api() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let e = Enforcer::new(m, adapter); @@ -442,7 +442,7 @@ mod tests { #[test] fn test_get_list() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let e = Enforcer::new(m, adapter); diff --git a/src/model.rs b/src/model.rs index a09cc273..0884d624 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,5 +1,5 @@ use crate::config::Config; -use crate::errors::CasbinError; +use crate::error::{Error, ModelError, PolicyError}; use crate::rbac::{DefaultRoleManager, RoleManager}; use crate::Result; @@ -32,7 +32,7 @@ fn escape_g_function(s: String) -> String { after } -type AssertionMap = HashMap; +pub(crate) type AssertionMap = HashMap; #[derive(Clone)] pub struct Assertion { @@ -58,25 +58,25 @@ impl Assertion { #[allow(clippy::borrowed_box)] pub fn build_role_links(&mut self, rm: &mut Box) -> Result<()> { let count = self.value.chars().filter(|&c| c == '_').count(); - for (_k, rule) in self.policy.iter().enumerate() { + for rule in &self.policy { if count < 2 { - return Err(CasbinError::new( - "the number of \"_\" in role definition should be at least 2", - ) + return Err(Error::ModelError(ModelError::P( + r#"the number of "_" in role definition should be at least 2"#.to_owned(), + )) .into()); } if rule.len() < count { - return Err(CasbinError::new( - "grouping policy elements do not meet role definition", - ) - .into()); + return Err(Error::PolicyError(PolicyError::UnmatchPolicyDefinition).into()); } if count == 2 { rm.add_link(&rule[0], &rule[1], None); } else if count == 3 { rm.add_link(&rule[0], &rule[1], Some(&rule[2])); } else if count >= 4 { - return Err(CasbinError::new("domain can at most contains 1 string").into()); + return Err(Error::ModelError(ModelError::P( + "Multiple domains are not supported".to_owned(), + )) + .into()); } } self.rm = rm.clone(); @@ -87,20 +87,10 @@ impl Assertion { #[derive(Clone, Default)] pub struct Model { - pub model: HashMap, + pub(crate) model: HashMap, } impl Model { - pub fn new() -> Self { - Model::default() - } - - pub fn new_from_file(path: &str) -> Self { - let mut model = Model::new(); - model.load_model(path); - model - } - fn get_key_suffix(&self, i: u64) -> String { if i == 1 { "".to_owned() @@ -109,55 +99,65 @@ impl Model { } } - fn load_assersion(&mut self, cfg: &Config, sec: &str, key: &str) -> bool { + fn load_assersion(&mut self, cfg: &Config, sec: &str, key: &str) -> Result { let sec_name = match sec { "r" => "request_definition", "p" => "policy_definition", "g" => "role_definition", "e" => "policy_effect", "m" => "matchers", - _ => panic!("section is not one of [r,p,g,e,m] {}", sec), + _ => { + return Err(Error::ModelError(ModelError::Other(sec.to_owned())).into()); + } }; if let Some(val) = cfg.get_str(&format!("{}::{}", sec_name, key)) { - self.add_def(sec, key, val) + Ok(self.add_def(sec, key, val)) } else { - false + Ok(false) } } - fn load_section(&mut self, cfg: &Config, sec: &str) { + fn load_section(&mut self, cfg: &Config, sec: &str) -> Result<()> { let mut i = 1; loop { - if !self.load_assersion(cfg, sec, &format!("{}{}", sec, self.get_key_suffix(i))) { - break; + if !self.load_assersion(cfg, sec, &format!("{}{}", sec, self.get_key_suffix(i)))? { + break Ok(()); } else { i += 1; } } } - pub fn load_model(&mut self, path: &str) { - let cfg = Config::new(path); + pub fn from_file(path: &str) -> Result { + let cfg = Config::from_file(path)?; + + let mut model = Model::default(); - self.load_section(&cfg, "r"); - self.load_section(&cfg, "p"); - self.load_section(&cfg, "e"); - self.load_section(&cfg, "m"); + model.load_section(&cfg, "r")?; + model.load_section(&cfg, "p")?; + model.load_section(&cfg, "e")?; + model.load_section(&cfg, "m")?; - self.load_section(&cfg, "g"); + model.load_section(&cfg, "g")?; + + Ok(model) } - pub fn load_model_from_text(&mut self, text: &str) { - let cfg = Config::from_text(text); + pub fn from_str(&mut self, s: &str) -> Result { + let cfg = Config::from_str(s)?; + + let mut model = Model::default(); + + model.load_section(&cfg, "r")?; + model.load_section(&cfg, "p")?; + model.load_section(&cfg, "e")?; + model.load_section(&cfg, "m")?; - self.load_section(&cfg, "r"); - self.load_section(&cfg, "p"); - self.load_section(&cfg, "e"); - self.load_section(&cfg, "m"); + model.load_section(&cfg, "g")?; - self.load_section(&cfg, "g"); + Ok(model) } pub fn add_def(&mut self, sec: &str, key: &str, value: &str) -> bool { @@ -165,7 +165,7 @@ impl Model { ast.key = key.to_owned(); ast.value = value.to_owned(); - if ast.value == "" { + if ast.value.is_empty() { return false; } @@ -498,161 +498,189 @@ mod tests { use crate::enforcer::Enforcer; #[test] fn test_basic_model() { - let m = Model::new_from_file("examples/basic_model.conf"); + let m = Model::from_file("examples/basic_model.conf").unwrap(); let adapter = FileAdapter::new("examples/basic_policy.csv"); let e = Enforcer::new(m, adapter); - assert!(e.enforce(vec!["alice", "data1", "read"])); - assert!(!e.enforce(vec!["alice", "data1", "write"])); - assert!(!e.enforce(vec!["alice", "data2", "read"])); - assert!(!e.enforce(vec!["alice", "data2", "write"])); - assert!(!e.enforce(vec!["bob", "data1", "read"])); - assert!(!e.enforce(vec!["bob", "data1", "write"])); - assert!(!e.enforce(vec!["bob", "data2", "read"])); - assert!(e.enforce(vec!["bob", "data2", "write"])); + 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()); } #[test] fn test_basic_model_no_policy() { - let m = Model::new_from_file("examples/basic_model.conf"); + let m = Model::from_file("examples/basic_model.conf").unwrap(); let adapter = MemoryAdapter::default(); let e = Enforcer::new(m, adapter); - assert!(!e.enforce(vec!["alice", "data1", "read"])); - assert!(!e.enforce(vec!["alice", "data1", "write"])); - assert!(!e.enforce(vec!["alice", "data2", "read"])); - assert!(!e.enforce(vec!["alice", "data2", "write"])); - assert!(!e.enforce(vec!["bob", "data1", "read"])); - assert!(!e.enforce(vec!["bob", "data1", "write"])); - assert!(!e.enforce(vec!["bob", "data2", "read"])); - assert!(!e.enforce(vec!["bob", "data2", "write"])); + 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()); } #[test] fn test_basic_model_with_root() { - let m = Model::new_from_file("examples/basic_with_root_model.conf"); + let m = Model::from_file("examples/basic_with_root_model.conf").unwrap(); let adapter = FileAdapter::new("examples/basic_policy.csv"); let e = Enforcer::new(m, adapter); - assert!(e.enforce(vec!["alice", "data1", "read"])); - assert!(e.enforce(vec!["bob", "data2", "write"])); - assert!(e.enforce(vec!["root", "data1", "read"])); - assert!(e.enforce(vec!["root", "data1", "write"])); - assert!(e.enforce(vec!["root", "data2", "read"])); - assert!(e.enforce(vec!["root", "data2", "write"])); - assert!(!e.enforce(vec!["alice", "data1", "write"])); - assert!(!e.enforce(vec!["alice", "data2", "read"])); - assert!(!e.enforce(vec!["alice", "data2", "write"])); - assert!(!e.enforce(vec!["bob", "data1", "read"])); - assert!(!e.enforce(vec!["bob", "data1", "write"])); - assert!(!e.enforce(vec!["bob", "data2", "read"])); + 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()); } #[test] fn test_basic_model_with_root_no_policy() { - let m = Model::new_from_file("examples/basic_with_root_model.conf"); + let m = Model::from_file("examples/basic_with_root_model.conf").unwrap(); let adapter = MemoryAdapter::default(); let e = Enforcer::new(m, adapter); - assert!(!e.enforce(vec!["alice", "data1", "read"])); - assert!(!e.enforce(vec!["bob", "data2", "write"])); - assert!(e.enforce(vec!["root", "data1", "read"])); - assert!(e.enforce(vec!["root", "data1", "write"])); - assert!(e.enforce(vec!["root", "data2", "read"])); - assert!(e.enforce(vec!["root", "data2", "write"])); - assert!(!e.enforce(vec!["alice", "data1", "write"])); - assert!(!e.enforce(vec!["alice", "data2", "read"])); - assert!(!e.enforce(vec!["alice", "data2", "write"])); - assert!(!e.enforce(vec!["bob", "data1", "read"])); - assert!(!e.enforce(vec!["bob", "data1", "write"])); - assert!(!e.enforce(vec!["bob", "data2", "read"])); + 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()); } #[test] fn test_basic_model_without_users() { - let m = Model::new_from_file("examples/basic_without_users_model.conf"); + let m = Model::from_file("examples/basic_without_users_model.conf").unwrap(); let adapter = FileAdapter::new("examples/basic_without_users_policy.csv"); let e = Enforcer::new(m, adapter); - assert!(e.enforce(vec!["data1", "read"])); - assert!(!e.enforce(vec!["data1", "write"])); - assert!(!e.enforce(vec!["data2", "read"])); - assert!(e.enforce(vec!["data2", "write"])); + 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()); } #[test] fn test_basic_model_without_resources() { - let m = Model::new_from_file("examples/basic_without_resources_model.conf"); + let m = Model::from_file("examples/basic_without_resources_model.conf").unwrap(); let adapter = FileAdapter::new("examples/basic_without_resources_policy.csv"); let e = Enforcer::new(m, adapter); - assert!(e.enforce(vec!["alice", "read"])); - assert!(e.enforce(vec!["bob", "write"])); - assert!(!e.enforce(vec!["alice", "write"])); - assert!(!e.enforce(vec!["bob", "read"])); + 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()); } #[test] fn test_rbac_model() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let e = Enforcer::new(m, adapter); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); } #[test] fn test_rbac_model_with_resource_roles() { - let m = Model::new_from_file("examples/rbac_with_resource_roles_model.conf"); + let m = Model::from_file("examples/rbac_with_resource_roles_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_resource_roles_policy.csv"); let e = Enforcer::new(m, adapter); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); } #[test] fn test_rbac_model_with_domains() { - let m = Model::new_from_file("examples/rbac_with_domains_model.conf"); + let m = Model::from_file("examples/rbac_with_domains_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_domains_policy.csv"); let e = Enforcer::new(m, adapter); - assert_eq!(true, e.enforce(vec!["alice", "domain1", "data1", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "domain1", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["bob", "domain2", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "domain2", "data2", "write"])); + assert_eq!( + true, + e.enforce(vec!["alice", "domain1", "data1", "read"]) + .unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["alice", "domain1", "data1", "write"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data2", "read"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data2", "write"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data1", "read"]).unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data1", "write"]).unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "domain2", "data2", "read"]).unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "domain2", "data2", "write"]).unwrap() + ); } use crate::MgmtApi; #[test] fn test_rbac_model_with_domains_at_runtime() { - let m = Model::new_from_file("examples/rbac_with_domains_model.conf"); + let m = Model::from_file("examples/rbac_with_domains_model.conf").unwrap(); let adapter = MemoryAdapter::default(); let mut e = Enforcer::new(m, adapter); @@ -670,43 +698,127 @@ mod tests { e.add_grouping_policy(vec!["bob", "admin", "domain2"]) .unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "domain1", "data1", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "domain1", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["bob", "domain2", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "domain2", "data2", "write"])); + assert_eq!( + true, + e.enforce(vec!["alice", "domain1", "data1", "read"]) + .unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["alice", "domain1", "data1", "write"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data2", "read"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data2", "write"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data1", "read"]).unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data1", "write"]).unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "domain2", "data2", "read"]).unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "domain2", "data2", "write"]).unwrap() + ); e.remove_filtered_policy(1, vec!["domain1", "data1"]) .unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["bob", "domain2", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "domain2", "data2", "write"])); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data1", "read"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data1", "write"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data2", "read"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data2", "write"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data1", "read"]).unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data1", "write"]).unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "domain2", "data2", "read"]).unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "domain2", "data2", "write"]).unwrap() + ); e.remove_policy(vec!["admin", "domain2", "data2", "read"]) .unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "domain2", "data2", "write"])); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data1", "read"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data1", "write"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data2", "read"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data2", "write"]) + .unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data1", "read"]).unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data1", "write"]).unwrap() + ); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data2", "read"]).unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "domain2", "data2", "write"]).unwrap() + ); } #[test] fn test_rbac_model_with_domains_at_runtime_mock_adapter() { - let m = Model::new_from_file("examples/rbac_with_domains_model.conf"); + let m = Model::from_file("examples/rbac_with_domains_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_domains_policy.csv"); let mut e = Enforcer::new(m, adapter); @@ -716,49 +828,67 @@ mod tests { e.add_grouping_policy(vec!["alice", "admin", "domain3"]) .unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "domain3", "data1", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "domain1", "data1", "read"])); + assert_eq!( + true, + e.enforce(vec!["alice", "domain3", "data1", "read"]) + .unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["alice", "domain1", "data1", "read"]) + .unwrap() + ); e.remove_filtered_policy(1, vec!["domain1", "data1"]) .unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "domain1", "data1", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "domain2", "data2", "read"])); + assert_eq!( + false, + e.enforce(vec!["alice", "domain1", "data1", "read"]) + .unwrap() + ); + assert_eq!( + true, + e.enforce(vec!["bob", "domain2", "data2", "read"]).unwrap() + ); e.remove_policy(vec!["admin", "domain2", "data2", "read"]) .unwrap(); - assert_eq!(false, e.enforce(vec!["bob", "domain2", "data2", "read"])); + assert_eq!( + false, + e.enforce(vec!["bob", "domain2", "data2", "read"]).unwrap() + ); } #[test] fn test_rbac_model_with_deny() { - let m = Model::new_from_file("examples/rbac_with_deny_model.conf"); + let m = Model::from_file("examples/rbac_with_deny_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_deny_policy.csv"); let e = Enforcer::new(m, adapter); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); } #[test] fn test_rbac_model_with_not_deny() { - let m = Model::new_from_file("examples/rbac_with_not_deny_model.conf"); + let m = Model::from_file("examples/rbac_with_not_deny_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_deny_policy.csv"); let e = Enforcer::new(m, adapter); - assert_eq!(false, e.enforce(vec!["alice", "data2", "write"])); + assert_eq!(false, e.enforce(vec!["alice", "data2", "write"]).unwrap()); } #[test] fn test_rbac_model_with_custom_data() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let mut e = Enforcer::new(m, adapter); @@ -766,25 +896,25 @@ mod tests { e.add_grouping_policy(vec!["bob", "data2_admin", "custom_data"]) .unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); e.remove_grouping_policy(vec!["bob", "data2_admin", "custom_data"]) .unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); } } diff --git a/src/rbac/default_role_manager.rs b/src/rbac/default_role_manager.rs index 5fcf0321..3307c081 100644 --- a/src/rbac/default_role_manager.rs +++ b/src/rbac/default_role_manager.rs @@ -1,4 +1,4 @@ -use crate::errors::CasbinError; +use crate::error::{Error, RbacError}; use crate::rbac::RoleManager; use crate::Result; use std::collections::HashMap; @@ -63,7 +63,9 @@ impl RoleManager for DefaultRoleManager { name2 = format!("{}::{}", domain_val, name2); } if !self.has_role(&name1) || !self.has_role(&name2) { - return Err(CasbinError::new("name1 or name2 doesn't exists").into()); + return Err( + Error::RbacError(RbacError::NotFound(format!("{} OR {}", name1, name2))).into(), + ); } let role1 = self.create_role(&name1); let role2 = self.create_role(&name2); diff --git a/src/rbac_api.rs b/src/rbac_api.rs index 4e0ad01a..a7d1dff7 100644 --- a/src/rbac_api.rs +++ b/src/rbac_api.rs @@ -177,8 +177,10 @@ impl RbacApi for Enforcer { for user in users.iter() { let mut req = permission.clone(); req.insert(0, user); - if self.enforce(req) { - res.push(user.to_owned()); + if let Ok(r) = self.enforce(req) { + if r { + res.push(user.to_owned()); + } } } res @@ -194,7 +196,7 @@ mod tests { #[test] fn test_role_api() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let mut e = Enforcer::new(m, adapter); @@ -232,24 +234,24 @@ mod tests { assert_eq!(vec![String::new(); 0], e.get_roles_for_user("data2_admin")); e.add_role_for_user("alice", "data2_admin").unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); e.delete_role("data2_admin").unwrap(); - assert_eq!(true, e.enforce(vec!["alice", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "data2", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "data1", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "data2", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "data2", "write"])); + 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()); } use std::sync::{Arc, RwLock}; @@ -257,7 +259,7 @@ mod tests { #[test] fn test_role_api_threads() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_policy.csv"); let e = Arc::new(RwLock::new(Enforcer::new(m, adapter))); @@ -365,83 +367,131 @@ mod tests { .unwrap(); assert_eq!( true, - e.read().unwrap().enforce(vec!["alice", "data1", "read"]) + e.read() + .unwrap() + .enforce(vec!["alice", "data1", "read"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["alice", "data1", "write"]) + e.read() + .unwrap() + .enforce(vec!["alice", "data1", "write"]) + .unwrap() ); assert_eq!( true, - e.read().unwrap().enforce(vec!["alice", "data2", "read"]) + e.read() + .unwrap() + .enforce(vec!["alice", "data2", "read"]) + .unwrap() ); assert_eq!( true, - e.read().unwrap().enforce(vec!["alice", "data2", "write"]) + e.read() + .unwrap() + .enforce(vec!["alice", "data2", "write"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["bob", "data1", "read"]) + e.read() + .unwrap() + .enforce(vec!["bob", "data1", "read"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["bob", "data1", "write"]) + e.read() + .unwrap() + .enforce(vec!["bob", "data1", "write"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["bob", "data2", "read"]) + e.read() + .unwrap() + .enforce(vec!["bob", "data2", "read"]) + .unwrap() ); assert_eq!( true, - e.read().unwrap().enforce(vec!["bob", "data2", "write"]) + e.read() + .unwrap() + .enforce(vec!["bob", "data2", "write"]) + .unwrap() ); e.write().unwrap().delete_role("data2_admin").unwrap(); assert_eq!( true, - e.read().unwrap().enforce(vec!["alice", "data1", "read"]) + e.read() + .unwrap() + .enforce(vec!["alice", "data1", "read"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["alice", "data1", "write"]) + e.read() + .unwrap() + .enforce(vec!["alice", "data1", "write"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["alice", "data2", "read"]) + e.read() + .unwrap() + .enforce(vec!["alice", "data2", "read"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["alice", "data2", "write"]) + e.read() + .unwrap() + .enforce(vec!["alice", "data2", "write"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["bob", "data1", "read"]) + e.read() + .unwrap() + .enforce(vec!["bob", "data1", "read"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["bob", "data1", "write"]) + e.read() + .unwrap() + .enforce(vec!["bob", "data1", "write"]) + .unwrap() ); assert_eq!( false, - e.read().unwrap().enforce(vec!["bob", "data2", "read"]) + e.read() + .unwrap() + .enforce(vec!["bob", "data2", "read"]) + .unwrap() ); assert_eq!( true, - e.read().unwrap().enforce(vec!["bob", "data2", "write"]) + e.read() + .unwrap() + .enforce(vec!["bob", "data2", "write"]) + .unwrap() ); } #[test] fn test_permission_api() { - let m = Model::new_from_file("examples/basic_without_resources_model.conf"); + let m = Model::from_file("examples/basic_without_resources_model.conf").unwrap(); let adapter = FileAdapter::new("examples/basic_without_resources_policy.csv"); let mut e = Enforcer::new(m, adapter); - assert_eq!(true, e.enforce(vec!["alice", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "write"])); + 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!( vec![vec!["alice", "read"]], @@ -459,36 +509,36 @@ mod tests { e.delete_permission(vec!["read"]).unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "write"])); + 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()); e.add_permission_for_user("bob", vec!["read"]).unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "write"])); - assert_eq!(true, e.enforce(vec!["bob", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "write"])); + 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()); e.delete_permission_for_user("bob", vec!["read"]).unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "read"])); - assert_eq!(true, e.enforce(vec!["bob", "write"])); + 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()); e.delete_permissions_for_user("bob").unwrap(); - assert_eq!(false, e.enforce(vec!["alice", "read"])); - assert_eq!(false, e.enforce(vec!["alice", "write"])); - assert_eq!(false, e.enforce(vec!["bob", "read"])); - assert_eq!(false, e.enforce(vec!["bob", "write"])); + 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()); } #[test] fn test_implicit_role_api() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_hierarchy_policy.csv"); let mut e = Enforcer::new(m, adapter); @@ -514,7 +564,7 @@ mod tests { #[test] fn test_implicit_permission_api() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_hierarchy_policy.csv"); let mut e = Enforcer::new(m, adapter); @@ -546,7 +596,7 @@ mod tests { #[test] fn test_implicit_user_api() { - let m = Model::new_from_file("examples/rbac_model.conf"); + let m = Model::from_file("examples/rbac_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_hierarchy_policy.csv"); let e = Enforcer::new(m, adapter); @@ -571,7 +621,7 @@ mod tests { #[test] fn test_implicit_permission_api_with_domain() { - let m = Model::new_from_file("examples/rbac_with_domains_model.conf"); + let m = Model::from_file("examples/rbac_with_domains_model.conf").unwrap(); let adapter = FileAdapter::new("examples/rbac_with_hierarchy_with_domains_policy.csv"); let mut e = Enforcer::new(m, adapter); From b7ceeeb658af9f3861207b1b8d9b5daeede58f72 Mon Sep 17 00:00:00 2001 From: Cheng JIANG Date: Fri, 3 Jan 2020 01:27:24 +0800 Subject: [PATCH 2/2] resolve clippy errors --- src/enforcer.rs | 64 ++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/enforcer.rs b/src/enforcer.rs index 3304139c..c383458c 100644 --- a/src/enforcer.rs +++ b/src/enforcer.rs @@ -116,46 +116,62 @@ impl Enforcer { .model .model .get("r") - .ok_or(Error::ModelError( - ModelError::R("Missing request definition in conf file".to_owned()).into(), - ))? + .ok_or_else(|| { + Error::ModelError(ModelError::R( + "Missing request definition in conf file".to_owned(), + )) + })? .get("r") - .ok_or(Error::ModelError( - ModelError::R("Missing request secion in conf file".to_owned()).into(), - ))?; + .ok_or_else(|| { + Error::ModelError(ModelError::R( + "Missing request secion in conf file".to_owned(), + )) + })?; let p = self .model .model .get("p") - .ok_or(Error::ModelError( - ModelError::P("Missing policy definition in conf file".to_owned()).into(), - ))? + .ok_or_else(|| { + Error::ModelError(ModelError::P( + "Missing policy definition in conf file".to_owned(), + )) + })? .get("p") - .ok_or(Error::ModelError( - ModelError::P("Missing policy section in conf file".to_owned()).into(), - ))?; + .ok_or_else(|| { + Error::ModelError(ModelError::P( + "Missing policy section in conf file".to_owned(), + )) + })?; let m = self .model .model .get("m") - .ok_or(Error::ModelError( - ModelError::M("Missing matcher definition in conf file".to_owned()).into(), - ))? + .ok_or_else(|| { + Error::ModelError(ModelError::M( + "Missing matcher definition in conf file".to_owned(), + )) + })? .get("m") - .ok_or(Error::ModelError( - ModelError::M("Missing matcher section in conf file".to_owned()).into(), - ))?; + .ok_or_else(|| { + Error::ModelError(ModelError::M( + "Missing matcher section in conf file".to_owned(), + )) + })?; let e = self .model .model .get("e") - .ok_or(Error::ModelError( - ModelError::E("Missing effector definition in conf file".to_owned()).into(), - ))? + .ok_or_else(|| { + Error::ModelError(ModelError::E( + "Missing effector definition in conf file".to_owned(), + )) + })? .get("e") - .ok_or(Error::ModelError( - ModelError::E("Missing effector section in conf file".to_owned()).into(), - ))?; + .ok_or_else(|| { + Error::ModelError(ModelError::E( + "Missing effector section in conf file".to_owned(), + )) + })?; for (i, token) in r.tokens.iter().enumerate() { let scope_exp = format!("let {} = \"{}\";", token.clone(), rvals[i]);