1mod lexer;
5mod parser;
6#[cfg(feature = "caching")]
7pub mod caching;
8pub mod authorization_expression;
9mod authorizations;
10
11pub use crate::lexer::Lexer;
12pub use crate::parser::Parser;
13pub use crate::parser::ParserError;
14pub use crate::authorizations::Authorizations;
15pub use crate::authorization_expression::AuthorizationExpression;
16
17pub enum JsonError {
18 ParsingFailed(String),
19}
20
21impl std::fmt::Display for JsonError {
23 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
24 match self {
25 JsonError::ParsingFailed(e) => write!(f, "{}", e),
26 }
27 }
28}
29
30pub struct AccessEvaluator {}
31
32pub fn check_authorization(expression: &str, tokens: &[String]) -> Result<bool, ParserError> {
62 let lexer: Lexer<'_> = Lexer::new(expression);
63 let mut parser = Parser::new(lexer);
64
65 let auth_expr = parser.parse()?;
66 let authorized_labels = tokens.iter().cloned().collect();
67 let result = auth_expr.evaluate(&authorized_labels);
68 Ok(result)
69}
70
71pub fn prepare_authorization_csv(tokens: String) -> impl Fn(String) -> Result<bool, ParserError> {
73 let tokens: Vec<String> = tokens.split(',').map(|s| s.to_string()).collect();
74 move |expression| check_authorization(expression.as_str(), &tokens)
75}
76
77pub fn check_authorization_csv(
79 expression: String,
80 tokens: String,
81) -> Result<bool, ParserError> {
82 prepare_authorization_csv(tokens)(expression)
83}
84
85pub fn expression_to_json_string(expression: &str) -> Result<String, ParserError> {
86 let lexer: Lexer<'_> = Lexer::new(expression);
87 let mut parser = Parser::new(lexer);
88
89 let auth_expr = parser.parse();
90
91 match auth_expr {
92 Ok(auth_expr) => {
93 Ok(auth_expr.to_json_str())
94 }
95 Err(e) => Err(e),
96 }
97}
98
99pub fn expression_to_json(expression: &str) -> Result<serde_json::Value, JsonError> {
100 let lexer: Lexer<'_> = Lexer::new(expression);
101 let mut parser = Parser::new(lexer);
102 let expr = parser.parse();
103 match expr {
104 Ok(expr) => Ok(expr.to_json()),
105 Err(e) => Err(JsonError::ParsingFailed(format!("{:?}", e))),
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112 use rstest::rstest;
113
114 #[rstest]
115 #[case("", "", true)]
116 #[case("label1", "label1", true)]
117 #[case("label1|label2", "label1", true)]
118 #[case("label1&label2", "label1", false)]
119 #[case("label1&label2", "label1,label2", true)]
120 #[case("label1&(label2|label3)", "label1", false)]
121 #[case("label1&(label2|label3)", "label1,label3", true)]
122 #[case("label1&(label2|label3)", "label1,label2", true)]
123 #[case("(label2|label3)", "label1", false)]
124 #[case("(label2|label3)", "label2", true)]
125 #[case("(label2&label3)", "label2", false)]
126 #[case("((label2|label3))", "label2", true)]
127 #[case("((label2&label3))", "label2", false)]
128 #[case("(((((label2&label3)))))", "label2", false)]
129 #[case("\"a b c\"", "\"a b c\"", true)]
130 #[case("\"abc!12\"&\"abc\\\\xyz\"&GHI", "abc\\xyz,abc!12", false)] fn test_check_authorization(
132 #[case] expr: impl AsRef<str>,
133 #[case] authorized_tokens: impl AsRef<str>,
134 #[case] expected: bool,
135 ) {
136 let authorized_tokens: Vec<String> = AsRef::as_ref(&authorized_tokens).split(',')
137 .map(|s| s.to_string().replace(['"','\''], ""))
138 .collect();
139
140 let result = check_authorization(expr.as_ref(), &authorized_tokens).unwrap();
141 assert_eq!(result, expected);
142 }
143
144 #[test]
145 fn normalization_test() {
146 let expression = "A&B&A&(D|E)&(E|D)"; let lexer: Lexer<'_> = Lexer::new(expression);
148 let mut parser = Parser::new(lexer);
149
150 let mut auth_expr = parser.parse().unwrap();
151 auth_expr.normalize();
152 let expected = AuthorizationExpression::ConjunctionOf(
153 vec![
154 AuthorizationExpression::AccessToken("A".to_string()),
155 AuthorizationExpression::AccessToken("B".to_string()),
156 AuthorizationExpression::DisjunctionOf(vec![
157 AuthorizationExpression::AccessToken("D".to_string()),
158 AuthorizationExpression::AccessToken("E".to_string())
159 ])
160 ],
161 );
162 assert_eq!(expected, auth_expr)
163 }
164}