feat(audit): clickable column headers with asc/desc sort
CI / Build (windows/amd64) (pull_request) Successful in 23s
CI / Lint (pull_request) Successful in 34s
CI / Build (linux/amd64) (pull_request) Successful in 23s
CI / Build (linux/arm64) (pull_request) Successful in 21s
CI / Test (linux/amd64) (pull_request) Successful in 3m41s

This commit is contained in:
2026-05-05 08:15:22 +01:00
parent 1d0d994bc4
commit ba425c9766
7 changed files with 207 additions and 8 deletions
+48
View File
@@ -109,6 +109,54 @@ func TestListAuditFiltersAndOrdering(t *testing.T) {
}
}
func TestListAuditSort(t *testing.T) {
t.Parallel()
st, uid := newAuditTestStore(t)
t0 := time.Now().UTC()
appendAudit(t, st, uid, "user", "host.enrolled", "host", "h1", t0.Add(-3*time.Hour))
appendAudit(t, st, uid, "user", "alert.acknowledge", "alert", "a1", t0.Add(-time.Hour))
appendAudit(t, st, "", "system", "host.auto_init", "host", "h1", t0.Add(-30*time.Minute))
ctx := context.Background()
// Sort by action ASC.
got, err := st.ListAudit(ctx, AuditFilter{OrderBy: "action", OrderAsc: true})
if err != nil {
t.Fatalf("sort action asc: %v", err)
}
wantActions := []string{"alert.acknowledge", "host.auto_init", "host.enrolled"}
for i, w := range wantActions {
if got[i].Action != w {
t.Errorf("[%d] action: got %q want %q", i, got[i].Action, w)
}
}
// Sort by action DESC.
got, _ = st.ListAudit(ctx, AuditFilter{OrderBy: "action", OrderAsc: false})
if got[0].Action != "host.enrolled" {
t.Errorf("desc head: got %q want host.enrolled", got[0].Action)
}
// Unknown OrderBy → falls back to ts DESC.
got, _ = st.ListAudit(ctx, AuditFilter{OrderBy: "DROP TABLE; --"})
if got[0].Action != "host.auto_init" {
t.Errorf("unknown OrderBy should fall back to ts DESC; got head %q", got[0].Action)
}
// Sort by actor — ties tie-break on ts DESC, so 'user' rows
// should come back newest-first within the actor group.
got, _ = st.ListAudit(ctx, AuditFilter{OrderBy: "actor", OrderAsc: true})
// First two are 'system' (1 row) and 'user' (2 rows newest-first):
// expect system → user(ack) → user(enrolled)
if got[0].Actor != "system" {
t.Errorf("actor asc head: got %q want system", got[0].Actor)
}
if got[1].Action != "alert.acknowledge" {
t.Errorf("actor asc tie-break should be ts DESC; got [1]=%q", got[1].Action)
}
}
func TestDistinctAuditActions(t *testing.T) {
t.Parallel()
st, uid := newAuditTestStore(t)