global events query + handler — fleet-wide notification bell feed
This commit is contained in:
parent
7d1ad50399
commit
6debe1f729
2 changed files with 90 additions and 0 deletions
57
server/internal/api/handlers/global_events.go
Normal file
57
server/internal/api/handlers/global_events.go
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/Fimeg/RedFlag/server/internal/database/queries"
|
||||
"github.com/Fimeg/RedFlag/server/internal/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GlobalEventsHandler serves the fleet-wide event feed for the notification bell.
|
||||
type GlobalEventsHandler struct {
|
||||
agentQueries *queries.AgentQueries
|
||||
}
|
||||
|
||||
// NewGlobalEventsHandler creates a GlobalEventsHandler.
|
||||
func NewGlobalEventsHandler(aq *queries.AgentQueries) *GlobalEventsHandler {
|
||||
return &GlobalEventsHandler{agentQueries: aq}
|
||||
}
|
||||
|
||||
// GetGlobalEvents returns recent system events across all agents.
|
||||
// GET /api/v1/events?severity=error,critical,warning&limit=50
|
||||
func (h *GlobalEventsHandler) GetGlobalEvents(c *gin.Context) {
|
||||
severity := c.Query("severity")
|
||||
limitStr := c.DefaultQuery("limit", "50")
|
||||
limit, err := strconv.Atoi(limitStr)
|
||||
if err != nil || limit < 1 {
|
||||
limit = 50
|
||||
}
|
||||
if limit > 200 {
|
||||
limit = 200
|
||||
}
|
||||
|
||||
events, err := h.agentQueries.GetGlobalEvents(severity, limit)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to fetch global events: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to fetch events"})
|
||||
return
|
||||
}
|
||||
|
||||
// Populate narrative for each event — UI consumes rendered text.
|
||||
for i := range events {
|
||||
events[i].Narrative = services.RenderSystemEvent(
|
||||
events[i].EventType,
|
||||
events[i].EventSubtype,
|
||||
events[i].Message,
|
||||
events[i].Metadata,
|
||||
)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"events": events,
|
||||
"total": len(events),
|
||||
})
|
||||
}
|
||||
|
|
@ -478,6 +478,39 @@ func (q *AgentQueries) GetAgentEvents(agentID uuid.UUID, severity string, limit
|
|||
return events, nil
|
||||
}
|
||||
|
||||
// GetGlobalEvents retrieves recent system events across all agents.
|
||||
// Used by the notification bell to surface fleet-wide activity.
|
||||
func (q *AgentQueries) GetGlobalEvents(severity string, limit int) ([]models.SystemEvent, error) {
|
||||
query := `
|
||||
SELECT id, agent_id, event_type, event_subtype, severity, component,
|
||||
message, metadata, created_at
|
||||
FROM system_events
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $1
|
||||
`
|
||||
args := []interface{}{limit}
|
||||
|
||||
if severity != "" {
|
||||
query = `
|
||||
SELECT id, agent_id, event_type, event_subtype, severity, component,
|
||||
message, metadata, created_at
|
||||
FROM system_events
|
||||
WHERE severity = ANY(string_to_array($1, ','))
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $2
|
||||
`
|
||||
args = []interface{}{severity, limit}
|
||||
}
|
||||
|
||||
var events []models.SystemEvent
|
||||
err := q.db.Select(&events, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch global events: %w", err)
|
||||
}
|
||||
|
||||
return events, nil
|
||||
}
|
||||
|
||||
// SetAgentUpdating marks an agent as updating with nonce
|
||||
func (q *AgentQueries) SetAgentUpdating(agentID string, isUpdating bool, targetVersion string) error {
|
||||
query := `
|
||||
|
|
|
|||
Loading…
Reference in a new issue