88 lines
2.1 KiB
Rust
88 lines
2.1 KiB
Rust
use std::{collections::HashMap, sync::Arc};
|
|
|
|
use chrono::{DateTime, Utc};
|
|
use tokio::sync::RwLock;
|
|
use uuid::Uuid;
|
|
|
|
#[derive(Clone)]
|
|
pub struct AuditStore {
|
|
inner: Arc<RwLock<AuditState>>,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct AuditState {
|
|
event_types_by_name: HashMap<String, Uuid>,
|
|
events: Vec<AuditEventSnapshot>,
|
|
attributes: Vec<AuditEventAttributeSnapshot>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
#[allow(dead_code)]
|
|
struct AuditEventSnapshot {
|
|
id: Uuid,
|
|
audit_event_type_id: Uuid,
|
|
session_id: Option<Uuid>,
|
|
user_id: Option<Uuid>,
|
|
occurred_at: DateTime<Utc>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
#[allow(dead_code)]
|
|
struct AuditEventAttributeSnapshot {
|
|
id: Uuid,
|
|
audit_event_id: Uuid,
|
|
attribute_key: String,
|
|
attribute_value: String,
|
|
}
|
|
|
|
impl AuditStore {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
inner: Arc::new(RwLock::new(AuditState::default())),
|
|
}
|
|
}
|
|
|
|
pub async fn record<I, K, V>(
|
|
&self,
|
|
action: impl Into<String>,
|
|
session_id: Option<Uuid>,
|
|
user_id: Option<Uuid>,
|
|
occurred_at: DateTime<Utc>,
|
|
attributes: I,
|
|
) where
|
|
I: IntoIterator<Item = (K, V)>,
|
|
K: Into<String>,
|
|
V: Into<String>,
|
|
{
|
|
let mut state = self.inner.write().await;
|
|
let action = action.into();
|
|
let event_type_id = *state
|
|
.event_types_by_name
|
|
.entry(action)
|
|
.or_insert_with(Uuid::new_v4);
|
|
|
|
let audit_event_id = Uuid::new_v4();
|
|
state.events.push(AuditEventSnapshot {
|
|
id: audit_event_id,
|
|
audit_event_type_id: event_type_id,
|
|
session_id,
|
|
user_id,
|
|
occurred_at,
|
|
});
|
|
|
|
for (key, value) in attributes {
|
|
state.attributes.push(AuditEventAttributeSnapshot {
|
|
id: Uuid::new_v4(),
|
|
audit_event_id,
|
|
attribute_key: key.into(),
|
|
attribute_value: value.into(),
|
|
});
|
|
}
|
|
}
|
|
|
|
pub async fn counts(&self) -> (usize, usize) {
|
|
let state = self.inner.read().await;
|
|
(state.events.len(), state.attributes.len())
|
|
}
|
|
}
|