Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lx9FNLG2CqeBbVGGd9bFsP
49 lines
1.7 KiB
Go
49 lines
1.7 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/danielgtaylor/huma/v2"
|
|
|
|
"github.com/v10networks/nmon/internal/store"
|
|
)
|
|
|
|
// AuditView is one audit-log entry. What changed (before and after) stays in the database: it can hold request
|
|
// bodies, and this list is for answering who did what and when.
|
|
type AuditView struct {
|
|
At time.Time `json:"at"`
|
|
Actor string `json:"actor" doc:"Who: an IDP subject, token:<name>, breakglass, console, dev or system."`
|
|
Action string `json:"action" example:"device.edit"`
|
|
Object string `json:"object"`
|
|
}
|
|
|
|
// AuditList is a page of AuditView, newest first.
|
|
type AuditList struct {
|
|
Items []AuditView `json:"items"`
|
|
Page int64 `json:"page"`
|
|
PerPage int64 `json:"per_page"`
|
|
Total int64 `json:"total"`
|
|
}
|
|
|
|
func (s *server) registerAudit(api huma.API) {
|
|
huma.Register(api, huma.Operation{
|
|
OperationID: "list-audit", Method: http.MethodGet, Path: "/api/v1/audit", Tags: []string{"admin"},
|
|
Summary: "Audit log",
|
|
Description: "Admin only. Who changed what, newest first: logins, token and secret changes, imports, settings, backups.",
|
|
}, s.listAudit)
|
|
}
|
|
|
|
func (s *server) listAudit(ctx context.Context, in *struct{ PageParams }) (*struct{ Body AuditList }, error) {
|
|
rows, total, err := s.Store.ListAudit(ctx, store.Page{Offset: in.offset(), Limit: in.limit()})
|
|
if err != nil {
|
|
return nil, s.storeErr(err)
|
|
}
|
|
out := AuditList{Items: make([]AuditView, 0, len(rows)), Page: in.pageNo(), PerPage: in.limit(), Total: total}
|
|
for _, r := range rows {
|
|
out.Items = append(out.Items, AuditView{At: r.At.UTC(), Actor: r.Actor, Action: r.Action, Object: r.Object})
|
|
}
|
|
return &struct{ Body AuditList }{out}, nil
|
|
}
|