Skip to main content

orion_accessor/addr/access_ctrl/
rule.rs

1use crate::prelude::*;
2use serde_derive::{Deserialize, Serialize};
3use wildmatch::WildMatch;
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Getters)]
6#[getset(get = "pub")]
7pub struct Rule {
8    #[serde(skip)]
9    matchs: WildMatch,
10    pattern: String,
11    target: String,
12}
13
14impl Rule {
15    pub fn new<S: AsRef<str>, S2: Into<String>>(matchs: S, target: S2) -> Self {
16        let pattern = matchs.as_ref().to_string();
17        Self {
18            matchs: WildMatch::new(&pattern),
19            pattern,
20            target: target.into(),
21        }
22    }
23    pub fn replace(&self, input: &str) -> Option<String> {
24        if self.matchs.matches(input) {
25            // 找到模式中的通配符位置
26            if let Some(star_idx) = self.pattern.find('*') {
27                let prefix = &self.pattern[..star_idx];
28                if let Some(suffix) = input.strip_prefix(prefix) {
29                    return Some(format!("{}{suffix}", self.target));
30                }
31            }
32            // 如果没有通配符或者精确匹配,直接替换整个字符串
33            None
34        } else {
35            None
36        }
37    }
38}
39impl EnvEvalable<Rule> for Rule {
40    fn env_eval(self, dict: &EnvDict) -> Rule {
41        Rule::new(self.pattern.env_eval(dict), self.target.env_eval(dict))
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn test_rule2() {
51        let rule = Rule::new(
52            "https://github.com/galaxy-sec/galaxy-flow*",
53            "https://gflow.com",
54        );
55        let url = rule.replace("https://github.com/galaxy-sec/galaxy-flow/releases/download/v0.8.5/galaxy-flow-v0.8.5-aarch64-apple-darwin.tar.gz");
56        assert_eq!(url, Some("https://gflow.com/releases/download/v0.8.5/galaxy-flow-v0.8.5-aarch64-apple-darwin.tar.gz".to_string()));
57    }
58
59    #[test]
60    fn test_rule_env_eval() {
61        let mut env_dict = EnvDict::new();
62        env_dict.insert(
63            "DOMAIN".to_string(),
64            ValueType::String("example.com".to_string()),
65        );
66        env_dict.insert(
67            "TARGET".to_string(),
68            ValueType::String("redirect.com".to_string()),
69        );
70
71        let rule = Rule::new("https://${DOMAIN}/*", "https://${TARGET}");
72        let evaluated = rule.env_eval(&env_dict);
73
74        assert_eq!(evaluated.pattern(), "https://example.com/*");
75        assert_eq!(evaluated.target(), "https://redirect.com");
76    }
77
78    #[test]
79    fn test_rule_env_eval_with_defaults() {
80        let env_dict = EnvDict::new();
81
82        let rule = Rule::new(
83            "https://${MISSING_DOMAIN:default.com}/*",
84            "https://${MISSING_TARGET:target.com}",
85        );
86        let evaluated = rule.env_eval(&env_dict);
87
88        assert_eq!(evaluated.pattern(), "https://default.com/*");
89        assert_eq!(evaluated.target(), "https://target.com");
90    }
91}