fix(tui,status,store): add delete confirm, input validation, XSS fix, history persistence

Prevent accidental deletes with y/n confirmation dialog. Validate all
numeric form inputs (interval, port, timeout, threshold, retries) with
range checks instead of silently defaulting to zero. Escape user-supplied
data in status page JavaScript to close XSS via monitor names. Persist
check history to new check_history table so sparklines and uptime
percentages survive restarts.
This commit is contained in:
2026-05-14 20:51:06 -04:00
parent 2f8de35d4b
commit e97780ad38
9 changed files with 253 additions and 24 deletions
+30
View File
@@ -1,6 +1,7 @@
package monitor
import (
"go-upkeep/internal/store"
"sync"
"time"
)
@@ -19,6 +20,31 @@ var (
historyMu sync.RWMutex
)
func InitHistoryFromStore() {
s := store.Get()
if s == nil {
return
}
all := s.LoadAllHistory(maxHistoryLen)
historyMu.Lock()
defer historyMu.Unlock()
for siteID, records := range all {
h := &SiteHistory{}
for _, r := range records {
h.TotalChecks++
if r.IsUp {
h.UpChecks++
}
h.Latencies = append(h.Latencies, time.Duration(r.LatencyNs))
h.Statuses = append(h.Statuses, r.IsUp)
}
histories[siteID] = h
}
if len(all) > 0 {
AddLog("Loaded check history from database")
}
}
func RecordCheck(siteID int, latency time.Duration, isUp bool) {
historyMu.Lock()
defer historyMu.Unlock()
@@ -43,6 +69,10 @@ func RecordCheck(siteID int, latency time.Duration, isUp bool) {
if len(h.Statuses) > maxHistoryLen {
h.Statuses = h.Statuses[len(h.Statuses)-maxHistoryLen:]
}
if s := store.Get(); s != nil {
go s.SaveCheck(siteID, latency.Nanoseconds(), isUp)
}
}
func GetHistory(siteID int) (SiteHistory, bool) {