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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user