casbin/
enforcer.rs

1use crate::{
2    adapter::{Adapter, Filter},
3    convert::{EnforceArgs, TryIntoAdapter, TryIntoModel},
4    core_api::CoreApi,
5    effector::{DefaultEffector, EffectKind, Effector},
6    emitter::{Event, EventData, EventEmitter},
7    error::{ModelError, PolicyError, RequestError},
8    get_or_err, get_or_err_with_context,
9    management_api::MgmtApi,
10    model::{FunctionMap, Model, OperatorFunction},
11    rbac::{DefaultRoleManager, RoleManager},
12    register_g_function,
13    util::{escape_assertion, escape_eval},
14    Result,
15};
16
17#[cfg(any(feature = "logging", feature = "watcher"))]
18use crate::emitter::notify_logger_and_watcher;
19
20#[cfg(feature = "watcher")]
21use crate::watcher::Watcher;
22
23#[cfg(feature = "logging")]
24use crate::{DefaultLogger, Logger};
25
26use async_trait::async_trait;
27use once_cell::sync::Lazy;
28use parking_lot::RwLock;
29use rhai::{
30    def_package,
31    packages::{
32        ArithmeticPackage, BasicArrayPackage, BasicMapPackage, LogicPackage,
33        Package,
34    },
35    Dynamic, Engine, EvalAltResult, ImmutableString, Scope,
36};
37
38def_package! {
39    pub CasbinPackage(lib) {
40        ArithmeticPackage::init(lib);
41        LogicPackage::init(lib);
42        BasicArrayPackage::init(lib);
43        BasicMapPackage::init(lib);
44
45        lib.set_native_fn("escape_assertion", |s: ImmutableString| {
46            Ok(escape_assertion(&s))
47        });
48    }
49}
50
51static CASBIN_PACKAGE: Lazy<CasbinPackage> = Lazy::new(CasbinPackage::new);
52
53use std::{cmp::max, collections::HashMap, sync::Arc};
54
55type EventCallback = fn(&mut Enforcer, EventData);
56
57/// Enforcer is the main interface for authorization enforcement and policy management.
58pub struct Enforcer {
59    model: Box<dyn Model>,
60    adapter: Box<dyn Adapter>,
61    fm: FunctionMap,
62    eft: Box<dyn Effector>,
63    rm: Arc<RwLock<dyn RoleManager>>,
64    enabled: bool,
65    auto_save: bool,
66    auto_build_role_links: bool,
67    #[cfg(feature = "watcher")]
68    auto_notify_watcher: bool,
69    #[cfg(feature = "watcher")]
70    watcher: Option<Box<dyn Watcher>>,
71    events: HashMap<Event, Vec<EventCallback>>,
72    engine: Engine,
73    #[cfg(feature = "logging")]
74    logger: Box<dyn Logger>,
75}
76
77pub struct EnforceContext {
78    pub r_type: String,
79    pub p_type: String,
80    pub e_type: String,
81    pub m_type: String,
82}
83
84impl EnforceContext {
85    pub fn new(suffix: &str) -> Self {
86        Self {
87            r_type: format!("r{}", suffix),
88            p_type: format!("p{}", suffix),
89            e_type: format!("e{}", suffix),
90            m_type: format!("m{}", suffix),
91        }
92    }
93    pub fn get_cache_key(&self) -> String {
94        format!(
95            "EnforceContext{{{}-{}-{}-{}}}",
96            &self.r_type, &self.p_type, &self.e_type, &self.m_type,
97        )
98    }
99}
100
101impl EventEmitter<Event> for Enforcer {
102    fn on(&mut self, e: Event, f: fn(&mut Self, EventData)) {
103        self.events.entry(e).or_default().push(f)
104    }
105
106    fn off(&mut self, e: Event) {
107        self.events.remove(&e);
108    }
109
110    fn emit(&mut self, e: Event, d: EventData) {
111        if let Some(cbs) = self.events.get(&e) {
112            for cb in cbs.clone().iter() {
113                cb(self, d.clone())
114            }
115        }
116    }
117}
118
119impl Enforcer {
120    pub(crate) fn private_enforce(
121        &self,
122        rvals: &[Dynamic],
123    ) -> Result<(bool, Option<Vec<usize>>)> {
124        if !self.enabled {
125            return Ok((true, None));
126        }
127
128        let mut scope: Scope = Scope::new();
129
130        let r_ast = get_or_err!(self, "r", ModelError::R, "request");
131        let p_ast = get_or_err!(self, "p", ModelError::P, "policy");
132        let m_ast = get_or_err!(self, "m", ModelError::M, "matcher");
133        let e_ast = get_or_err!(self, "e", ModelError::E, "effector");
134
135        if r_ast.tokens.len() != rvals.len() {
136            return Err(RequestError::UnmatchRequestDefinition(
137                r_ast.tokens.len(),
138                rvals.len(),
139            )
140            .into());
141        }
142
143        for (rtoken, rval) in r_ast.tokens.iter().zip(rvals.iter()) {
144            scope.push_constant_dynamic(rtoken, rval.to_owned());
145        }
146
147        let policies = p_ast.get_policy();
148        let (policy_len, scope_len) = (policies.len(), scope.len());
149
150        let mut eft_stream =
151            self.eft.new_stream(&e_ast.value, max(policy_len, 1));
152        let m_ast_compiled = self
153            .engine
154            .compile_expression(escape_eval(&m_ast.value))
155            .map_err(Into::<Box<EvalAltResult>>::into)?;
156
157        if policy_len == 0 {
158            for token in p_ast.tokens.iter() {
159                scope.push_constant(token, String::new());
160            }
161
162            let eval_result = self
163                .engine
164                .eval_ast_with_scope::<bool>(&mut scope, &m_ast_compiled)?;
165            let eft = if eval_result {
166                EffectKind::Allow
167            } else {
168                EffectKind::Indeterminate
169            };
170
171            eft_stream.push_effect(eft);
172
173            return Ok((eft_stream.next(), None));
174        }
175
176        for pvals in policies {
177            scope.rewind(scope_len);
178
179            if p_ast.tokens.len() != pvals.len() {
180                return Err(PolicyError::UnmatchPolicyDefinition(
181                    p_ast.tokens.len(),
182                    pvals.len(),
183                )
184                .into());
185            }
186            for (ptoken, pval) in p_ast.tokens.iter().zip(pvals.iter()) {
187                scope.push_constant(ptoken, pval.to_owned());
188            }
189
190            let eval_result = self
191                .engine
192                .eval_ast_with_scope::<bool>(&mut scope, &m_ast_compiled)?;
193            let eft = match p_ast.tokens.iter().position(|x| x == "p_eft") {
194                Some(j) if eval_result => {
195                    let p_eft = &pvals[j];
196                    if p_eft == "deny" {
197                        EffectKind::Deny
198                    } else if p_eft == "allow" {
199                        EffectKind::Allow
200                    } else {
201                        EffectKind::Indeterminate
202                    }
203                }
204                None if eval_result => EffectKind::Allow,
205                _ => EffectKind::Indeterminate,
206            };
207
208            if eft_stream.push_effect(eft) {
209                break;
210            }
211        }
212
213        Ok((eft_stream.next(), {
214            #[cfg(feature = "explain")]
215            {
216                eft_stream.explain()
217            }
218            #[cfg(not(feature = "explain"))]
219            {
220                None
221            }
222        }))
223    }
224
225    pub(crate) fn private_enforce_with_context(
226        &self,
227        ctx: EnforceContext,
228        rvals: &[Dynamic],
229    ) -> Result<(bool, Option<Vec<usize>>)> {
230        if !self.enabled {
231            return Ok((true, None));
232        }
233
234        let mut scope: Scope = Scope::new();
235        let r_ast = get_or_err_with_context!(
236            self,
237            "r",
238            &ctx.r_type,
239            ModelError::R,
240            "request"
241        );
242        let p_ast = get_or_err_with_context!(
243            self,
244            "p",
245            &ctx.p_type,
246            ModelError::P,
247            "policy"
248        );
249        let m_ast = get_or_err_with_context!(
250            self,
251            "m",
252            &ctx.m_type,
253            ModelError::M,
254            "matcher"
255        );
256        let e_ast = get_or_err_with_context!(
257            self,
258            "e",
259            &ctx.e_type,
260            ModelError::E,
261            "effector"
262        );
263
264        if r_ast.tokens.len() != rvals.len() {
265            return Err(RequestError::UnmatchRequestDefinition(
266                r_ast.tokens.len(),
267                rvals.len(),
268            )
269            .into());
270        }
271
272        for (rtoken, rval) in r_ast.tokens.iter().zip(rvals.iter()) {
273            scope.push_constant_dynamic(rtoken, rval.to_owned());
274        }
275
276        let policies = p_ast.get_policy();
277        let (policy_len, scope_len) = (policies.len(), scope.len());
278
279        let mut eft_stream =
280            self.eft.new_stream(&e_ast.value, max(policy_len, 1));
281        let m_ast_compiled = self
282            .engine
283            .compile_expression(escape_eval(&m_ast.value))
284            .map_err(Into::<Box<EvalAltResult>>::into)?;
285
286        if policy_len == 0 {
287            for token in p_ast.tokens.iter() {
288                scope.push_constant(token, String::new());
289            }
290
291            let eval_result = self
292                .engine
293                .eval_ast_with_scope::<bool>(&mut scope, &m_ast_compiled)?;
294            let eft = if eval_result {
295                EffectKind::Allow
296            } else {
297                EffectKind::Indeterminate
298            };
299
300            eft_stream.push_effect(eft);
301
302            return Ok((eft_stream.next(), None));
303        }
304
305        for pvals in policies {
306            scope.rewind(scope_len);
307
308            if p_ast.tokens.len() != pvals.len() {
309                return Err(PolicyError::UnmatchPolicyDefinition(
310                    p_ast.tokens.len(),
311                    pvals.len(),
312                )
313                .into());
314            }
315            for (ptoken, pval) in p_ast.tokens.iter().zip(pvals.iter()) {
316                scope.push_constant(ptoken, pval.to_owned());
317            }
318
319            let eval_result = self
320                .engine
321                .eval_ast_with_scope::<bool>(&mut scope, &m_ast_compiled)?;
322            let eft = match p_ast.tokens.iter().position(|x| x == "p_eft") {
323                Some(j) if eval_result => {
324                    let p_eft = &pvals[j];
325                    if p_eft == "deny" {
326                        EffectKind::Deny
327                    } else if p_eft == "allow" {
328                        EffectKind::Allow
329                    } else {
330                        EffectKind::Indeterminate
331                    }
332                }
333                None if eval_result => EffectKind::Allow,
334                _ => EffectKind::Indeterminate,
335            };
336
337            if eft_stream.push_effect(eft) {
338                break;
339            }
340        }
341
342        Ok((eft_stream.next(), {
343            #[cfg(feature = "explain")]
344            {
345                eft_stream.explain()
346            }
347            #[cfg(not(feature = "explain"))]
348            {
349                None
350            }
351        }))
352    }
353
354    fn register_function(engine: &mut Engine, key: &str, f: OperatorFunction) {
355        match f {
356            OperatorFunction::Arg0(func) => {
357                engine.register_fn(key, func);
358            }
359            OperatorFunction::Arg1(func) => {
360                engine.register_fn(key, func);
361            }
362            OperatorFunction::Arg2(func) => {
363                engine.register_fn(key, func);
364            }
365            OperatorFunction::Arg3(func) => {
366                engine.register_fn(key, func);
367            }
368            OperatorFunction::Arg4(func) => {
369                engine.register_fn(key, func);
370            }
371            OperatorFunction::Arg5(func) => {
372                engine.register_fn(key, func);
373            }
374            OperatorFunction::Arg6(func) => {
375                engine.register_fn(key, func);
376            }
377        }
378    }
379
380    pub(crate) fn register_g_functions(&mut self) -> Result<()> {
381        if let Some(ast_map) = self.model.get_model().get("g") {
382            for (fname, ast) in ast_map {
383                register_g_function!(self, fname, ast);
384            }
385        }
386
387        Ok(())
388    }
389}
390
391#[async_trait]
392impl CoreApi for Enforcer {
393    #[allow(clippy::box_default)]
394    async fn new_raw<M: TryIntoModel, A: TryIntoAdapter>(
395        m: M,
396        a: A,
397    ) -> Result<Self> {
398        let model = m.try_into_model().await?;
399        let adapter = a.try_into_adapter().await?;
400        let fm = FunctionMap::default();
401        let eft = Box::new(DefaultEffector);
402        let rm = Arc::new(RwLock::new(DefaultRoleManager::new(10)));
403
404        let mut engine = Engine::new_raw();
405
406        engine.register_global_module(CASBIN_PACKAGE.as_shared_module());
407
408        for (key, &func) in fm.get_functions() {
409            Self::register_function(&mut engine, key, func);
410        }
411
412        let mut e = Self {
413            model,
414            adapter,
415            fm,
416            eft,
417            rm,
418            enabled: true,
419            auto_save: true,
420            auto_build_role_links: true,
421            #[cfg(feature = "watcher")]
422            auto_notify_watcher: true,
423            #[cfg(feature = "watcher")]
424            watcher: None,
425            events: HashMap::new(),
426            engine,
427            #[cfg(feature = "logging")]
428            logger: Box::new(DefaultLogger::default()),
429        };
430
431        #[cfg(any(feature = "logging", feature = "watcher"))]
432        e.on(Event::PolicyChange, notify_logger_and_watcher);
433
434        e.register_g_functions()?;
435
436        Ok(e)
437    }
438
439    #[inline]
440    async fn new<M: TryIntoModel, A: TryIntoAdapter>(
441        m: M,
442        a: A,
443    ) -> Result<Self> {
444        let mut e = Self::new_raw(m, a).await?;
445
446        // Do not initialize the full policy when using a filtered adapter
447        if !e.adapter.is_filtered() {
448            e.load_policy().await?;
449        }
450        Ok(e)
451    }
452
453    #[inline]
454    fn add_function(&mut self, fname: &str, f: OperatorFunction) {
455        self.fm.add_function(fname, f);
456        Self::register_function(&mut self.engine, fname, f);
457    }
458
459    #[inline]
460    fn get_model(&self) -> &dyn Model {
461        &*self.model
462    }
463
464    #[inline]
465    fn get_mut_model(&mut self) -> &mut dyn Model {
466        &mut *self.model
467    }
468
469    #[inline]
470    fn get_adapter(&self) -> &dyn Adapter {
471        &*self.adapter
472    }
473
474    #[inline]
475    fn get_mut_adapter(&mut self) -> &mut dyn Adapter {
476        &mut *self.adapter
477    }
478
479    #[cfg(feature = "watcher")]
480    #[inline]
481    fn set_watcher(&mut self, w: Box<dyn Watcher>) {
482        self.watcher = Some(w);
483    }
484
485    #[cfg(feature = "logging")]
486    #[inline]
487    fn get_logger(&self) -> &dyn Logger {
488        &*self.logger
489    }
490
491    #[cfg(feature = "logging")]
492    #[inline]
493    fn set_logger(&mut self, l: Box<dyn Logger>) {
494        self.logger = l;
495    }
496
497    #[cfg(feature = "watcher")]
498    #[inline]
499    fn get_watcher(&self) -> Option<&dyn Watcher> {
500        if let Some(ref watcher) = self.watcher {
501            Some(&**watcher)
502        } else {
503            None
504        }
505    }
506
507    #[cfg(feature = "watcher")]
508    #[inline]
509    fn get_mut_watcher(&mut self) -> Option<&mut dyn Watcher> {
510        if let Some(ref mut watcher) = self.watcher {
511            Some(&mut **watcher)
512        } else {
513            None
514        }
515    }
516
517    #[inline]
518    fn get_role_manager(&self) -> Arc<RwLock<dyn RoleManager>> {
519        Arc::clone(&self.rm)
520    }
521
522    #[inline]
523    fn set_role_manager(
524        &mut self,
525        rm: Arc<RwLock<dyn RoleManager>>,
526    ) -> Result<()> {
527        self.rm = rm;
528        if self.auto_build_role_links {
529            self.build_role_links()?;
530        }
531
532        self.register_g_functions()
533    }
534
535    async fn set_model<M: TryIntoModel>(&mut self, m: M) -> Result<()> {
536        self.model = m.try_into_model().await?;
537        self.load_policy().await?;
538        Ok(())
539    }
540
541    async fn set_adapter<A: TryIntoAdapter>(&mut self, a: A) -> Result<()> {
542        self.adapter = a.try_into_adapter().await?;
543        self.load_policy().await?;
544        Ok(())
545    }
546
547    #[inline]
548    fn set_effector(&mut self, e: Box<dyn Effector>) {
549        self.eft = e;
550    }
551
552    /// Enforce decides whether a "subject" can access a "object" with the operation "action",
553    /// input parameters are usually: (sub, obj, act).
554    ///
555    /// # Examples
556    /// ```
557    /// use casbin::prelude::*;
558    /// #[cfg(feature = "runtime-async-std")]
559    /// #[async_std::main]
560    /// async fn main() -> Result<()> {
561    ///     let mut e = Enforcer::new("examples/basic_model.conf", "examples/basic_policy.csv").await?;
562    ///     assert_eq!(true, e.enforce(("alice", "data1", "read"))?);
563    ///     Ok(())
564    /// }
565    ///
566    /// #[cfg(feature = "runtime-tokio")]
567    /// #[tokio::main]
568    /// async fn main() -> Result<()> {
569    ///     let mut e = Enforcer::new("examples/basic_model.conf", "examples/basic_policy.csv").await?;
570    ///     assert_eq!(true, e.enforce(("alice", "data1", "read"))?);
571    ///
572    ///     Ok(())
573    /// }
574    /// #[cfg(all(not(feature = "runtime-async-std"), not(feature = "runtime-tokio")))]
575    /// fn main() {}
576    /// ```
577    fn enforce<ARGS: EnforceArgs>(&self, rvals: ARGS) -> Result<bool> {
578        let rvals = rvals.try_into_vec()?;
579        #[allow(unused_variables)]
580        let (authorized, indices) = self.private_enforce(&rvals)?;
581
582        #[cfg(feature = "logging")]
583        {
584            self.logger.print_enforce_log(
585                rvals.iter().map(|x| x.to_string()).collect(),
586                authorized,
587                false,
588            );
589
590            #[cfg(feature = "explain")]
591            if let Some(indices) = indices {
592                let all_rules = get_or_err!(self, "p", ModelError::P, "policy")
593                    .get_policy();
594
595                let rules: Vec<String> = indices
596                    .into_iter()
597                    .filter_map(|y| {
598                        all_rules.iter().nth(y).map(|x| x.join(", "))
599                    })
600                    .collect();
601
602                self.logger.print_explain_log(rules);
603            }
604        }
605
606        Ok(authorized)
607    }
608    /// Enforce decides whether a "subject" can access a "object" with the operation "action",
609    /// input parameters are usually: (sub, obj, act).
610    /// this function will add suffix to each model eg. r2, p2, e2, m2, g2,
611    ///
612    /// # Examples
613    /// ```
614    /// use casbin::prelude::*;
615    /// use casbin::EnforceContext;
616    ///
617    /// #[cfg(feature = "runtime-async-std")]
618    /// #[async_std::main]
619    /// async fn main() -> Result<()> {
620    ///     let mut e = Enforcer::new("examples/multi_section_model.conf", "examples/multi_section_policy.csv").await?;
621    ///     assert_eq!(true, e.enforce(("alice", "read", "project1"))?);
622    ///     let ctx = EnforceContext::new("2");
623    ///     assert_eq!(true, e.enforce_with_context(ctx, ("james", "execute"))?);
624    ///     Ok(())
625    /// }
626    ///
627    /// #[cfg(feature = "runtime-tokio")]
628    /// #[tokio::main]
629    /// async fn main() -> Result<()> {
630    ///     let mut e = Enforcer::new("examples/multi_section_model.conf", "examples/multi_section_policy.csv").await?;
631    ///     assert_eq!(true, e.enforce(("alice", "read", "project1"))?);
632    ///     let ctx = EnforceContext::new("2");
633    ///     assert_eq!(true, e.enforce_with_context(ctx, ("james", "execute"))?);
634    ///
635    ///     Ok(())
636    /// }
637    /// #[cfg(all(not(feature = "runtime-async-std"), not(feature = "runtime-tokio")))]
638    /// fn main() {}
639    /// ```
640    fn enforce_with_context<ARGS: EnforceArgs>(
641        &self,
642        ctx: EnforceContext,
643        rvals: ARGS,
644    ) -> Result<bool> {
645        let rvals = rvals.try_into_vec()?;
646        #[allow(unused_variables)]
647        let (authorized, indices) =
648            self.private_enforce_with_context(ctx, &rvals)?;
649
650        #[cfg(feature = "logging")]
651        {
652            self.logger.print_enforce_log(
653                rvals.iter().map(|x| x.to_string()).collect(),
654                authorized,
655                false,
656            );
657
658            #[cfg(feature = "explain")]
659            if let Some(indices) = indices {
660                let all_rules = get_or_err!(self, "p", ModelError::P, "policy")
661                    .get_policy();
662
663                let rules: Vec<String> = indices
664                    .into_iter()
665                    .filter_map(|y| {
666                        all_rules.iter().nth(y).map(|x| x.join(", "))
667                    })
668                    .collect();
669
670                self.logger.print_explain_log(rules);
671            }
672        }
673
674        Ok(authorized)
675    }
676
677    fn enforce_mut<ARGS: EnforceArgs>(&mut self, rvals: ARGS) -> Result<bool> {
678        self.enforce(rvals)
679    }
680
681    #[cfg(feature = "explain")]
682    fn enforce_ex<ARGS: EnforceArgs>(
683        &self,
684        rvals: ARGS,
685    ) -> Result<(bool, Vec<Vec<String>>)> {
686        let rvals = rvals.try_into_vec()?;
687        #[allow(unused_variables)]
688        let (authorized, indices) = self.private_enforce(&rvals)?;
689
690        let rules = match indices {
691            Some(indices) => {
692                let all_rules = get_or_err!(self, "p", ModelError::P, "policy")
693                    .get_policy();
694
695                indices
696                    .into_iter()
697                    .filter_map(|y| all_rules.iter().nth(y).cloned())
698                    .collect::<Vec<_>>()
699            }
700            None => vec![],
701        };
702
703        Ok((authorized, rules))
704    }
705
706    fn build_role_links(&mut self) -> Result<()> {
707        self.rm.write().clear();
708        self.model.build_role_links(Arc::clone(&self.rm))?;
709
710        Ok(())
711    }
712
713    #[cfg(feature = "incremental")]
714    fn build_incremental_role_links(&mut self, d: EventData) -> Result<()> {
715        self.model
716            .build_incremental_role_links(Arc::clone(&self.rm), d)?;
717
718        Ok(())
719    }
720
721    async fn load_policy(&mut self) -> Result<()> {
722        self.model.clear_policy();
723        self.adapter.load_policy(&mut *self.model).await?;
724
725        if self.auto_build_role_links {
726            self.build_role_links()?;
727        }
728
729        Ok(())
730    }
731
732    async fn load_filtered_policy<'a>(&mut self, f: Filter<'a>) -> Result<()> {
733        self.model.clear_policy();
734        self.adapter
735            .load_filtered_policy(&mut *self.model, f)
736            .await?;
737
738        if self.auto_build_role_links {
739            self.build_role_links()?;
740        }
741
742        Ok(())
743    }
744
745    #[inline]
746    fn is_filtered(&self) -> bool {
747        self.adapter.is_filtered()
748    }
749
750    #[inline]
751    fn is_enabled(&self) -> bool {
752        self.enabled
753    }
754
755    async fn save_policy(&mut self) -> Result<()> {
756        assert!(!self.is_filtered(), "cannot save filtered policy");
757
758        self.adapter.save_policy(&mut *self.model).await?;
759
760        let mut policies = self.get_all_policy();
761        let gpolicies = self.get_all_grouping_policy();
762
763        policies.extend(gpolicies);
764
765        #[cfg(any(feature = "logging", feature = "watcher"))]
766        self.emit(Event::PolicyChange, EventData::SavePolicy(policies));
767
768        Ok(())
769    }
770
771    #[inline]
772    async fn clear_policy(&mut self) -> Result<()> {
773        if self.auto_save {
774            self.adapter.clear_policy().await?;
775        }
776        self.model.clear_policy();
777
778        #[cfg(any(feature = "logging", feature = "watcher"))]
779        self.emit(Event::PolicyChange, EventData::ClearPolicy);
780
781        Ok(())
782    }
783
784    #[inline]
785    fn enable_enforce(&mut self, enabled: bool) {
786        self.enabled = enabled;
787
788        #[cfg(feature = "logging")]
789        self.logger.print_status_log(enabled);
790    }
791
792    #[cfg(feature = "logging")]
793    #[inline]
794    fn enable_log(&mut self, enabled: bool) {
795        self.logger.enable_log(enabled);
796    }
797
798    #[inline]
799    fn enable_auto_save(&mut self, auto_save: bool) {
800        self.auto_save = auto_save;
801    }
802
803    #[inline]
804    fn enable_auto_build_role_links(&mut self, auto_build_role_links: bool) {
805        self.auto_build_role_links = auto_build_role_links;
806    }
807
808    #[cfg(feature = "watcher")]
809    #[inline]
810    fn enable_auto_notify_watcher(&mut self, auto_notify_watcher: bool) {
811        if !auto_notify_watcher {
812            self.off(Event::PolicyChange);
813        } else {
814            self.on(Event::PolicyChange, notify_logger_and_watcher);
815        }
816
817        self.auto_notify_watcher = auto_notify_watcher;
818    }
819
820    #[inline]
821    fn has_auto_save_enabled(&self) -> bool {
822        self.auto_save
823    }
824
825    #[cfg(feature = "watcher")]
826    #[inline]
827    fn has_auto_notify_watcher_enabled(&self) -> bool {
828        self.auto_notify_watcher
829    }
830
831    #[inline]
832    fn has_auto_build_role_links_enabled(&self) -> bool {
833        self.auto_build_role_links
834    }
835}
836
837#[cfg(test)]
838mod tests {
839    use super::*;
840    use crate::prelude::*;
841
842    fn is_send<T: Send>() -> bool {
843        true
844    }
845
846    fn is_sync<T: Sync>() -> bool {
847        true
848    }
849
850    #[test]
851    fn test_send_sync() {
852        assert!(is_send::<Enforcer>());
853        assert!(is_sync::<Enforcer>());
854    }
855
856    #[cfg(not(target_arch = "wasm32"))]
857    #[cfg_attr(
858        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
859        async_std::test
860    )]
861    #[cfg_attr(
862        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
863        tokio::test
864    )]
865    async fn test_enforcer_swap_adapter_type() {
866        let mut m = DefaultModel::default();
867        m.add_def("r", "r", "sub, obj, act");
868        m.add_def("p", "p", "sub, obj, act");
869        m.add_def("e", "e", "some(where (p.eft == allow))");
870        m.add_def(
871            "m",
872            "m",
873            "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)",
874        );
875
876        let file = FileAdapter::new("examples/basic_policy.csv");
877        let mem = MemoryAdapter::default();
878        let mut e = Enforcer::new(m, file).await.unwrap();
879        // this should fail since FileAdapter has basically no add_policy
880        assert!(e
881            .adapter
882            .add_policy(
883                "p",
884                "p",
885                vec!["alice".into(), "data".into(), "read".into()]
886            )
887            .await
888            .unwrap());
889        e.set_adapter(mem).await.unwrap();
890        // this passes since our MemoryAdapter has a working add_policy method
891        assert!(e
892            .adapter
893            .add_policy(
894                "p",
895                "p",
896                vec!["alice".into(), "data".into(), "read".into()]
897            )
898            .await
899            .unwrap())
900    }
901
902    #[cfg(not(target_arch = "wasm32"))]
903    #[cfg_attr(
904        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
905        async_std::test
906    )]
907    #[cfg_attr(
908        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
909        tokio::test
910    )]
911    async fn test_key_match_model_in_memory() {
912        let mut m = DefaultModel::default();
913        m.add_def("r", "r", "sub, obj, act");
914        m.add_def("p", "p", "sub, obj, act");
915        m.add_def("e", "e", "some(where (p.eft == allow))");
916        m.add_def(
917            "m",
918            "m",
919            "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)",
920        );
921
922        let adapter = FileAdapter::new("examples/keymatch_policy.csv");
923        let e = Enforcer::new(m, adapter).await.unwrap();
924        assert_eq!(
925            true,
926            e.enforce(("alice", "/alice_data/resource1", "GET"))
927                .unwrap()
928        );
929        assert_eq!(
930            true,
931            e.enforce(("alice", "/alice_data/resource1", "POST"))
932                .unwrap()
933        );
934        assert_eq!(
935            true,
936            e.enforce(("alice", "/alice_data/resource2", "GET"))
937                .unwrap()
938        );
939        assert_eq!(
940            false,
941            e.enforce(("alice", "/alice_data/resource2", "POST"))
942                .unwrap()
943        );
944        assert_eq!(
945            false,
946            e.enforce(("alice", "/bob_data/resource1", "GET")).unwrap()
947        );
948        assert_eq!(
949            false,
950            e.enforce(("alice", "/bob_data/resource1", "POST")).unwrap()
951        );
952        assert_eq!(
953            false,
954            e.enforce(("alice", "/bob_data/resource2", "GET")).unwrap()
955        );
956        assert_eq!(
957            false,
958            e.enforce(("alice", "/bob_data/resource2", "POST")).unwrap()
959        );
960
961        assert_eq!(
962            false,
963            e.enforce(("bob", "/alice_data/resource1", "GET")).unwrap()
964        );
965        assert_eq!(
966            false,
967            e.enforce(("bob", "/alice_data/resource1", "POST")).unwrap()
968        );
969        assert_eq!(
970            true,
971            e.enforce(("bob", "/alice_data/resource2", "GET")).unwrap()
972        );
973        assert_eq!(
974            false,
975            e.enforce(("bob", "/alice_data/resource2", "POST")).unwrap()
976        );
977        assert_eq!(
978            false,
979            e.enforce(("bob", "/bob_data/resource1", "GET")).unwrap()
980        );
981        assert_eq!(
982            true,
983            e.enforce(("bob", "/bob_data/resource1", "POST")).unwrap()
984        );
985        assert_eq!(
986            false,
987            e.enforce(("bob", "/bob_data/resource2", "GET")).unwrap()
988        );
989        assert_eq!(
990            true,
991            e.enforce(("bob", "/bob_data/resource2", "POST")).unwrap()
992        );
993
994        assert_eq!(true, e.enforce(("cathy", "/cathy_data", "GET")).unwrap());
995        assert_eq!(true, e.enforce(("cathy", "/cathy_data", "POST")).unwrap());
996        assert_eq!(
997            false,
998            e.enforce(("cathy", "/cathy_data", "DELETE")).unwrap()
999        );
1000    }
1001
1002    #[cfg(not(target_arch = "wasm32"))]
1003    #[cfg_attr(
1004        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1005        async_std::test
1006    )]
1007    #[cfg_attr(
1008        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1009        tokio::test
1010    )]
1011    async fn test_key_match_model_in_memory_deny() {
1012        let mut m = DefaultModel::default();
1013        m.add_def("r", "r", "sub, obj, act");
1014        m.add_def("p", "p", "sub, obj, act");
1015        m.add_def("e", "e", "!some(where (p.eft == deny))");
1016        m.add_def(
1017            "m",
1018            "m",
1019            "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)",
1020        );
1021
1022        let adapter = FileAdapter::new("examples/keymatch_policy.csv");
1023        let e = Enforcer::new(m, adapter).await.unwrap();
1024        assert_eq!(
1025            true,
1026            e.enforce(("alice", "/alice_data/resource2", "POST"))
1027                .unwrap()
1028        );
1029    }
1030
1031    use crate::RbacApi;
1032    #[cfg(not(target_arch = "wasm32"))]
1033    #[cfg_attr(
1034        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1035        async_std::test
1036    )]
1037    #[cfg_attr(
1038        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1039        tokio::test
1040    )]
1041    async fn test_rbac_model_in_memory_indeterminate() {
1042        let mut m = DefaultModel::default();
1043        m.add_def("r", "r", "sub, obj, act");
1044        m.add_def("p", "p", "sub, obj, act");
1045        m.add_def("g", "g", "_, _");
1046        m.add_def("e", "e", "some(where (p.eft == allow))");
1047        m.add_def(
1048            "m",
1049            "m",
1050            "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act",
1051        );
1052
1053        let adapter = MemoryAdapter::default();
1054        let mut e = Enforcer::new(m, adapter).await.unwrap();
1055        e.add_permission_for_user(
1056            "alice",
1057            vec!["data1", "invalid"]
1058                .iter()
1059                .map(|s| s.to_string())
1060                .collect(),
1061        )
1062        .await
1063        .unwrap();
1064        assert_eq!(false, e.enforce(("alice", "data1", "read")).unwrap());
1065    }
1066
1067    #[cfg(not(target_arch = "wasm32"))]
1068    #[cfg_attr(
1069        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1070        async_std::test
1071    )]
1072    #[cfg_attr(
1073        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1074        tokio::test
1075    )]
1076    async fn test_rbac_model_in_memory() {
1077        let mut m = DefaultModel::default();
1078        m.add_def("r", "r", "sub, obj, act");
1079        m.add_def("p", "p", "sub, obj, act");
1080        m.add_def("g", "g", "_, _");
1081        m.add_def("e", "e", "some(where (p.eft == allow))");
1082        m.add_def(
1083            "m",
1084            "m",
1085            "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act",
1086        );
1087
1088        let adapter = MemoryAdapter::default();
1089        let mut e = Enforcer::new(m, adapter).await.unwrap();
1090        e.add_permission_for_user(
1091            "alice",
1092            vec!["data1", "read"]
1093                .iter()
1094                .map(|s| s.to_string())
1095                .collect(),
1096        )
1097        .await
1098        .unwrap();
1099        e.add_permission_for_user(
1100            "bob",
1101            vec!["data2", "write"]
1102                .iter()
1103                .map(|s| s.to_string())
1104                .collect(),
1105        )
1106        .await
1107        .unwrap();
1108        e.add_permission_for_user(
1109            "data2_admin",
1110            vec!["data2", "read"]
1111                .iter()
1112                .map(|s| s.to_string())
1113                .collect(),
1114        )
1115        .await
1116        .unwrap();
1117        e.add_permission_for_user(
1118            "data2_admin",
1119            vec!["data2", "write"]
1120                .iter()
1121                .map(|s| s.to_string())
1122                .collect(),
1123        )
1124        .await
1125        .unwrap();
1126        e.add_role_for_user("alice", "data2_admin", None)
1127            .await
1128            .unwrap();
1129
1130        assert_eq!(true, e.enforce(("alice", "data1", "read")).unwrap());
1131        assert_eq!(false, e.enforce(("alice", "data1", "write")).unwrap());
1132        assert_eq!(true, e.enforce(("alice", "data2", "read")).unwrap());
1133        assert_eq!(true, e.enforce(("alice", "data2", "write")).unwrap());
1134        assert_eq!(false, e.enforce(("bob", "data1", "read")).unwrap());
1135        assert_eq!(false, e.enforce(("bob", "data1", "write")).unwrap());
1136        assert_eq!(false, e.enforce(("bob", "data2", "read")).unwrap());
1137        assert_eq!(true, e.enforce(("bob", "data2", "write")).unwrap());
1138    }
1139
1140    #[cfg(not(target_arch = "wasm32"))]
1141    #[cfg_attr(
1142        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1143        async_std::test
1144    )]
1145    #[cfg_attr(
1146        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1147        tokio::test
1148    )]
1149    async fn test_not_used_rbac_model_in_memory() {
1150        let mut m = DefaultModel::default();
1151        m.add_def("r", "r", "sub, obj, act");
1152        m.add_def("p", "p", "sub, obj, act");
1153        m.add_def("g", "g", "_, _");
1154        m.add_def("e", "e", "some(where (p.eft == allow))");
1155        m.add_def(
1156            "m",
1157            "m",
1158            "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act",
1159        );
1160
1161        let adapter = MemoryAdapter::default();
1162        let mut e = Enforcer::new(m, adapter).await.unwrap();
1163        e.add_permission_for_user(
1164            "alice",
1165            vec!["data1", "read"]
1166                .iter()
1167                .map(|s| s.to_string())
1168                .collect(),
1169        )
1170        .await
1171        .unwrap();
1172        e.add_permission_for_user(
1173            "bob",
1174            vec!["data2", "write"]
1175                .iter()
1176                .map(|s| s.to_string())
1177                .collect(),
1178        )
1179        .await
1180        .unwrap();
1181
1182        assert_eq!(true, e.enforce(("alice", "data1", "read")).unwrap());
1183        assert_eq!(false, e.enforce(("alice", "data1", "write")).unwrap());
1184        assert_eq!(false, e.enforce(("alice", "data2", "read")).unwrap());
1185        assert_eq!(false, e.enforce(("alice", "data2", "write")).unwrap());
1186        assert_eq!(false, e.enforce(("bob", "data1", "read")).unwrap());
1187        assert_eq!(false, e.enforce(("bob", "data1", "write")).unwrap());
1188        assert_eq!(false, e.enforce(("bob", "data2", "read")).unwrap());
1189        assert_eq!(true, e.enforce(("bob", "data2", "write")).unwrap());
1190    }
1191
1192    #[cfg(feature = "ip")]
1193    #[cfg(not(target_arch = "wasm32"))]
1194    #[cfg_attr(
1195        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1196        async_std::test
1197    )]
1198    #[cfg_attr(
1199        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1200        tokio::test
1201    )]
1202    async fn test_ip_match_model() {
1203        let m = DefaultModel::from_file("examples/ipmatch_model.conf")
1204            .await
1205            .unwrap();
1206
1207        let adapter = FileAdapter::new("examples/ipmatch_policy.csv");
1208        let e = Enforcer::new(m, adapter).await.unwrap();
1209
1210        assert!(e.enforce(("192.168.2.123", "data1", "read")).unwrap());
1211
1212        assert!(e.enforce(("10.0.0.5", "data2", "write")).unwrap());
1213
1214        assert!(!e.enforce(("192.168.2.123", "data1", "write")).unwrap());
1215        assert!(!e.enforce(("192.168.2.123", "data2", "read")).unwrap());
1216        assert!(!e.enforce(("192.168.2.123", "data2", "write")).unwrap());
1217
1218        assert!(!e.enforce(("192.168.0.123", "data1", "read")).unwrap());
1219        assert!(!e.enforce(("192.168.0.123", "data1", "write")).unwrap());
1220        assert!(!e.enforce(("192.168.0.123", "data2", "read")).unwrap());
1221        assert!(!e.enforce(("192.168.0.123", "data2", "write")).unwrap());
1222
1223        assert!(!e.enforce(("10.0.0.5", "data1", "read")).unwrap());
1224        assert!(!e.enforce(("10.0.0.5", "data1", "write")).unwrap());
1225        assert!(!e.enforce(("10.0.0.5", "data2", "read")).unwrap());
1226
1227        assert!(!e.enforce(("192.168.0.1", "data1", "read")).unwrap());
1228        assert!(!e.enforce(("192.168.0.1", "data1", "write")).unwrap());
1229        assert!(!e.enforce(("192.168.0.1", "data2", "read")).unwrap());
1230        assert!(!e.enforce(("192.168.0.1", "data2", "write")).unwrap());
1231    }
1232
1233    #[cfg(not(target_arch = "wasm32"))]
1234    #[cfg_attr(
1235        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1236        async_std::test
1237    )]
1238    #[cfg_attr(
1239        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1240        tokio::test
1241    )]
1242    async fn test_enable_auto_save() {
1243        let m = DefaultModel::from_file("examples/basic_model.conf")
1244            .await
1245            .unwrap();
1246
1247        let adapter = FileAdapter::new("examples/basic_policy.csv");
1248        let mut e = Enforcer::new(m, adapter).await.unwrap();
1249        e.enable_auto_save(false);
1250        e.remove_policy(
1251            vec!["alice", "data1", "read"]
1252                .iter()
1253                .map(|s| s.to_string())
1254                .collect(),
1255        )
1256        .await
1257        .unwrap();
1258        e.load_policy().await.unwrap();
1259
1260        assert_eq!(true, e.enforce(("alice", "data1", "read")).unwrap());
1261        assert_eq!(false, e.enforce(("alice", "data1", "write")).unwrap());
1262        assert_eq!(false, e.enforce(("alice", "data2", "read")).unwrap());
1263        assert_eq!(false, e.enforce(("alice", "data2", "write")).unwrap());
1264        assert_eq!(false, e.enforce(("bob", "data1", "read")).unwrap());
1265        assert_eq!(false, e.enforce(("bob", "data1", "write")).unwrap());
1266        assert_eq!(false, e.enforce(("bob", "data2", "read")).unwrap());
1267        assert_eq!(true, e.enforce(("bob", "data2", "write")).unwrap());
1268
1269        e.enable_auto_save(true);
1270        e.remove_policy(
1271            vec!["alice", "data1", "read"]
1272                .iter()
1273                .map(|s| s.to_string())
1274                .collect(),
1275        )
1276        .await
1277        .unwrap();
1278        e.load_policy().await.unwrap();
1279        assert_eq!(true, e.enforce(("alice", "data1", "read")).unwrap());
1280        assert_eq!(false, e.enforce(("alice", "data1", "write")).unwrap());
1281        assert_eq!(false, e.enforce(("alice", "data2", "read")).unwrap());
1282        assert_eq!(false, e.enforce(("alice", "data2", "write")).unwrap());
1283        assert_eq!(false, e.enforce(("bob", "data1", "read")).unwrap());
1284        assert_eq!(false, e.enforce(("bob", "data1", "write")).unwrap());
1285        assert_eq!(false, e.enforce(("bob", "data2", "read")).unwrap());
1286        assert_eq!(true, e.enforce(("bob", "data2", "write")).unwrap());
1287    }
1288
1289    #[cfg(not(target_arch = "wasm32"))]
1290    #[cfg_attr(
1291        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1292        async_std::test
1293    )]
1294    #[cfg_attr(
1295        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1296        tokio::test
1297    )]
1298    async fn test_role_links() {
1299        let m = DefaultModel::from_file("examples/rbac_model.conf")
1300            .await
1301            .unwrap();
1302
1303        let adapter = MemoryAdapter::default();
1304        let mut e = Enforcer::new(m, adapter).await.unwrap();
1305        e.enable_auto_build_role_links(false);
1306        e.build_role_links().unwrap();
1307        assert_eq!(false, e.enforce(("user501", "data9", "read")).unwrap());
1308    }
1309
1310    #[cfg(not(target_arch = "wasm32"))]
1311    #[cfg_attr(
1312        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1313        async_std::test
1314    )]
1315    #[cfg_attr(
1316        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1317        tokio::test
1318    )]
1319    async fn test_get_and_set_model() {
1320        let m1 = DefaultModel::from_file("examples/basic_model.conf")
1321            .await
1322            .unwrap();
1323        let adapter1 = FileAdapter::new("examples/basic_policy.csv");
1324        let mut e = Enforcer::new(m1, adapter1).await.unwrap();
1325
1326        assert_eq!(false, e.enforce(("root", "data1", "read")).unwrap());
1327
1328        let m2 = DefaultModel::from_file("examples/basic_with_root_model.conf")
1329            .await
1330            .unwrap();
1331        let adapter2 = FileAdapter::new("examples/basic_policy.csv");
1332        let e2 = Enforcer::new(m2, adapter2).await.unwrap();
1333
1334        e.model = e2.model;
1335        assert_eq!(true, e.enforce(("root", "data1", "read")).unwrap());
1336    }
1337
1338    #[cfg(not(target_arch = "wasm32"))]
1339    #[cfg_attr(
1340        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1341        async_std::test
1342    )]
1343    #[cfg_attr(
1344        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1345        tokio::test
1346    )]
1347    async fn test_get_and_set_adapter_in_mem() {
1348        let m1 = DefaultModel::from_file("examples/basic_model.conf")
1349            .await
1350            .unwrap();
1351        let adapter1 = FileAdapter::new("examples/basic_policy.csv");
1352        let mut e = Enforcer::new(m1, adapter1).await.unwrap();
1353
1354        assert_eq!(true, e.enforce(("alice", "data1", "read")).unwrap());
1355        assert_eq!(false, e.enforce(("alice", "data1", "write")).unwrap());
1356
1357        let m2 = DefaultModel::from_file("examples/basic_model.conf")
1358            .await
1359            .unwrap();
1360        let adapter2 = FileAdapter::new("examples/basic_inverse_policy.csv");
1361        let e2 = Enforcer::new(m2, adapter2).await.unwrap();
1362
1363        e.adapter = e2.adapter;
1364        e.load_policy().await.unwrap();
1365        assert_eq!(false, e.enforce(("alice", "data1", "read")).unwrap());
1366        assert_eq!(true, e.enforce(("alice", "data1", "write")).unwrap());
1367    }
1368
1369    #[cfg(not(target_arch = "wasm32"))]
1370    #[cfg_attr(
1371        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1372        async_std::test
1373    )]
1374    #[cfg_attr(
1375        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1376        tokio::test
1377    )]
1378    async fn test_keymatch_custom_model() {
1379        use crate::model::key_match;
1380
1381        let m1 = DefaultModel::from_file("examples/keymatch_custom_model.conf")
1382            .await
1383            .unwrap();
1384        let adapter1 = FileAdapter::new("examples/keymatch_policy.csv");
1385        let mut e = Enforcer::new(m1, adapter1).await.unwrap();
1386
1387        e.add_function(
1388            "keyMatchCustom",
1389            OperatorFunction::Arg2(
1390                |s1: ImmutableString, s2: ImmutableString| {
1391                    key_match(&s1, &s2).into()
1392                },
1393            ),
1394        );
1395
1396        assert_eq!(
1397            true,
1398            e.enforce(("alice", "/alice_data/123", "GET")).unwrap()
1399        );
1400        assert_eq!(
1401            true,
1402            e.enforce(("alice", "/alice_data/resource1", "POST"))
1403                .unwrap()
1404        );
1405
1406        assert_eq!(
1407            true,
1408            e.enforce(("bob", "/alice_data/resource2", "GET")).unwrap()
1409        );
1410
1411        assert_eq!(
1412            true,
1413            e.enforce(("bob", "/bob_data/resource1", "POST")).unwrap()
1414        );
1415
1416        assert_eq!(true, e.enforce(("cathy", "/cathy_data", "GET")).unwrap());
1417        assert_eq!(true, e.enforce(("cathy", "/cathy_data", "POST")).unwrap());
1418    }
1419
1420    #[cfg(not(target_arch = "wasm32"))]
1421    #[cfg_attr(
1422        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1423        async_std::test
1424    )]
1425    #[cfg_attr(
1426        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1427        tokio::test
1428    )]
1429    async fn test_filtered_file_adapter() {
1430        let adapter = FileAdapter::new_filtered_adapter(
1431            "examples/rbac_with_domains_policy.csv",
1432        );
1433        let mut e =
1434            Enforcer::new("examples/rbac_with_domains_model.conf", adapter)
1435                .await
1436                .unwrap();
1437
1438        let filter = Filter {
1439            p: vec!["", "domain1"],
1440            g: vec!["", "", "domain1"],
1441        };
1442
1443        e.load_filtered_policy(filter).await.unwrap();
1444        assert_eq!(
1445            e.enforce(("alice", "domain1", "data1", "read")).unwrap(),
1446            true
1447        );
1448        assert!(e.enforce(("alice", "domain1", "data1", "write")).unwrap());
1449        assert!(!e.enforce(("alice", "domain1", "data2", "read")).unwrap());
1450        assert!(!e.enforce(("alice", "domain1", "data2", "write")).unwrap());
1451        assert!(!e.enforce(("bob", "domain2", "data2", "read")).unwrap());
1452        assert!(!e.enforce(("bob", "domain2", "data2", "write")).unwrap());
1453    }
1454
1455    #[cfg(not(target_arch = "wasm32"))]
1456    #[cfg_attr(
1457        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1458        async_std::test
1459    )]
1460    #[cfg_attr(
1461        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1462        tokio::test
1463    )]
1464    async fn test_set_role_manager() {
1465        let mut e = Enforcer::new(
1466            "examples/rbac_with_domains_model.conf",
1467            "examples/rbac_with_domains_policy.csv",
1468        )
1469        .await
1470        .unwrap();
1471
1472        let new_rm = Arc::new(RwLock::new(DefaultRoleManager::new(10)));
1473
1474        e.set_role_manager(new_rm).unwrap();
1475
1476        assert!(e.enforce(("alice", "domain1", "data1", "read")).unwrap(),);
1477        assert!(e.enforce(("alice", "domain1", "data1", "write")).unwrap());
1478        assert!(e.enforce(("bob", "domain2", "data2", "read")).unwrap());
1479        assert!(e.enforce(("bob", "domain2", "data2", "write")).unwrap());
1480    }
1481
1482    #[cfg(not(target_arch = "wasm32"))]
1483    #[cfg_attr(
1484        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1485        async_std::test
1486    )]
1487    #[cfg_attr(
1488        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1489        tokio::test
1490    )]
1491    async fn test_policy_abac1() {
1492        use serde::Serialize;
1493
1494        let mut m = DefaultModel::default();
1495        m.add_def("r", "r", "sub, obj, act");
1496        m.add_def("p", "p", "sub_rule, obj, act");
1497        m.add_def("e", "e", "some(where (p.eft == allow))");
1498        m.add_def(
1499            "m",
1500            "m",
1501            "eval(p.sub_rule) && r.obj == p.obj && r.act == p.act",
1502        );
1503
1504        let a = MemoryAdapter::default();
1505
1506        let mut e = Enforcer::new(m, a).await.unwrap();
1507
1508        e.add_policy(
1509            vec!["r.sub.age > 18", "/data1", "read"]
1510                .into_iter()
1511                .map(|x| x.to_string())
1512                .collect(),
1513        )
1514        .await
1515        .unwrap();
1516
1517        #[derive(Serialize, Hash)]
1518        pub struct Person<'a> {
1519            name: &'a str,
1520            age: u8,
1521        }
1522
1523        assert_eq!(
1524            e.enforce((
1525                Person {
1526                    name: "alice",
1527                    age: 16
1528                },
1529                "/data1",
1530                "read"
1531            ))
1532            .unwrap(),
1533            false
1534        );
1535        assert_eq!(
1536            e.enforce((
1537                Person {
1538                    name: "bob",
1539                    age: 19
1540                },
1541                "/data1",
1542                "read"
1543            ))
1544            .unwrap(),
1545            true
1546        );
1547    }
1548
1549    #[cfg(not(target_arch = "wasm32"))]
1550    #[cfg_attr(
1551        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1552        async_std::test
1553    )]
1554    #[cfg_attr(
1555        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1556        tokio::test
1557    )]
1558    async fn test_policy_abac2() {
1559        use serde::Serialize;
1560
1561        let mut m = DefaultModel::default();
1562        m.add_def("r", "r", "sub, obj, act");
1563        m.add_def("p", "p", "sub, obj, act");
1564        m.add_def("e", "e", "some(where (p.eft == allow))");
1565        m.add_def("g", "g", "_, _");
1566        m.add_def(
1567            "m",
1568            "m",
1569            "(g(r.sub, p.sub) || eval(p.sub) == true) && r.act == p.act",
1570        );
1571
1572        let a = MemoryAdapter::default();
1573
1574        let mut e = Enforcer::new(m, a).await.unwrap();
1575
1576        e.add_policy(
1577            vec![r#""admin""#, "post", "write"]
1578                .into_iter()
1579                .map(|x| x.to_string())
1580                .collect(),
1581        )
1582        .await
1583        .unwrap();
1584
1585        e.add_policy(
1586            vec!["r.sub == r.obj.author", "post", "write"]
1587                .into_iter()
1588                .map(|x| x.to_string())
1589                .collect(),
1590        )
1591        .await
1592        .unwrap();
1593
1594        e.add_grouping_policy(
1595            vec!["alice", r#""admin""#]
1596                .into_iter()
1597                .map(|x| x.to_string())
1598                .collect(),
1599        )
1600        .await
1601        .unwrap();
1602
1603        #[derive(Serialize, Hash)]
1604        pub struct Post<'a> {
1605            author: &'a str,
1606        }
1607
1608        assert_eq!(
1609            e.enforce(("alice", Post { author: "bob" }, "write"))
1610                .unwrap(),
1611            true
1612        );
1613
1614        assert_eq!(
1615            e.enforce(("bob", Post { author: "bob" }, "write")).unwrap(),
1616            true
1617        );
1618    }
1619
1620    #[cfg(feature = "explain")]
1621    #[cfg(not(target_arch = "wasm32"))]
1622    #[cfg_attr(
1623        all(feature = "runtime-async-std", not(target_arch = "wasm32")),
1624        async_std::test
1625    )]
1626    #[cfg_attr(
1627        all(feature = "runtime-tokio", not(target_arch = "wasm32")),
1628        tokio::test
1629    )]
1630    async fn test_enforce_ex() {
1631        use crate::adapter;
1632
1633        let model = DefaultModel::from_file("examples/basic_model.conf")
1634            .await
1635            .unwrap();
1636
1637        let adapter = adapter::FileAdapter::new("examples/basic_policy.csv");
1638
1639        let e = Enforcer::new(model, adapter).await.unwrap();
1640
1641        assert_eq!(
1642            e.enforce_ex(("alice", "data1", "read")).unwrap(),
1643            (
1644                true,
1645                vec![vec![
1646                    "alice".to_string(),
1647                    "data1".to_string(),
1648                    "read".to_string()
1649                ]]
1650            )
1651        );
1652        assert_eq!(
1653            e.enforce_ex(("alice", "data1", "write")).unwrap(),
1654            (false, vec![])
1655        );
1656        assert_eq!(
1657            e.enforce_ex(("alice", "data2", "read")).unwrap(),
1658            (false, vec![])
1659        );
1660        assert_eq!(
1661            e.enforce_ex(("alice", "data2", "write")).unwrap(),
1662            (false, vec![])
1663        );
1664        assert_eq!(
1665            e.enforce_ex(("bob", "data1", "read")).unwrap(),
1666            (false, vec![])
1667        );
1668        assert_eq!(
1669            e.enforce_ex(("bob", "data1", "write")).unwrap(),
1670            (false, vec![])
1671        );
1672        assert_eq!(
1673            e.enforce_ex(("bob", "data2", "read")).unwrap(),
1674            (false, vec![])
1675        );
1676        assert_eq!(
1677            e.enforce_ex(("bob", "data2", "write")).unwrap(),
1678            (
1679                true,
1680                vec![vec![
1681                    "bob".to_string(),
1682                    "data2".to_string(),
1683                    "write".to_string()
1684                ]]
1685            )
1686        );
1687
1688        let e = Enforcer::new(
1689            "examples/rbac_model.conf",
1690            "examples/rbac_policy.csv",
1691        )
1692        .await
1693        .unwrap();
1694
1695        assert_eq!(
1696            e.enforce_ex(("alice", "data1", "read")).unwrap(),
1697            (
1698                true,
1699                vec![vec![
1700                    "alice".to_string(),
1701                    "data1".to_string(),
1702                    "read".to_string()
1703                ]]
1704            )
1705        );
1706        assert_eq!(
1707            e.enforce_ex(("alice", "data1", "write")).unwrap(),
1708            (false, vec![])
1709        );
1710        assert_eq!(
1711            e.enforce_ex(("alice", "data2", "read")).unwrap(),
1712            (
1713                true,
1714                vec![vec![
1715                    "data2_admin".to_string(),
1716                    "data2".to_string(),
1717                    "read".to_string()
1718                ]]
1719            )
1720        );
1721        assert_eq!(
1722            e.enforce_ex(("alice", "data2", "write")).unwrap(),
1723            (
1724                true,
1725                vec![vec![
1726                    "data2_admin".to_string(),
1727                    "data2".to_string(),
1728                    "write".to_string()
1729                ]]
1730            )
1731        );
1732        assert_eq!(
1733            e.enforce_ex(("bob", "data1", "read")).unwrap(),
1734            (false, vec![])
1735        );
1736        assert_eq!(
1737            e.enforce_ex(("bob", "data1", "write")).unwrap(),
1738            (false, vec![])
1739        );
1740        assert_eq!(
1741            e.enforce_ex(("bob", "data2", "read")).unwrap(),
1742            (false, vec![])
1743        );
1744        assert_eq!(
1745            e.enforce_ex(("bob", "data2", "write")).unwrap(),
1746            (
1747                true,
1748                vec![vec![
1749                    "bob".to_string(),
1750                    "data2".to_string(),
1751                    "write".to_string()
1752                ]]
1753            )
1754        );
1755
1756        let e = Enforcer::new(
1757            "examples/priority_model.conf",
1758            "examples/priority_policy.csv",
1759        )
1760        .await
1761        .unwrap();
1762
1763        assert_eq!(
1764            e.enforce_ex(("alice", "data1", "read")).unwrap(),
1765            (
1766                true,
1767                vec![vec![
1768                    "alice".to_string(),
1769                    "data1".to_string(),
1770                    "read".to_string(),
1771                    "allow".to_string()
1772                ]]
1773            )
1774        );
1775        assert_eq!(
1776            e.enforce_ex(("alice", "data1", "write")).unwrap(),
1777            (
1778                false,
1779                vec![vec![
1780                    "data1_deny_group".to_string(),
1781                    "data1".to_string(),
1782                    "write".to_string(),
1783                    "deny".to_string()
1784                ]]
1785            )
1786        );
1787        assert_eq!(
1788            e.enforce_ex(("alice", "data2", "read")).unwrap(),
1789            (false, vec![])
1790        );
1791        assert_eq!(
1792            e.enforce_ex(("alice", "data2", "write")).unwrap(),
1793            (false, vec![])
1794        );
1795        assert_eq!(
1796            e.enforce_ex(("bob", "data1", "write")).unwrap(),
1797            (false, vec![])
1798        );
1799        assert_eq!(
1800            e.enforce_ex(("bob", "data2", "read")).unwrap(),
1801            (
1802                true,
1803                vec![vec![
1804                    "data2_allow_group".to_string(),
1805                    "data2".to_string(),
1806                    "read".to_string(),
1807                    "allow".to_string()
1808                ]]
1809            )
1810        );
1811        assert_eq!(
1812            e.enforce_ex(("bob", "data2", "write")).unwrap(),
1813            (
1814                false,
1815                vec![vec![
1816                    "bob".to_string(),
1817                    "data2".to_string(),
1818                    "write".to_string(),
1819                    "deny".to_string()
1820                ]]
1821            )
1822        );
1823    }
1824}