use rocketmq_security_api::Action;
use super::environment::Environment;
use super::policy_entry::PolicyEntry;
use super::resource::Resource;
use crate::authorization::enums::decision::Decision;
use crate::authorization::enums::policy_type::PolicyType;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Policy {
policy_type: PolicyType,
entries: Vec<PolicyEntry>,
}
impl Policy {
pub fn of(
resources: Vec<Resource>,
actions: Vec<Action>,
environment: Option<Environment>,
decision: Decision,
) -> Self {
Self::of_type(PolicyType::Custom, resources, actions, environment, decision)
}
pub fn of_type(
policy_type: PolicyType,
resources: Vec<Resource>,
actions: Vec<Action>,
environment: Option<Environment>,
decision: Decision,
) -> Self {
let entries = resources
.into_iter()
.map(|r| PolicyEntry::of(r, actions.clone(), environment.clone(), decision))
.collect();
Policy { policy_type, entries }
}
pub fn of_entries(policy_type: PolicyType, entries: Vec<PolicyEntry>) -> Self {
Policy { policy_type, entries }
}
pub fn update_entry(&mut self, new_entries: Vec<PolicyEntry>) {
if self.entries.is_empty() {
self.entries = Vec::new();
}
for new_entry in new_entries {
match self.get_entry_mut(new_entry.resource()) {
None => self.entries.push(new_entry),
Some(entry) => entry.update_entry(
new_entry.actions().clone(),
new_entry.environment().cloned(),
new_entry.decision(),
),
}
}
}
pub fn delete_entry(&mut self, resource: &Resource) {
if let Some(pos) = self.entries.iter().position(|e| e.resource() == resource) {
self.entries.remove(pos);
}
}
fn get_entry_mut(&mut self, resource: &Resource) -> Option<&mut PolicyEntry> {
self.entries.iter_mut().find(|e| e.resource() == resource)
}
pub fn policy_type(&self) -> PolicyType {
self.policy_type
}
pub fn set_policy_type(&mut self, t: PolicyType) {
self.policy_type = t;
}
pub fn entries(&self) -> &Vec<PolicyEntry> {
&self.entries
}
pub fn set_entries(&mut self, e: Vec<PolicyEntry>) {
self.entries = e;
}
}
#[cfg(test)]
mod tests {
use rocketmq_security_api::Action;
use rocketmq_security_api::ResourcePattern;
use rocketmq_security_api::ResourceType;
use super::*;
use crate::authorization::enums::policy_type::PolicyType;
#[test]
fn test_of_and_update_delete() {
let r1 = Resource::of(ResourceType::Topic, Some("t1".to_string()), ResourcePattern::Literal);
let r2 = Resource::of(ResourceType::Topic, Some("t2".to_string()), ResourcePattern::Literal);
let mut p = Policy::of(vec![r1.clone()], vec![Action::Pub], None, Decision::Allow);
assert_eq!(p.entries().len(), 1);
p.update_entry(vec![PolicyEntry::of(
r2.clone(),
vec![Action::Pub],
None,
Decision::Allow,
)]);
assert_eq!(p.entries().len(), 2);
p.delete_entry(&r1);
assert_eq!(p.entries().len(), 1);
assert!(p.entries().iter().all(|e| e.resource() != &r1));
p.set_entries(vec![PolicyEntry::of(
r1.clone(),
vec![Action::Sub],
None,
Decision::Deny,
)]);
assert_eq!(p.entries().len(), 1);
assert_eq!(p.policy_type(), PolicyType::Custom);
}
}