New page /analytics/compare and API GET /admin/analytics/compare (+ /lists/{group}):
the administrator picks an old (A) and a new (B) run; the report shows the new
addresses (only in B), the ones that left (only in A) and the common ones whose
membership in the seven indicators (pass, partial, fail, egress https any/all,
ingress ssh any/all) differs, with a "what changed" summary per address; the
dynamics of each indicator (delta = new - left + entered - exited) and a verdict
transition matrix. Every number opens a list with CSV. Cancelled addresses are not
part of a run. The list dialog moved to a shared analytics-dialog.js and template;
/analytics got a "compare with another run" button.
Docs, plan and summary in docs/changes/.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
73 lines
3.3 KiB
Go
73 lines
3.3 KiB
Go
package dashboard
|
|
|
|
import "net/http"
|
|
|
|
func (s *Server) routes(mux *http.ServeMux) {
|
|
// /login, /logout and /static/ are the only routes reachable without a
|
|
// session — see authMiddleware in auth.go.
|
|
mux.HandleFunc("GET /login", s.handleLoginPage)
|
|
mux.HandleFunc("POST /login", s.handleLoginSubmit)
|
|
mux.HandleFunc("POST /logout", s.handleLogout)
|
|
|
|
mux.HandleFunc("GET /{$}", s.handleIndex)
|
|
|
|
mux.HandleFunc("GET /overview", s.handleOverview)
|
|
mux.HandleFunc("GET /overview/fragment", s.handleOverviewFragment)
|
|
|
|
mux.HandleFunc("GET /ips", s.handleIPsPage)
|
|
mux.HandleFunc("GET /ips/{ip}", s.handleIPDetail)
|
|
mux.HandleFunc("POST /ips", s.handleIPsSubmit)
|
|
mux.HandleFunc("POST /ips/scan", s.handleIPsScan)
|
|
mux.HandleFunc("GET /ips/scan/status", s.handleIPsScanStatus)
|
|
mux.HandleFunc("POST /ips/{ip}/recheck", s.handleIPRecheck)
|
|
mux.HandleFunc("POST /ips/{ip}/cancel", s.handleIPCancel)
|
|
mux.HandleFunc("DELETE /ips/{ip}", s.handleIPDelete)
|
|
mux.HandleFunc("POST /ips/delete", s.handleIPsDeleteSelected)
|
|
mux.HandleFunc("POST /ips/recheck", s.handleIPsRecheckSelected)
|
|
mux.HandleFunc("POST /ips/clear", s.handleIPsClear)
|
|
|
|
mux.HandleFunc("GET /registry", s.handleRegistryPage)
|
|
mux.HandleFunc("GET /registry/{ip}", s.handleRegistryDetail)
|
|
|
|
mux.HandleFunc("GET /analytics", s.handleAnalyticsPage)
|
|
mux.HandleFunc("GET /analytics/lists/{kind}", s.handleAnalyticsList)
|
|
mux.HandleFunc("GET /analytics/csv/{kind}", s.handleAnalyticsCSV)
|
|
mux.HandleFunc("GET /analytics/compare", s.handleAnalyticsComparePage)
|
|
mux.HandleFunc("GET /analytics/compare/lists/{group}", s.handleAnalyticsCompareList)
|
|
mux.HandleFunc("GET /analytics/compare/csv/{group}", s.handleAnalyticsCompareCSV)
|
|
|
|
mux.HandleFunc("GET /validators", s.handleValidatorsPage)
|
|
mux.HandleFunc("POST /validators", s.handleValidatorCreate)
|
|
mux.HandleFunc("PUT /validators/{id}", s.handleValidatorUpdate)
|
|
mux.HandleFunc("DELETE /validators/{id}", s.handleValidatorDelete)
|
|
|
|
mux.HandleFunc("GET /sites", s.handleSitesPage)
|
|
mux.HandleFunc("POST /sites", s.handleSiteCreate)
|
|
mux.HandleFunc("PUT /sites/{index}", s.handleSitePut)
|
|
mux.HandleFunc("DELETE /sites/{index}", s.handleSiteDelete)
|
|
|
|
mux.HandleFunc("GET /targets", s.handleTargetsPage)
|
|
mux.HandleFunc("POST /targets", s.handleTargetCreate)
|
|
mux.HandleFunc("PUT /targets/{group}", s.handleTargetUpdate)
|
|
mux.HandleFunc("DELETE /targets/{group}", s.handleTargetDelete)
|
|
|
|
mux.HandleFunc("GET /check-types", s.handleCheckTypesPage)
|
|
mux.HandleFunc("POST /check-types", s.handleCheckTypeCreate)
|
|
mux.HandleFunc("PUT /check-types/{name}", s.handleCheckTypeUpdate)
|
|
mux.HandleFunc("DELETE /check-types/{name}", s.handleCheckTypeDelete)
|
|
|
|
mux.HandleFunc("GET /settings", s.handleSettingsPage)
|
|
mux.HandleFunc("PUT /settings", s.handleSettingsPut)
|
|
mux.HandleFunc("PUT /settings/inbound-checks", s.handleInboundChecksPut)
|
|
mux.HandleFunc("PUT /settings/subnets", s.handleSubnetsPut)
|
|
mux.HandleFunc("PUT /settings/auto-cycle", s.handleAutoCyclePut)
|
|
mux.HandleFunc("POST /settings/auto-cycle/start", s.handleAutoCycleStart)
|
|
mux.HandleFunc("POST /settings/auto-cycle/stop", s.handleAutoCycleStop)
|
|
|
|
mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServerFS(staticSubFS())))
|
|
}
|
|
|
|
func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
|
|
http.Redirect(w, r, "/overview", http.StatusFound)
|
|
}
|