Add activity logs, sidebar badges, and logout with working alert colors.

Record auth audits and surface them in Activity, poll sidebar counts without resetting idle, and add a profile logout path plus theme red/green/blue tokens so failure badges render.
This commit is contained in:
2026-07-18 21:43:44 +02:00
parent e3793f380c
commit 463aa9a7a3
32 changed files with 3282 additions and 171 deletions
+1 -46
View File
@@ -450,50 +450,24 @@ func (app *App) nodesDeleteHandler(writer http.ResponseWriter, request *http.Req
}
func (app *App) nodeLogsListHandler(writer http.ResponseWriter, request *http.Request) {
if err := app.authorizeNodesRead(request); err != nil {
if err := app.authorizeLogsRead(request); err != nil {
writeJSON(writer, http.StatusForbidden, apiErrorResponse{Error: err.Error()})
return
}
user, ok := UserFromContext(request.Context())
if !ok {
writeJSON(writer, http.StatusUnauthorized, apiErrorResponse{Error: "authentication required"})
return
}
settingsPayload, err := loadSettingsOrDefault(app.ConfigDir)
if err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
store, err := settings.LoadNodeAuditOrEmpty(app.ConfigDir)
if err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
nodesStore, err := settings.LoadNodesOrEmpty(app.ConfigDir)
if err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
nodeByID := make(map[string]settings.Node, len(nodesStore.Nodes))
for _, node := range nodesStore.Nodes {
nodeByID[node.ID] = node
}
kindFilter := strings.TrimSpace(request.URL.Query().Get("kind"))
isAdmin := userIsAdministrator(user)
filtered := make([]settings.NodeAuditEvent, 0, len(store.Events))
for index := len(store.Events) - 1; index >= 0; index-- {
event := store.Events[index]
if kindFilter != "" && string(event.NodeKind) != kindFilter {
continue
}
if !userCanSeeNodeAuditEvent(user, settingsPayload.Groups, nodeByID, event, isAdmin) {
continue
}
filtered = append(filtered, event)
}
@@ -609,25 +583,6 @@ func userCanAccessNode(user settings.UserCredential, groups []settings.Group, no
return false
}
func userCanSeeNodeAuditEvent(
user settings.UserCredential,
groups []settings.Group,
nodeByID map[string]settings.Node,
event settings.NodeAuditEvent,
isAdmin bool,
) bool {
if isAdmin {
return true
}
if event.Actor == user.Username {
return true
}
if node, ok := nodeByID[event.NodeID]; ok {
return userCanAccessNode(user, groups, node)
}
return false
}
func appendNodeAudit(
configDir string,
action settings.NodeAuditAction,