package web import ( "log" "net/http" "github.com/salvacybersec/keyhunter/pkg/storage" ) // OverviewData holds template data for the overview dashboard page. type OverviewData struct { TotalKeys int TotalProviders int ReconSources int LastScan string RecentFindings []storage.Finding PageTitle string } // handleOverview renders the overview dashboard page with aggregated stats. func (s *Server) handleOverview(w http.ResponseWriter, r *http.Request) { data := OverviewData{ PageTitle: "Overview", } // Provider count. if s.cfg.Providers != nil { data.TotalProviders = s.cfg.Providers.Stats().Total } // Recon source count. if s.cfg.ReconEngine != nil { data.ReconSources = len(s.cfg.ReconEngine.List()) } // Recent findings + total count from DB. if s.cfg.DB != nil && s.cfg.EncKey != nil { recent, err := s.cfg.DB.ListFindingsFiltered(s.cfg.EncKey, storage.Filters{Limit: 10}) if err != nil { log.Printf("web: listing recent findings: %v", err) } else { data.RecentFindings = recent } // Total count via a broader query. all, err := s.cfg.DB.ListFindingsFiltered(s.cfg.EncKey, storage.Filters{}) if err != nil { log.Printf("web: counting findings: %v", err) } else { data.TotalKeys = len(all) } } if err := s.tmpl.ExecuteTemplate(w, "layout", data); err != nil { log.Printf("web: rendering overview: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) } }