kindly_guard_server/storage/
memory.rs1use super::{
20 async_trait, Arc, CorrelationState, DateTime, Duration, EventFilter, EventId, RateLimitKey,
21 RateLimitState, Result, SecurityEvent, SnapshotId, StorageProvider, StorageStats, Utc,
22};
23use std::collections::{HashMap, VecDeque};
24use tokio::sync::RwLock;
25use tracing::{debug, info};
26use uuid::Uuid;
27
28pub struct InMemoryStorage {
30 events: Arc<RwLock<HashMap<EventId, SecurityEvent>>>,
32 events_by_client: Arc<RwLock<HashMap<String, Vec<EventId>>>>,
34 rate_limits: Arc<RwLock<HashMap<String, RateLimitState>>>,
36 correlations: Arc<RwLock<HashMap<String, CorrelationState>>>,
38 snapshots: Arc<RwLock<HashMap<SnapshotId, Snapshot>>>,
40 event_order: Arc<RwLock<VecDeque<EventId>>>,
42 max_events: usize,
44}
45
46#[derive(Clone)]
47struct Snapshot {
48 id: SnapshotId,
49 created_at: DateTime<Utc>,
50 events: HashMap<EventId, SecurityEvent>,
51 rate_limits: HashMap<String, RateLimitState>,
52 correlations: HashMap<String, CorrelationState>,
53}
54
55impl Default for InMemoryStorage {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl InMemoryStorage {
62 pub fn new() -> Self {
64 Self::with_capacity(100_000) }
66
67 pub fn with_capacity(max_events: usize) -> Self {
69 info!(
70 "Initializing in-memory storage with capacity: {}",
71 max_events
72 );
73 Self {
74 events: Arc::new(RwLock::new(HashMap::new())),
75 events_by_client: Arc::new(RwLock::new(HashMap::new())),
76 rate_limits: Arc::new(RwLock::new(HashMap::new())),
77 correlations: Arc::new(RwLock::new(HashMap::new())),
78 snapshots: Arc::new(RwLock::new(HashMap::new())),
79 event_order: Arc::new(RwLock::new(VecDeque::new())),
80 max_events,
81 }
82 }
83
84 async fn evict_if_needed(&self) {
86 let mut order = self.event_order.write().await;
87 let mut events = self.events.write().await;
88
89 while order.len() >= self.max_events {
90 if let Some(old_id) = order.pop_front() {
91 if let Some(old_event) = events.remove(&old_id) {
92 let mut by_client = self.events_by_client.write().await;
94 if let Some(client_events) = by_client.get_mut(&old_event.client_id) {
95 client_events.retain(|id| id != &old_id);
96 }
97 }
98 }
99 }
100 }
101}
102
103#[async_trait]
104impl StorageProvider for InMemoryStorage {
105 async fn store_event(&self, event: &SecurityEvent) -> Result<EventId> {
106 self.evict_if_needed().await;
108
109 let id = EventId(Uuid::new_v4().to_string());
110
111 {
113 let mut events = self.events.write().await;
114 events.insert(id.clone(), event.clone());
115 }
116
117 {
119 let mut by_client = self.events_by_client.write().await;
120 by_client
121 .entry(event.client_id.clone())
122 .or_insert_with(Vec::new)
123 .push(id.clone());
124 }
125
126 {
128 let mut order = self.event_order.write().await;
129 order.push_back(id.clone());
130 }
131
132 debug!("Stored event {} for client {}", id.0, event.client_id);
133 Ok(id)
134 }
135
136 async fn get_event(&self, id: &EventId) -> Result<Option<SecurityEvent>> {
137 let events = self.events.read().await;
138 Ok(events.get(id).cloned())
139 }
140
141 async fn query_events(&self, filter: EventFilter) -> Result<Vec<SecurityEvent>> {
142 let events = self.events.read().await;
143 let by_client = self.events_by_client.read().await;
144
145 let mut results = Vec::new();
146
147 if let Some(client_id) = &filter.client_id {
149 if let Some(event_ids) = by_client.get(client_id) {
150 for event_id in event_ids {
151 if let Some(event) = events.get(event_id) {
152 if Self::matches_filter(event, &filter) {
153 results.push(event.clone());
154 }
155 }
156 }
157 }
158 } else {
159 for event in events.values() {
161 if Self::matches_filter(event, &filter) {
162 results.push(event.clone());
163 }
164 }
165 }
166
167 results.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));
169
170 if let Some(limit) = filter.limit {
172 results.truncate(limit);
173 }
174
175 Ok(results)
176 }
177
178 async fn store_rate_limit_state(
179 &self,
180 key: &RateLimitKey,
181 state: &RateLimitState,
182 ) -> Result<()> {
183 let mut rate_limits = self.rate_limits.write().await;
184 let key_str = format!("{}:{}", key.client_id, key.method.as_deref().unwrap_or("*"));
185 rate_limits.insert(key_str, state.clone());
186 Ok(())
187 }
188
189 async fn get_rate_limit_state(&self, key: &RateLimitKey) -> Result<Option<RateLimitState>> {
190 let rate_limits = self.rate_limits.read().await;
191 let key_str = format!("{}:{}", key.client_id, key.method.as_deref().unwrap_or("*"));
192 Ok(rate_limits.get(&key_str).cloned())
193 }
194
195 async fn cleanup_rate_limit_states(&self, older_than: Duration) -> Result<u64> {
196 let mut rate_limits = self.rate_limits.write().await;
197 let cutoff = Utc::now() - chrono::Duration::from_std(older_than)?;
198 let initial_count = rate_limits.len();
199
200 rate_limits.retain(|_, state| state.last_refill > cutoff);
201
202 let removed = initial_count - rate_limits.len();
203 debug!("Cleaned up {} old rate limit states", removed);
204 Ok(removed as u64)
205 }
206
207 async fn store_correlation_state(
208 &self,
209 client_id: &str,
210 state: &CorrelationState,
211 ) -> Result<()> {
212 let mut correlations = self.correlations.write().await;
213 correlations.insert(client_id.to_string(), state.clone());
214 Ok(())
215 }
216
217 async fn get_correlation_state(&self, client_id: &str) -> Result<Option<CorrelationState>> {
218 let correlations = self.correlations.read().await;
219 Ok(correlations.get(client_id).cloned())
220 }
221
222 async fn create_snapshot(&self) -> Result<SnapshotId> {
223 let id = SnapshotId(Uuid::new_v4().to_string());
224
225 let snapshot = Snapshot {
226 id: id.clone(),
227 created_at: Utc::now(),
228 events: self.events.read().await.clone(),
229 rate_limits: self.rate_limits.read().await.clone(),
230 correlations: self.correlations.read().await.clone(),
231 };
232
233 let mut snapshots = self.snapshots.write().await;
234 snapshots.insert(id.clone(), snapshot);
235
236 info!("Created snapshot {}", id.0);
237 Ok(id)
238 }
239
240 async fn list_snapshots(&self) -> Result<Vec<(SnapshotId, DateTime<Utc>)>> {
241 let snapshots = self.snapshots.read().await;
242 let mut list: Vec<_> = snapshots
243 .values()
244 .map(|s| (s.id.clone(), s.created_at))
245 .collect();
246 list.sort_by(|a, b| b.1.cmp(&a.1)); Ok(list)
248 }
249
250 async fn restore_snapshot(&self, id: &SnapshotId) -> Result<()> {
251 let snapshots = self.snapshots.read().await;
252 let snapshot = snapshots
253 .get(id)
254 .ok_or_else(|| anyhow::anyhow!("Snapshot not found"))?
255 .clone();
256 drop(snapshots);
257
258 *self.events.write().await = snapshot.events;
260 *self.rate_limits.write().await = snapshot.rate_limits;
261 *self.correlations.write().await = snapshot.correlations;
262
263 let mut order = self.event_order.write().await;
265 let mut by_client = self.events_by_client.write().await;
266
267 order.clear();
268 by_client.clear();
269
270 let events = self.events.read().await;
271 let mut event_list: Vec<_> = events.iter().collect();
272 event_list.sort_by_key(|(_, event)| event.timestamp);
273
274 for (id, event) in event_list {
275 order.push_back(id.clone());
276 by_client
277 .entry(event.client_id.clone())
278 .or_insert_with(Vec::new)
279 .push(id.clone());
280 }
281
282 info!("Restored from snapshot {}", id.0);
283 Ok(())
284 }
285
286 async fn delete_snapshot(&self, id: &SnapshotId) -> Result<()> {
287 let mut snapshots = self.snapshots.write().await;
288 snapshots
289 .remove(id)
290 .ok_or_else(|| anyhow::anyhow!("Snapshot not found"))?;
291 Ok(())
292 }
293
294 async fn get_stats(&self) -> Result<StorageStats> {
295 let events = self.events.read().await;
296 let rate_limits = self.rate_limits.read().await;
297 let correlations = self.correlations.read().await;
298
299 let event_size = events.len() * std::mem::size_of::<(EventId, SecurityEvent)>();
301 let rate_limit_size = rate_limits.len() * std::mem::size_of::<(String, RateLimitState)>();
302 let correlation_size =
303 correlations.len() * std::mem::size_of::<(String, CorrelationState)>();
304
305 Ok(StorageStats {
306 event_count: events.len() as u64,
307 total_size: (event_size + rate_limit_size + correlation_size) as u64,
308 rate_limit_entries: rate_limits.len() as u64,
309 correlation_states: correlations.len() as u64,
310 storage_type: "memory".to_string(),
311 metadata: serde_json::json!({
312 "max_events": self.max_events,
313 "snapshots": self.snapshots.read().await.len(),
314 }),
315 })
316 }
317
318 async fn compact(&self) -> Result<()> {
319 self.events.write().await.shrink_to_fit();
321 self.events_by_client.write().await.shrink_to_fit();
322 self.rate_limits.write().await.shrink_to_fit();
323 self.correlations.write().await.shrink_to_fit();
324 debug!("Compacted in-memory storage");
325 Ok(())
326 }
327}
328
329impl InMemoryStorage {
330 fn matches_filter(event: &SecurityEvent, filter: &EventFilter) -> bool {
332 if let Some(event_type) = &filter.event_type {
334 if &event.event_type != event_type {
335 return false;
336 }
337 }
338
339 let event_time =
341 DateTime::<Utc>::from_timestamp(event.timestamp as i64, 0).unwrap_or_else(Utc::now);
342
343 if let Some(from) = filter.from_time {
344 if event_time < from {
345 return false;
346 }
347 }
348
349 if let Some(to) = filter.to_time {
350 if event_time > to {
351 return false;
352 }
353 }
354
355 if let Some(min_severity) = &filter.min_severity {
357 if let Some(severity) = event.metadata.get("severity").and_then(|v| v.as_str()) {
358 let severity_rank = match severity {
360 "low" => 1,
361 "medium" => 2,
362 "high" => 3,
363 "critical" => 4,
364 _ => 0,
365 };
366 let min_rank = match min_severity.as_str() {
367 "low" => 1,
368 "medium" => 2,
369 "high" => 3,
370 "critical" => 4,
371 _ => 0,
372 };
373 if severity_rank < min_rank {
374 return false;
375 }
376 }
377 }
378
379 true
380 }
381}