package handlers import ( "context" "net/http" "strings" "time" "crowdsec-dashy/internal/crowdsec" ) // DashboardHandler serves the main dashboard page. type DashboardHandler struct { deps Deps } func NewDashboardHandler(deps Deps) *DashboardHandler { return &DashboardHandler{deps: deps} } // DashboardData is passed to the dashboard template. type DashboardData struct { PageData RecentDecisions []crowdsec.Decision RecentAlerts []crowdsec.Alert LAPIHealthy bool } func (h *DashboardHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second) defer cancel() var decisions []crowdsec.Decision if h.deps.CLIAvailable { decisions, _ = h.deps.CLI.ListDecisions(ctx, crowdsec.DecisionFilter{Limit: 10}) } // Fetch extra so filtering "update :" scenarios still yields 10 real threats. rawAlerts, _ := h.deps.LAPI.ListAlerts(ctx, crowdsec.AlertFilter{Limit: 50}) var alerts []crowdsec.Alert for _, a := range rawAlerts { s := a.Scenario if strings.HasPrefix(s, "update :") || strings.HasPrefix(s, "update:") { continue } alerts = append(alerts, a) if len(alerts) == 10 { break } } h.deps.Renderer.Render(w, "dashboard", DashboardData{ PageData: NewPageData(r, "Dashboard", h.deps.CLIAvailable, h.deps.PollInterval), RecentDecisions: decisions, RecentAlerts: alerts, LAPIHealthy: h.deps.LAPI.IsHealthy(ctx), }) }