uvb_storage_memory/
audit.rs1use async_trait::async_trait;
2use std::collections::VecDeque;
3use std::sync::Arc;
4use tokio::sync::RwLock;
5use uvb_storage_api::{AuditError, AuditEvent, AuditLogStore, AuditQueryFilters};
6
7const MAX_EVENTS: usize = 10_000; pub struct InMemoryAuditLogStore {
10 events: Arc<RwLock<VecDeque<AuditEvent>>>,
11}
12
13impl InMemoryAuditLogStore {
14 pub fn new() -> Self {
15 Self {
16 events: Arc::new(RwLock::new(VecDeque::new())),
17 }
18 }
19}
20
21impl Default for InMemoryAuditLogStore {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27#[async_trait]
28impl AuditLogStore for InMemoryAuditLogStore {
29 async fn log(&self, event: AuditEvent) -> Result<(), AuditError> {
30 let mut events = self.events.write().await;
31
32 if events.len() >= MAX_EVENTS {
34 events.pop_front();
35 }
36
37 events.push_back(event);
38 Ok(())
39 }
40
41 async fn query(&self, filters: AuditQueryFilters) -> Result<Vec<AuditEvent>, AuditError> {
42 let events = self.events.read().await;
43 let mut results: Vec<AuditEvent> = events
44 .iter()
45 .filter(|e| {
46 if let Some(ref user_id) = filters.user_id {
47 if e.user_id.as_ref() != Some(user_id) {
48 return false;
49 }
50 }
51 if let Some(ref tenant_id) = filters.tenant_id {
52 if &e.tenant_id != tenant_id {
53 return false;
54 }
55 }
56 if let Some(ref types) = filters.event_types {
57 if !types.contains(&e.event_type) {
58 return false;
59 }
60 }
61 if let Some(start) = filters.start_time {
62 if e.timestamp < start {
63 return false;
64 }
65 }
66 if let Some(end) = filters.end_time {
67 if e.timestamp > end {
68 return false;
69 }
70 }
71 if let Some(success) = filters.success {
72 if e.success != success {
73 return false;
74 }
75 }
76 true
77 })
78 .cloned()
79 .collect();
80
81 results.sort_by_key(|a| std::cmp::Reverse(a.timestamp));
83
84 if let Some(offset) = filters.offset {
86 if offset < results.len() {
87 results = results[offset..].to_vec();
88 } else {
89 results.clear();
90 }
91 }
92
93 if let Some(limit) = filters.limit {
94 results.truncate(limit);
95 }
96
97 Ok(results)
98 }
99
100 async fn count(&self, filters: AuditQueryFilters) -> Result<u64, AuditError> {
101 let events = self.query(filters).await?;
102 Ok(events.len() as u64)
103 }
104}