audit-log: expose total count in /api/audit-log response
Per iris's dashboard-side ask: return { entries, total } instead of a
bare array so the UI can show 'latest 500 of N' rather than silently
capping at the clamp. Adds AuditLog::count_total().
This commit is contained in:
parent
a452a92fb1
commit
962259a8d6
2 changed files with 23 additions and 5 deletions
|
|
@ -168,6 +168,14 @@ impl AuditLog {
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Total row count, regardless of the `list_recent` clamp. Lets the
|
||||||
|
/// dashboard show "latest N of TOTAL" instead of silently capping.
|
||||||
|
pub fn count_total(&self) -> Result<i64> {
|
||||||
|
let conn = self.conn.lock().unwrap();
|
||||||
|
let n: i64 = conn.query_row("SELECT COUNT(*) FROM audit_log", [], |r| r.get(0))?;
|
||||||
|
Ok(n)
|
||||||
|
}
|
||||||
|
|
||||||
/// Drop rows older than the retention window. Returns the number of
|
/// Drop rows older than the retention window. Returns the number of
|
||||||
/// rows deleted. Called from the hourly vacuum loop.
|
/// rows deleted. Called from the hourly vacuum loop.
|
||||||
pub fn vacuum(&self) -> Result<u64> {
|
pub fn vacuum(&self) -> Result<u64> {
|
||||||
|
|
@ -255,6 +263,7 @@ mod tests {
|
||||||
assert!(rows[1].detail.is_none());
|
assert!(rows[1].detail.is_none());
|
||||||
assert_eq!(rows[0].agent, "atlas");
|
assert_eq!(rows[0].agent, "atlas");
|
||||||
assert_eq!(rows[0].action, "restart_infra");
|
assert_eq!(rows[0].action, "restart_infra");
|
||||||
|
assert_eq!(db.count_total().expect("count"), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -1315,12 +1315,21 @@ async fn api_container_resources() -> Response {
|
||||||
|
|
||||||
/// `GET /api/audit-log` — most-recent agent-initiated privileged-action
|
/// `GET /api/audit-log` — most-recent agent-initiated privileged-action
|
||||||
/// audit entries, newest first (server-clamped to 500). Backs the
|
/// audit entries, newest first (server-clamped to 500). Backs the
|
||||||
/// operator dashboard's audit view. Returns `Vec<AuditEntry>` JSON.
|
/// operator dashboard's audit view. Returns
|
||||||
|
/// `{ "entries": [AuditEntry…], "total": N }` so the UI can show
|
||||||
|
/// "latest 500 of N" rather than silently capping. `ts_unix` is in
|
||||||
|
/// **seconds**.
|
||||||
async fn api_audit_log(State(state): State<AppState>) -> Response {
|
async fn api_audit_log(State(state): State<AppState>) -> Response {
|
||||||
match state.coord.audit_log.list_recent(500) {
|
const LIMIT: usize = 500;
|
||||||
Ok(rows) => axum::Json(rows).into_response(),
|
let entries = match state.coord.audit_log.list_recent(LIMIT) {
|
||||||
Err(e) => error_response(&format!("audit-log: {e:#}")),
|
Ok(rows) => rows,
|
||||||
}
|
Err(e) => return error_response(&format!("audit-log: {e:#}")),
|
||||||
|
};
|
||||||
|
let total = match state.coord.audit_log.count_total() {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(e) => return error_response(&format!("audit-log count: {e:#}")),
|
||||||
|
};
|
||||||
|
axum::Json(serde_json::json!({ "entries": entries, "total": total })).into_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validate that a path-param agent name conforms to the hyperhive
|
/// Validate that a path-param agent name conforms to the hyperhive
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue