casbin/model/
assertion.rs1use crate::{
2 error::{ModelError, PolicyError},
3 rbac::{DefaultRoleManager, RoleManager},
4 Result,
5};
6
7#[cfg(feature = "incremental")]
8use crate::emitter::EventData;
9
10use hashlink::{LinkedHashMap, LinkedHashSet};
11use parking_lot::RwLock;
12
13use std::sync::Arc;
14
15pub type AssertionMap = LinkedHashMap<String, Assertion>;
16
17#[derive(Clone)]
18pub struct Assertion {
19 pub key: String,
20 pub value: String,
21 pub tokens: Vec<String>,
22 pub policy: LinkedHashSet<Vec<String>>,
23 pub rm: Arc<RwLock<dyn RoleManager>>,
24}
25
26impl Default for Assertion {
27 fn default() -> Self {
28 Assertion {
29 key: String::new(),
30 value: String::new(),
31 tokens: vec![],
32 policy: LinkedHashSet::new(),
33 rm: Arc::new(RwLock::new(DefaultRoleManager::new(0))),
34 }
35 }
36}
37
38impl Assertion {
39 #[inline]
40 pub fn get_policy(&self) -> &LinkedHashSet<Vec<String>> {
41 &self.policy
42 }
43
44 #[inline]
45 pub fn get_mut_policy(&mut self) -> &mut LinkedHashSet<Vec<String>> {
46 &mut self.policy
47 }
48
49 pub fn build_role_links(
50 &mut self,
51 rm: Arc<RwLock<dyn RoleManager>>,
52 ) -> Result<()> {
53 let count = self.value.matches('_').count();
54 if count < 2 {
55 return Err(ModelError::P(
56 r#"the number of "_" in role definition should be at least 2"#
57 .to_owned(),
58 )
59 .into());
60 }
61 for rule in &self.policy {
62 if rule.len() < count {
63 return Err(PolicyError::UnmatchPolicyDefinition(
64 count,
65 rule.len(),
66 )
67 .into());
68 }
69 if count == 2 {
70 rm.write().add_link(&rule[0], &rule[1], None);
71 } else if count == 3 {
72 rm.write().add_link(&rule[0], &rule[1], Some(&rule[2]));
73 } else if count >= 4 {
74 return Err(ModelError::P(
75 "Multiple domains are not supported".to_owned(),
76 )
77 .into());
78 }
79 }
80 self.rm = Arc::clone(&rm);
81 Ok(())
82 }
83
84 #[cfg(feature = "incremental")]
85 pub fn build_incremental_role_links(
86 &mut self,
87 rm: Arc<RwLock<dyn RoleManager>>,
88 d: EventData,
89 ) -> Result<()> {
90 let count = self.value.matches('_').count();
91 if count < 2 {
92 return Err(ModelError::P(
93 r#"the number of "_" in role definition should be at least 2"#
94 .to_owned(),
95 )
96 .into());
97 }
98
99 if let Some((insert, rules)) = match d {
100 EventData::AddPolicy(_, _, rule) => Some((true, vec![rule])),
101 EventData::AddPolicies(_, _, rules) => Some((true, rules)),
102 EventData::RemovePolicy(_, _, rule) => Some((false, vec![rule])),
103 EventData::RemovePolicies(_, _, rules) => Some((false, rules)),
104 EventData::RemoveFilteredPolicy(_, _, rules) => {
105 Some((false, rules))
106 }
107 _ => None,
108 } {
109 for rule in rules {
110 if rule.len() < count {
111 return Err(PolicyError::UnmatchPolicyDefinition(
112 count,
113 rule.len(),
114 )
115 .into());
116 }
117 if count == 2 {
118 if insert {
119 rm.write().add_link(&rule[0], &rule[1], None);
120 } else {
121 rm.write().delete_link(&rule[0], &rule[1], None)?;
122 }
123 } else if count == 3 {
124 if insert {
125 rm.write().add_link(&rule[0], &rule[1], Some(&rule[2]));
126 } else {
127 rm.write().delete_link(
128 &rule[0],
129 &rule[1],
130 Some(&rule[2]),
131 )?;
132 }
133 } else if count >= 4 {
134 return Err(ModelError::P(
135 "Multiple domains are not supported".to_owned(),
136 )
137 .into());
138 }
139 }
140
141 self.rm = Arc::clone(&rm);
142 }
143
144 Ok(())
145 }
146}