package cli import ( "encoding/json" "fmt" "net/url" "strconv" "github.com/spf13/cobra" "gitea.mynodes.xyz/ilker/llmgw/internal/store" ) func newAuditCmd(client func() *ctlClient, asJSON *bool) *cobra.Command { var ( since, actor, contains string limit int detail bool ) c := &cobra.Command{ Use: "audit", Short: "Who changed what: every change through the admin API and the administration pages", Long: "Each change made with `llmgw ctl`, the console, or the pages under /admin —\n" + "and a person's own keys and password — is recorded: who, when, through\n" + "what, the fields it was given with anything secret taken out, and how it\n" + "ended. The newest first.", Example: " llmgw ctl audit --since 24h\n llmgw ctl audit --actor ilker --contains models\n llmgw ctl audit --contains bob@example.com --detail", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { q := url.Values{"since": {since}, "limit": {strconv.Itoa(limit)}} if actor != "" { q.Set("actor", actor) } if contains != "" { q.Set("contains", contains) } var ev []store.AuditEvent if err := client().get(cmd.Context(), "/api/v1/audit?"+q.Encode(), &ev); err != nil { return err } if *asJSON { return json.NewEncoder(cmd.OutOrStdout()).Encode(ev) } if len(ev) == 0 { fmt.Fprintln(cmd.OutOrStdout(), "No changes recorded in that time.") return nil } w := tab() fmt.Fprintln(w, "WHEN (UTC)\tWHO\tVIA\tWHAT\tTARGET\tSTATUS") for _, e := range ev { fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%d\n", e.At.UTC().Format("2006-01-02 15:04:05"), e.Actor, e.Source, e.Action, dash(e.Target), e.Status) if detail && e.Detail != "" && e.Detail != "{}" { fmt.Fprintf(w, "\t\t\t %s\t\t\n", e.Detail) } } return w.Flush() }, } f := c.Flags() f.StringVar(&since, "since", "7d", "how far back: 90m, 24h, 30d") f.StringVar(&actor, "actor", "", "only changes by this person") f.StringVar(&contains, "contains", "", "only changes whose action or target contains this") f.IntVar(&limit, "limit", 200, "at most this many") f.BoolVar(&detail, "detail", false, "show the fields each change was given") return c }