rocketmq_auth/authorization/model/
policy_entry.rs1use rocketmq_security_api::Action;
16
17use super::environment::Environment;
18use super::resource::Resource;
19use crate::authorization::enums::decision::Decision;
20
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct PolicyEntry {
23 resource: Resource,
24 actions: Vec<Action>,
25 environment: Option<Environment>,
26 decision: Decision,
27}
28
29impl PolicyEntry {
30 pub fn of(resource: Resource, actions: Vec<Action>, environment: Option<Environment>, decision: Decision) -> Self {
31 Self {
32 resource,
33 actions,
34 environment,
35 decision,
36 }
37 }
38
39 pub fn update_entry(&mut self, actions: Vec<Action>, environment: Option<Environment>, decision: Decision) {
40 self.actions = actions;
41 self.environment = environment;
42 self.decision = decision;
43 }
44
45 pub fn is_match_resource(&self, resource: &Resource) -> bool {
46 self.resource.is_match(resource)
47 }
48
49 pub fn is_match_action(&self, actions: &[Action]) -> bool {
52 if self.actions.is_empty() {
53 return false;
54 }
55 if actions.contains(&Action::Any) {
56 return true;
57 }
58 let contains_all = self.actions.contains(&Action::All);
60 actions
61 .iter()
62 .any(|a| self.actions.iter().any(|sa| sa == a) || contains_all)
63 }
64
65 pub fn is_match_environment(&self, environment: &Environment) -> bool {
66 match &self.environment {
67 None => true,
68 Some(env) => env.is_match(environment),
69 }
70 }
71
72 pub fn to_resource_str(&self) -> Option<String> {
73 self.resource.resource_key()
74 }
75
76 pub fn to_actions_str(&self) -> Option<Vec<String>> {
77 if self.actions.is_empty() {
78 return None;
79 }
80 Some(
81 self.actions
82 .iter()
83 .map(|a| a.name().to_string())
84 .collect::<Vec<String>>(),
85 )
86 }
87
88 pub fn resource(&self) -> &Resource {
90 &self.resource
91 }
92
93 pub fn set_resource(&mut self, r: Resource) {
94 self.resource = r;
95 }
96
97 pub fn actions(&self) -> &Vec<Action> {
98 &self.actions
99 }
100
101 pub fn set_actions(&mut self, a: Vec<Action>) {
102 self.actions = a;
103 }
104
105 pub fn environment(&self) -> Option<&Environment> {
106 self.environment.as_ref()
107 }
108
109 pub fn set_environment(&mut self, e: Option<Environment>) {
110 self.environment = e;
111 }
112
113 pub fn decision(&self) -> Decision {
114 self.decision
115 }
116
117 pub fn set_decision(&mut self, d: Decision) {
118 self.decision = d;
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use rocketmq_security_api::Action;
125 use rocketmq_security_api::ResourceType;
126
127 use super::*;
128 use crate::authorization::enums::decision::Decision;
129 use crate::authorization::model::resource::Resource;
130
131 #[test]
132 fn test_of_and_to_strings() {
133 let r = Resource::of(
134 ResourceType::Topic,
135 Some("foo".to_string()),
136 rocketmq_security_api::ResourcePattern::Literal,
137 );
138 let p = PolicyEntry::of(r.clone(), vec![Action::Pub, Action::Sub], None, Decision::Allow);
139 assert_eq!(p.to_resource_str(), Some("Topic:foo".to_string()));
140 assert_eq!(p.to_actions_str().unwrap(), vec!["Pub".to_string(), "Sub".to_string()]);
141 assert_eq!(p.decision(), Decision::Allow);
142 }
143
144 #[test]
145 fn test_is_match_action_any_and_all() {
146 let r = Resource::of(
147 ResourceType::Topic,
148 Some("x".to_string()),
149 rocketmq_security_api::ResourcePattern::Literal,
150 );
151 let p = PolicyEntry::of(r, vec![Action::Pub, Action::Sub], None, Decision::Allow);
152 assert!(p.is_match_action(&[Action::Pub]));
153 assert!(!p.is_match_action(&[Action::Create]));
154
155 assert!(p.is_match_action(&[Action::Any]));
157
158 let r2 = Resource::of(
160 ResourceType::Topic,
161 Some("x".to_string()),
162 rocketmq_security_api::ResourcePattern::Literal,
163 );
164 let p2 = PolicyEntry::of(r2, vec![Action::All], None, Decision::Allow);
165 assert!(p2.is_match_action(&[Action::Create]));
166 }
167
168 #[test]
169 fn test_is_match_resource_and_environment() {
170 let rule = PolicyEntry::of(
171 Resource::of(
172 ResourceType::Topic,
173 Some("pre".to_string()),
174 rocketmq_security_api::ResourcePattern::Prefixed,
175 ),
176 vec![Action::Pub],
177 Some(crate::authorization::model::environment::Environment::of("1.2.3.4").unwrap()),
178 Decision::Allow,
179 );
180
181 let res = Resource::of(
182 ResourceType::Topic,
183 Some("prefix_val".to_string()),
184 rocketmq_security_api::ResourcePattern::Literal,
185 );
186 assert!(rule.is_match_resource(&res));
187 assert!(
188 rule.is_match_environment(&crate::authorization::model::environment::Environment::of("1.2.3.4").unwrap())
189 );
190 assert!(
191 !rule.is_match_environment(&crate::authorization::model::environment::Environment::of("8.8.8.8").unwrap())
192 );
193 }
194}