62 lines
1.8 KiB
Go
62 lines
1.8 KiB
Go
package audit
|
|
|
|
import (
|
|
"context"
|
|
|
|
"nadir/internal/auditlog"
|
|
"nadir/internal/rbac"
|
|
|
|
"github.com/danielgtaylor/huma/v2"
|
|
)
|
|
|
|
const ModuleID = "audit"
|
|
|
|
type Module struct {
|
|
store *auditlog.Store
|
|
}
|
|
|
|
func New(store *auditlog.Store) *Module { return &Module{store: store} }
|
|
|
|
func (m *Module) ID() string { return ModuleID }
|
|
|
|
// Permissions: read to view the audit trail. There is no write - entries are
|
|
// produced by the middleware, never by an API call.
|
|
func (m *Module) Permissions() []rbac.Permission {
|
|
return []rbac.Permission{rbac.Read}
|
|
}
|
|
|
|
// Types are named AuditList* (not ListInput/ListOutput) because Huma derives
|
|
// OpenAPI schema names from the Go type name alone, not package-qualified, so a
|
|
// bare "ListOutput" here would collide with the packages module's.
|
|
type AuditListInput struct {
|
|
Limit int `query:"limit" default:"200" minimum:"1" maximum:"10000" doc:"Max entries to return, newest first"`
|
|
}
|
|
|
|
type AuditListOutput struct {
|
|
Body struct {
|
|
Entries []auditlog.Entry `json:"entries" doc:"Recorded actions, newest first"`
|
|
}
|
|
}
|
|
|
|
func (m *Module) Register(api huma.API) {
|
|
huma.Register(api, huma.Operation{
|
|
OperationID: "audit-list",
|
|
Method: "GET",
|
|
Path: "/api/audit",
|
|
Summary: "List recorded actions",
|
|
Description: "Returns the audit trail of privileged write operations " +
|
|
"(who, what, when, result), newest first.",
|
|
Tags: []string{"Audit"},
|
|
Metadata: map[string]any{"module": ModuleID, "permission": "read"},
|
|
Errors: []int{401, 403, 500},
|
|
}, func(ctx context.Context, in *AuditListInput) (*AuditListOutput, error) {
|
|
entries, err := m.store.List(in.Limit)
|
|
if err != nil {
|
|
return nil, huma.Error500InternalServerError("read audit log failed", err)
|
|
}
|
|
out := &AuditListOutput{}
|
|
out.Body.Entries = entries
|
|
return out, nil
|
|
})
|
|
}
|