74 lines
2.2 KiB
Rust
74 lines
2.2 KiB
Rust
use uuid::Uuid;
|
|
|
|
use crate::db::models::{AuditEvent, NewAuditEvent};
|
|
use crate::db::{Db, Page, Pagination, db_error};
|
|
use crate::error::AppResult;
|
|
|
|
pub async fn append(db: &Db, input: &NewAuditEvent) -> AppResult<AuditEvent> {
|
|
let client = db.client().await?;
|
|
let row = client
|
|
.query_one(
|
|
"INSERT INTO audit_events (
|
|
run_id, actor_type, actor_id, action, entity_type, entity_id,
|
|
before_data, after_data, metadata
|
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
|
RETURNING *",
|
|
&[
|
|
&input.run_id,
|
|
&input.actor_type,
|
|
&input.actor_id,
|
|
&input.action,
|
|
&input.entity_type,
|
|
&input.entity_id,
|
|
&input.before_data,
|
|
&input.after_data,
|
|
&input.metadata,
|
|
],
|
|
)
|
|
.await
|
|
.map_err(db_error)?;
|
|
AuditEvent::from_row(&row).map_err(db_error)
|
|
}
|
|
|
|
pub async fn list(
|
|
db: &Db,
|
|
run_id: Option<Uuid>,
|
|
entity_type: Option<&str>,
|
|
entity_id: Option<Uuid>,
|
|
pagination: Pagination,
|
|
) -> AppResult<Page<AuditEvent>> {
|
|
let client = db.client().await?;
|
|
let predicate = "($1::uuid IS NULL OR run_id = $1)
|
|
AND ($2::text IS NULL OR entity_type = $2)
|
|
AND ($3::uuid IS NULL OR entity_id = $3)";
|
|
let total_sql = format!("SELECT count(*)::bigint FROM audit_events WHERE {predicate}");
|
|
let total: i64 = client
|
|
.query_one(&total_sql, &[&run_id, &entity_type, &entity_id])
|
|
.await
|
|
.map_err(db_error)?
|
|
.get(0);
|
|
let list_sql = format!(
|
|
"SELECT * FROM audit_events WHERE {predicate}
|
|
ORDER BY created_at DESC, id DESC LIMIT $4 OFFSET $5"
|
|
);
|
|
let rows = client
|
|
.query(
|
|
&list_sql,
|
|
&[
|
|
&run_id,
|
|
&entity_type,
|
|
&entity_id,
|
|
&pagination.limit,
|
|
&pagination.offset,
|
|
],
|
|
)
|
|
.await
|
|
.map_err(db_error)?;
|
|
let items = rows
|
|
.iter()
|
|
.map(AuditEvent::from_row)
|
|
.collect::<Result<Vec<_>, _>>()
|
|
.map_err(db_error)?;
|
|
Ok(Page::new(items, total, pagination))
|
|
}
|