1use serde::Serialize;
2
3use crate::db::{ColumnMap, FromRow};
4use crate::error::Result;
5
6#[derive(Debug, Clone, Serialize)]
12pub struct AuditRecord {
13 pub id: String,
15 pub actor: String,
17 pub action: String,
19 pub resource_type: String,
21 pub resource_id: String,
23 pub metadata: serde_json::Value,
25 pub ip: Option<String>,
27 pub user_agent: Option<String>,
29 pub device_name: Option<String>,
31 pub device_type: Option<String>,
33 pub fingerprint: Option<String>,
35 pub tenant_id: Option<String>,
37 pub created_at: String,
39}
40
41impl FromRow for AuditRecord {
42 fn from_row(row: &libsql::Row) -> Result<Self> {
43 let cols = ColumnMap::from_row(row);
44 let metadata_str: String = cols.get(row, "metadata")?;
45 let metadata: serde_json::Value = serde_json::from_str(&metadata_str).map_err(|e| {
46 crate::error::Error::internal(format!("invalid audit metadata JSON: {e}"))
47 })?;
48
49 Ok(Self {
50 id: cols.get(row, "id")?,
51 actor: cols.get(row, "actor")?,
52 action: cols.get(row, "action")?,
53 resource_type: cols.get(row, "resource_type")?,
54 resource_id: cols.get(row, "resource_id")?,
55 metadata,
56 ip: cols.get(row, "ip")?,
57 user_agent: cols.get(row, "user_agent")?,
58 device_name: cols.get(row, "device_name")?,
59 device_type: cols.get(row, "device_type")?,
60 fingerprint: cols.get(row, "fingerprint")?,
61 tenant_id: cols.get(row, "tenant_id")?,
62 created_at: cols.get(row, "created_at")?,
63 })
64 }
65}