Skip to main content

ares/db/
audit_log.rs

1use sqlx::{PgPool, Row};
2use crate::types::{AppError, Result};
3use serde::{Deserialize, Serialize};
4use std::time::{SystemTime, UNIX_EPOCH};
5
6fn now_ts() -> i64 {
7    SystemTime::now()
8        .duration_since(UNIX_EPOCH)
9        .unwrap()
10        .as_secs() as i64
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct AuditLogEntry {
15    pub id: String,
16    pub action: String,
17    pub resource_type: String,
18    pub resource_id: String,
19    pub details: Option<String>,
20    pub admin_ip: Option<String>,
21    pub created_at: i64,
22}
23
24pub async fn log_admin_action(
25    pool: &PgPool,
26    action: &str,
27    resource_type: &str,
28    resource_id: &str,
29    details: Option<&str>,
30    admin_ip: Option<&str>,
31) -> Result<()> {
32    let id = uuid::Uuid::new_v4().to_string();
33    let now = now_ts();
34
35    sqlx::query(
36        "INSERT INTO admin_audit_log (id, action, resource_type, resource_id, details, admin_ip, created_at)
37         VALUES ($1, $2, $3, $4, $5, $6, $7)"
38    )
39    .bind(&id)
40    .bind(action)
41    .bind(resource_type)
42    .bind(resource_id)
43    .bind(details)
44    .bind(admin_ip)
45    .bind(now)
46    .execute(pool)
47    .await
48    .map_err(|e| AppError::Database(e.to_string()))?;
49
50    Ok(())
51}
52
53pub async fn list_audit_log(pool: &PgPool, limit: i64, offset: i64) -> Result<Vec<AuditLogEntry>> {
54    let rows = sqlx::query(
55        "SELECT id, action, resource_type, resource_id, details, admin_ip, created_at
56         FROM admin_audit_log ORDER BY created_at DESC LIMIT $1 OFFSET $2"
57    )
58    .bind(limit)
59    .bind(offset)
60    .fetch_all(pool)
61    .await
62    .map_err(|e| AppError::Database(e.to_string()))?;
63
64    rows.iter().map(|row| {
65        Ok(AuditLogEntry {
66            id: row.get("id"),
67            action: row.get("action"),
68            resource_type: row.get("resource_type"),
69            resource_id: row.get("resource_id"),
70            details: row.get("details"),
71            admin_ip: row.get("admin_ip"),
72            created_at: row.get("created_at"),
73        })
74    }).collect()
75}