rocketmq_auth/authorization/model/
policy.rs1use rocketmq_security_api::Action;
16
17use super::environment::Environment;
18use super::policy_entry::PolicyEntry;
19use super::resource::Resource;
20use crate::authorization::enums::decision::Decision;
21use crate::authorization::enums::policy_type::PolicyType;
22
23#[derive(Clone, Debug, PartialEq, Eq)]
24pub struct Policy {
25 policy_type: PolicyType,
26 entries: Vec<PolicyEntry>,
27}
28
29impl Policy {
30 pub fn of(
31 resources: Vec<Resource>,
32 actions: Vec<Action>,
33 environment: Option<Environment>,
34 decision: Decision,
35 ) -> Self {
36 Self::of_type(PolicyType::Custom, resources, actions, environment, decision)
37 }
38
39 pub fn of_type(
40 policy_type: PolicyType,
41 resources: Vec<Resource>,
42 actions: Vec<Action>,
43 environment: Option<Environment>,
44 decision: Decision,
45 ) -> Self {
46 let entries = resources
47 .into_iter()
48 .map(|r| PolicyEntry::of(r, actions.clone(), environment.clone(), decision))
49 .collect();
50 Policy { policy_type, entries }
51 }
52
53 pub fn of_entries(policy_type: PolicyType, entries: Vec<PolicyEntry>) -> Self {
54 Policy { policy_type, entries }
55 }
56
57 pub fn update_entry(&mut self, new_entries: Vec<PolicyEntry>) {
58 if self.entries.is_empty() {
59 self.entries = Vec::new();
60 }
61 for new_entry in new_entries {
62 match self.get_entry_mut(new_entry.resource()) {
63 None => self.entries.push(new_entry),
64 Some(entry) => entry.update_entry(
65 new_entry.actions().clone(),
66 new_entry.environment().cloned(),
67 new_entry.decision(),
68 ),
69 }
70 }
71 }
72
73 pub fn delete_entry(&mut self, resource: &Resource) {
74 if let Some(pos) = self.entries.iter().position(|e| e.resource() == resource) {
75 self.entries.remove(pos);
76 }
77 }
78
79 fn get_entry_mut(&mut self, resource: &Resource) -> Option<&mut PolicyEntry> {
80 self.entries.iter_mut().find(|e| e.resource() == resource)
81 }
82
83 pub fn policy_type(&self) -> PolicyType {
85 self.policy_type
86 }
87
88 pub fn set_policy_type(&mut self, t: PolicyType) {
89 self.policy_type = t;
90 }
91
92 pub fn entries(&self) -> &Vec<PolicyEntry> {
93 &self.entries
94 }
95
96 pub fn set_entries(&mut self, e: Vec<PolicyEntry>) {
97 self.entries = e;
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use rocketmq_security_api::Action;
104 use rocketmq_security_api::ResourcePattern;
105 use rocketmq_security_api::ResourceType;
106
107 use super::*;
108 use crate::authorization::enums::policy_type::PolicyType;
109
110 #[test]
111 fn test_of_and_update_delete() {
112 let r1 = Resource::of(ResourceType::Topic, Some("t1".to_string()), ResourcePattern::Literal);
113 let r2 = Resource::of(ResourceType::Topic, Some("t2".to_string()), ResourcePattern::Literal);
114 let mut p = Policy::of(vec![r1.clone()], vec![Action::Pub], None, Decision::Allow);
115 assert_eq!(p.entries().len(), 1);
116
117 p.update_entry(vec![PolicyEntry::of(
119 r2.clone(),
120 vec![Action::Pub],
121 None,
122 Decision::Allow,
123 )]);
124 assert_eq!(p.entries().len(), 2);
125
126 p.delete_entry(&r1);
128 assert_eq!(p.entries().len(), 1);
129 assert!(p.entries().iter().all(|e| e.resource() != &r1));
130
131 p.set_entries(vec![PolicyEntry::of(
133 r1.clone(),
134 vec![Action::Sub],
135 None,
136 Decision::Deny,
137 )]);
138 assert_eq!(p.entries().len(), 1);
139 assert_eq!(p.policy_type(), PolicyType::Custom);
140 }
141}