package api import ( "net/http" "time" "codeberg.org/SquidSE/ClusterCanvas/service/internal/auth" "codeberg.org/SquidSE/ClusterCanvas/service/internal/settings" ) type authLogsResponse struct { Events []settings.AuthAuditEvent `json:"events"` } func (app *App) authLogsListHandler(writer http.ResponseWriter, request *http.Request) { if err := app.authorizeLogsRead(request); err != nil { writeJSON(writer, http.StatusForbidden, apiErrorResponse{Error: err.Error()}) return } store, err := settings.LoadAuthAuditOrEmpty(app.ConfigDir) if err != nil { writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()}) return } filtered := make([]settings.AuthAuditEvent, 0, len(store.Events)) for index := len(store.Events) - 1; index >= 0; index-- { filtered = append(filtered, store.Events[index]) } writeJSON(writer, http.StatusOK, authLogsResponse{Events: filtered}) } func appendAuthAudit( configDir string, action string, outcome settings.AuthAuditOutcome, category settings.AuthAuditCategory, actor string, target string, detail string, ) { eventID, err := auth.NewUUID() if err != nil { return } _ = settings.AppendAuthAuditEvent(configDir, settings.AuthAuditEvent{ ID: eventID, At: time.Now().UTC(), Action: action, Outcome: outcome, Category: category, Actor: actor, Target: target, Detail: detail, }) } func actorUsernameFromRequest(request *http.Request) string { user, ok := UserFromContext(request.Context()) if !ok { return "" } return user.Username }