Skip to main content

decide_core/
evaluator.rs

1use crate::types::{DecideError, Resource, RoleMap, User};
2use crate::utils::{evaluate_condition};
3use std::fs::{self};
4
5// Core class
6pub struct Decide {
7    roles: RoleMap,
8}
9
10impl Decide {
11    // General constructor
12    pub fn new (roles: RoleMap) -> Self {
13        Self {
14            roles,
15        }
16    }
17
18    // Create from a custom JSON config file
19    pub fn from_file (path: &str) -> Result<Self, Box<dyn std::error::Error>> {
20        let content = fs::read_to_string(path)?;
21        let roles: RoleMap = serde_json::from_str(&content)?;
22        Ok(Self::new(roles))
23    }
24
25    // Create from default JSON config file
26    pub fn default () -> Result<Self, Box<dyn std::error::Error>> {
27        Self::from_file("decide.config.json")
28    }
29
30    pub fn can (&self, user: &User, action: &str, resource: &Resource) -> Result<bool, DecideError> {
31        for role_name in &user.roles {
32            if let Some(role) = self.roles.get(role_name) {
33                for pmsn in &role.permissions {
34                    if pmsn.action != action {
35                        continue;
36                    }
37
38                    match &pmsn.condition {
39                        Some(expr) => {
40                            let passed = evaluate_condition(expr, user, resource);
41                            if passed {
42                                return Ok(true);
43                            }
44                        }
45                        None => {
46                            return Ok(true);
47                        }
48                    }
49                }
50            } else {
51                return Err(DecideError::MissingRole(role_name.clone()));
52            }
53        }
54
55        Ok(false)
56    }
57}
58