feat(admin): очистка всех сканов — POST /api/admin/purge-scans + UI (NETTOPO_RESET_DB_SECRET)

Made-with: Cursor
This commit is contained in:
Луценко Андрей Анатольевич
2026-04-10 16:08:35 +10:00
parent a7f80eac9a
commit a782d36af9
7 changed files with 117 additions and 12 deletions
+30 -4
View File
@@ -12,8 +12,9 @@ import (
)
type Handler struct {
store scans.Store
run *scans.Runner
store scans.Store
run *scans.Runner
resetDBSecret string
}
type LinkView struct {
@@ -49,8 +50,8 @@ type ScanDiffResponse struct {
MissingLinks []string `json:"missing_links"`
}
func NewHandler(store scans.Store, run *scans.Runner) *Handler {
return &Handler{store: store, run: run}
func NewHandler(store scans.Store, run *scans.Runner, resetDBSecret string) *Handler {
return &Handler{store: store, run: run, resetDBSecret: strings.TrimSpace(resetDBSecret)}
}
func (h *Handler) Routes() http.Handler {
@@ -70,9 +71,34 @@ func (h *Handler) Routes() http.Handler {
mux.HandleFunc("GET /api/scans/{id}/interfaces", h.getScanInterfaces)
mux.HandleFunc("GET /api/scans/{id}/links", h.getScanLinks)
mux.HandleFunc("GET /api/scans/{id}/topology", h.getScanTopology)
mux.HandleFunc("POST /api/admin/purge-scans", h.postAdminPurgeScans)
return withJSON(mux)
}
func (h *Handler) postAdminPurgeScans(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeError(w, http.StatusMethodNotAllowed, "use POST")
return
}
if h.resetDBSecret == "" {
writeError(w, http.StatusForbidden, "purge disabled: set NETTOPO_RESET_DB_SECRET in environment")
return
}
key := strings.TrimSpace(r.Header.Get("X-Nettopo-Reset-Key"))
if key == "" || key != h.resetDBSecret {
writeError(w, http.StatusUnauthorized, "invalid or missing X-Nettopo-Reset-Key header")
return
}
if err := h.store.PurgeAllScanData(); err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJSON(w, http.StatusOK, map[string]any{
"ok": true,
"message": "all scan data removed (scan_jobs and related rows)",
})
}
func (h *Handler) health(w http.ResponseWriter, _ *http.Request) {
writeJSON(w, http.StatusOK, map[string]any{
"status": "ok",