oxihuman_core/
error_audit_log.rs1#![allow(dead_code)]
4
5pub struct AuditEventEntry {
7 pub timestamp_ms: u64,
8 pub actor: String,
9 pub action: String,
10}
11
12pub struct AuditEventLog {
14 pub entries: Vec<AuditEventEntry>,
15}
16
17impl AuditEventLog {
18 pub fn new() -> Self {
19 AuditEventLog {
20 entries: Vec::new(),
21 }
22 }
23}
24
25impl Default for AuditEventLog {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31pub fn new_audit_event_log() -> AuditEventLog {
32 AuditEventLog::new()
33}
34
35pub fn audit_event_record(log: &mut AuditEventLog, ts: u64, actor: &str, action: &str) {
36 log.entries.push(AuditEventEntry {
37 timestamp_ms: ts,
38 actor: actor.to_string(),
39 action: action.to_string(),
40 });
41}
42
43pub fn audit_event_count(log: &AuditEventLog) -> usize {
44 log.entries.len()
45}
46
47pub fn audit_event_last(log: &AuditEventLog) -> Option<&AuditEventEntry> {
48 log.entries.last()
49}
50
51pub fn audit_event_clear(log: &mut AuditEventLog) {
52 log.entries.clear();
53}
54
55pub fn audit_event_by_actor<'a>(log: &'a AuditEventLog, actor: &str) -> Vec<&'a AuditEventEntry> {
56 log.entries.iter().filter(|e| e.actor == actor).collect()
57}
58
59pub fn audit_event_since(log: &AuditEventLog, ts: u64) -> Vec<&AuditEventEntry> {
60 log.entries
61 .iter()
62 .filter(|e| e.timestamp_ms >= ts)
63 .collect()
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_new_empty() {
72 let log = new_audit_event_log();
74 assert_eq!(audit_event_count(&log), 0);
75 }
76
77 #[test]
78 fn test_record_and_count() {
79 let mut log = new_audit_event_log();
81 audit_event_record(&mut log, 1000, "alice", "login");
82 assert_eq!(audit_event_count(&log), 1);
83 }
84
85 #[test]
86 fn test_last_entry() {
87 let mut log = new_audit_event_log();
89 audit_event_record(&mut log, 100, "bob", "create");
90 audit_event_record(&mut log, 200, "alice", "delete");
91 let last = audit_event_last(&log).expect("should succeed");
92 assert_eq!(last.actor, "alice");
93 assert_eq!(last.action, "delete");
94 }
95
96 #[test]
97 fn test_clear() {
98 let mut log = new_audit_event_log();
100 audit_event_record(&mut log, 1, "x", "y");
101 audit_event_clear(&mut log);
102 assert_eq!(audit_event_count(&log), 0);
103 }
104
105 #[test]
106 fn test_by_actor() {
107 let mut log = new_audit_event_log();
109 audit_event_record(&mut log, 1, "alice", "a");
110 audit_event_record(&mut log, 2, "bob", "b");
111 audit_event_record(&mut log, 3, "alice", "c");
112 let alice_events = audit_event_by_actor(&log, "alice");
113 assert_eq!(alice_events.len(), 2);
114 }
115
116 #[test]
117 fn test_since() {
118 let mut log = new_audit_event_log();
120 audit_event_record(&mut log, 100, "x", "a");
121 audit_event_record(&mut log, 200, "x", "b");
122 audit_event_record(&mut log, 300, "x", "c");
123 let recent = audit_event_since(&log, 200);
124 assert_eq!(recent.len(), 2);
125 }
126
127 #[test]
128 fn test_last_empty() {
129 let log = new_audit_event_log();
131 assert!(audit_event_last(&log).is_none());
132 }
133
134 #[test]
135 fn test_multiple_actors() {
136 let mut log = new_audit_event_log();
138 audit_event_record(&mut log, 1, "alice", "x");
139 let result = audit_event_by_actor(&log, "ghost");
140 assert!(result.is_empty());
141 }
142}