Skip to main content

crue_engine/
decision.rs

1//! Decision Types
2
3use serde::{Deserialize, Serialize};
4
5/// Access decision
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "UPPERCASE")]
8pub enum Decision {
9    /// Allow access
10    Allow,
11    /// Block access
12    Block,
13    /// Allow with warning
14    Warn,
15    /// Require approval
16    ApprovalRequired,
17}
18
19impl Default for Decision {
20    fn default() -> Self {
21        Decision::Allow
22    }
23}
24
25impl std::fmt::Display for Decision {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        match self {
28            Decision::Allow => write!(f, "ALLOW"),
29            Decision::Block => write!(f, "BLOCK"),
30            Decision::Warn => write!(f, "WARN"),
31            Decision::ApprovalRequired => write!(f, "APPROVAL_REQUIRED"),
32        }
33    }
34}
35
36/// Action result from rule
37#[derive(Debug, Clone)]
38pub struct ActionResult {
39    pub decision: Decision,
40    pub error_code: Option<String>,
41    pub message: Option<String>,
42    pub alert_soc: bool,
43}
44
45impl ActionResult {
46    /// Create block result
47    pub fn block(code: &str, message: &str) -> Self {
48        ActionResult {
49            decision: Decision::Block,
50            error_code: Some(code.to_string()),
51            message: Some(message.to_string()),
52            alert_soc: false,
53        }
54    }
55    
56    /// Create warning result
57    pub fn warn(code: &str, message: &str) -> Self {
58        ActionResult {
59            decision: Decision::Warn,
60            error_code: Some(code.to_string()),
61            message: Some(message.to_string()),
62            alert_soc: false,
63        }
64    }
65    
66    /// Create approval required result
67    pub fn approval_required(code: &str, timeout_minutes: u32) -> Self {
68        ActionResult {
69            decision: Decision::ApprovalRequired,
70            error_code: Some(code.to_string()),
71            message: Some(format!("Approval required within {} minutes", timeout_minutes)),
72            alert_soc: false,
73        }
74    }
75    
76    /// Create allow result
77    pub fn allow() -> Self {
78        ActionResult {
79            decision: Decision::Allow,
80            error_code: None,
81            message: None,
82            alert_soc: false,
83        }
84    }
85    
86    /// Add SOC alert
87    pub fn with_soc_alert(mut self) -> Self {
88        self.alert_soc = true;
89        self
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    
97    #[test]
98    fn test_decision_display() {
99        assert_eq!(format!("{}", Decision::Allow), "ALLOW");
100        assert_eq!(format!("{}", Decision::Block), "BLOCK");
101    }
102    
103    #[test]
104    fn test_action_result() {
105        let result = ActionResult::block("VOLUME_EXCEEDED", "Quota dépassé");
106        assert_eq!(result.decision, Decision::Block);
107        assert_eq!(result.error_code, Some("VOLUME_EXCEEDED".to_string()));
108    }
109}