use std::collections::HashMap;
use glob::Pattern;
use crate::model::{OdrlDocument, RuleAction};
pub(super) type RuleKey = (String, String);
pub(super) type RuleIndex = HashMap<RuleKey, Vec<RuleRef>>;
pub(super) type WildcardActionIndex = HashMap<String, Vec<RuleRef>>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) struct RuleRef {
pub(super) policy_index: usize,
pub(super) rule_index: usize,
pub(super) ordinal: usize,
}
pub(super) fn target_matches(target: &str, resource: &str) -> bool {
if target == resource {
return true;
}
let stripped = target.strip_prefix("asset:").unwrap_or(target);
if stripped == resource {
return true;
}
Pattern::new(stripped).is_ok_and(|p| p.matches(resource))
}
pub(super) fn build_rule_index(doc: &OdrlDocument) -> (RuleIndex, WildcardActionIndex) {
let mut exact_rules: RuleIndex = HashMap::new();
let mut wildcard_action_rules: WildcardActionIndex = HashMap::new();
let mut ordinal = 0;
for (policy_index, policy) in doc.policies.iter().enumerate() {
for (rule_index, rule) in policy.rules.iter().enumerate() {
let rule_ref = RuleRef {
policy_index,
rule_index,
ordinal,
};
ordinal += 1;
if matches!(rule.action, RuleAction::Use) {
wildcard_action_rules
.entry(rule.assignee.clone())
.or_default()
.push(rule_ref);
} else {
exact_rules
.entry((
rule.assignee.clone(),
rule.action.as_permission_name().to_owned(),
))
.or_default()
.push(rule_ref);
}
}
}
(exact_rules, wildcard_action_rules)
}