rocketmq_auth/authorization/model/
acl.rs1use std::fmt;
16
17use super::policy::Policy;
18use super::resource::Resource;
19use crate::authentication::enums::subject_type::SubjectType;
20use crate::authentication::model::subject::Subject;
21use crate::authorization::enums::policy_type::PolicyType;
22
23#[derive(Clone, Debug, PartialEq, Eq)]
24pub struct Acl {
25 subject_key: String,
26 subject_type: SubjectType,
27 policies: Vec<Policy>,
28}
29
30impl Acl {
31 pub fn of_subject_and_policy<S: Subject>(subject: &S, policy: Policy) -> Self {
33 Self::of_subject_and_policies(subject, vec![policy])
34 }
35
36 pub fn of_subject_and_policies<S: Subject>(subject: &S, policies: Vec<Policy>) -> Self {
38 Acl {
39 subject_key: subject.subject_key().to_string(),
40 subject_type: subject.subject_type(),
41 policies,
42 }
43 }
44
45 pub fn of(subject_key: impl Into<String>, subject_type: SubjectType, policy: Policy) -> Self {
47 Self::of_with_policies(subject_key, subject_type, vec![policy])
48 }
49
50 pub fn of_with_policies(subject_key: impl Into<String>, subject_type: SubjectType, policies: Vec<Policy>) -> Self {
52 Acl {
53 subject_key: normalize_subject_key(subject_key.into(), subject_type),
54 subject_type,
55 policies,
56 }
57 }
58
59 pub fn update_policy(&mut self, policy: Policy) {
61 self.update_policies(vec![policy])
62 }
63
64 pub fn update_policies(&mut self, policies: Vec<Policy>) {
65 if self.policies.is_empty() {
66 self.policies = Vec::new();
67 }
68 for new_policy in policies {
69 match self.get_policy_mut(new_policy.policy_type()) {
70 None => self.policies.push(new_policy),
71 Some(old_policy) => old_policy.update_entry(new_policy.entries().clone()),
72 }
73 }
74 }
75
76 pub fn delete_policy(&mut self, policy_type: PolicyType, resource: &Resource) {
78 if let Some(policy) = self.get_policy_mut(policy_type) {
79 policy.delete_entry(resource);
80 if policy.entries().is_empty() {
81 if let Some(pos) = self.policies.iter().position(|p| p.policy_type() == policy_type) {
83 self.policies.remove(pos);
84 }
85 }
86 }
87 }
88
89 pub fn get_policy(&self, policy_type: PolicyType) -> Option<&Policy> {
90 self.policies.iter().find(|p| p.policy_type() == policy_type)
91 }
92
93 fn get_policy_mut(&mut self, policy_type: PolicyType) -> Option<&mut Policy> {
94 self.policies.iter_mut().find(|p| p.policy_type() == policy_type)
95 }
96
97 pub fn subject_key(&self) -> &str {
99 &self.subject_key
100 }
101
102 pub fn subject_type(&self) -> SubjectType {
103 self.subject_type
104 }
105
106 pub fn policies(&self) -> &Vec<Policy> {
107 &self.policies
108 }
109
110 pub fn set_policies(&mut self, p: Vec<Policy>) {
111 self.policies = p;
112 }
113
114 pub fn set_subject_key(&mut self, k: impl Into<String>) {
115 self.subject_key = k.into();
116 }
117
118 pub fn set_subject_type(&mut self, t: SubjectType) {
119 self.subject_type = t;
120 }
121}
122
123fn normalize_subject_key(subject_key: String, subject_type: SubjectType) -> String {
124 if let Some((_, raw_name)) = subject_key.split_once(':') {
125 return format!("{}:{}", subject_type.name(), raw_name);
126 }
127 format!("{}:{}", subject_type.name(), subject_key)
128}
129
130impl fmt::Display for Acl {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 write!(
133 f,
134 "Acl{{subject_key={}, subject_type={}, policies_len={}}}",
135 self.subject_key,
136 self.subject_type.name(),
137 self.policies.len()
138 )
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use rocketmq_security_api::Action;
145 use rocketmq_security_api::ResourcePattern;
146 use rocketmq_security_api::ResourceType;
147
148 use super::*;
149 use crate::authentication::model::user::User;
150 use crate::authorization::enums::decision::Decision;
151 use crate::authorization::model::policy::Policy;
152
153 #[test]
154 fn test_of_and_update_delete() {
155 let user = User::of("alice");
156 let r1 = Resource::of(ResourceType::Topic, Some("t1".to_string()), ResourcePattern::Literal);
157 let r2 = Resource::of(ResourceType::Topic, Some("t2".to_string()), ResourcePattern::Literal);
158 let mut acl = Acl::of_subject_and_policies(
159 &user,
160 vec![Policy::of(vec![r1.clone()], vec![Action::Pub], None, Decision::Allow)],
161 );
162 assert_eq!(acl.policies().len(), 1);
163
164 acl.update_policy(Policy::of(vec![r2.clone()], vec![Action::Pub], None, Decision::Allow));
166 assert_eq!(acl.policies().len(), 1);
167 assert_eq!(acl.policies().first().unwrap().entries().len(), 2);
168
169 acl.delete_policy(PolicyType::Custom, &r1);
171 assert_eq!(acl.policies().len(), 1);
172 assert_eq!(acl.policies().first().unwrap().entries().len(), 1);
173 }
174}