1use std::sync::Arc;
2
3use crate::db::{ConnExt, CursorPage, CursorRequest, Database, ValidatedFilter};
4use crate::error::Result;
5
6use super::record::AuditRecord;
7
8const COLS: &str = "id, actor, action, resource_type, resource_id, metadata, \
9 ip, user_agent, device_name, device_type, fingerprint, \
10 tenant_id, created_at";
11
12#[derive(Clone)]
18pub struct AuditRepo {
19 inner: Arc<AuditRepoInner>,
20}
21
22struct AuditRepoInner {
23 db: Database,
24}
25
26impl AuditRepo {
27 pub fn new(db: Database) -> Self {
29 Self {
30 inner: Arc::new(AuditRepoInner { db }),
31 }
32 }
33
34 pub async fn list(&self, req: CursorRequest) -> Result<CursorPage<AuditRecord>> {
40 self.inner
41 .db
42 .conn()
43 .select(&format!("SELECT {COLS} FROM audit_log"))
44 .cursor::<AuditRecord>(req)
45 .await
46 }
47
48 pub async fn query(
54 &self,
55 filter: ValidatedFilter,
56 req: CursorRequest,
57 ) -> Result<CursorPage<AuditRecord>> {
58 self.inner
59 .db
60 .conn()
61 .select(&format!("SELECT {COLS} FROM audit_log"))
62 .filter(filter)
63 .cursor::<AuditRecord>(req)
64 .await
65 }
66}