aaai_core/audit/
engine.rs1use crate::config::definition::AuditDefinition;
4use crate::diff::entry::DiffEntry;
5use super::result::{AuditResult, AuditStatus, FileAuditResult};
6use super::strategy;
7
8pub struct AuditEngine;
9
10impl AuditEngine {
11 pub fn evaluate(diffs: &[DiffEntry], definition: &AuditDefinition) -> AuditResult {
13 let mut results = Vec::new();
14
15 for diff in diffs {
16 let result = judge(diff, definition);
17 results.push(result);
18 }
19
20 AuditResult::new(results)
21 }
22}
23
24fn judge(diff: &DiffEntry, definition: &AuditDefinition) -> FileAuditResult {
25 if diff.diff_type.is_error() {
27 return FileAuditResult {
28 diff: diff.clone(),
29 entry: None,
30 status: AuditStatus::Error,
31 detail: diff.error_detail.clone().or_else(|| {
32 Some("File could not be read or compared.".into())
33 }),
34 };
35 }
36
37 let entry = match definition.find_entry(&diff.path) {
39 Some(e) => e,
40 None => {
41 return FileAuditResult {
42 diff: diff.clone(),
43 entry: None,
44 status: AuditStatus::Pending,
45 detail: Some("No audit rule defined for this path.".into()),
46 };
47 }
48 };
49
50 if !entry.enabled {
52 return FileAuditResult {
53 diff: diff.clone(),
54 entry: Some(entry.clone()),
55 status: AuditStatus::Ignored,
56 detail: Some("Entry is disabled.".into()),
57 };
58 }
59
60 if entry.diff_type != diff.diff_type {
62 return FileAuditResult {
63 diff: diff.clone(),
64 entry: Some(entry.clone()),
65 status: AuditStatus::Failed,
66 detail: Some(format!(
67 "Expected diff type {:?} but found {:?}.",
68 entry.diff_type, diff.diff_type
69 )),
70 };
71 }
72
73 match strategy::evaluate(&entry.strategy, diff) {
75 Ok(()) => FileAuditResult {
76 diff: diff.clone(),
77 entry: Some(entry.clone()),
78 status: AuditStatus::Ok,
79 detail: None,
80 },
81 Err(msg) => FileAuditResult {
82 diff: diff.clone(),
83 entry: Some(entry.clone()),
84 status: AuditStatus::Failed,
85 detail: Some(msg),
86 },
87 }
88}