fix: harden DynDNS recovery and publish v1.5.1

This commit is contained in:
admin committed 2026-10-10 02:26:47 +02:00
1 parent 3383b91e49
commit 81def77e3c
37 files changed
+2415 -250

No files matched your search

+70
View File
@@ -0,0 +1,70 @@
package web
import (
"encoding/json"
"net/http"
"net/netip"
"time"
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/buildinfo"
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/diagnostics"
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/model"
)
// Only this allowlisted report is downloadable, never raw Docker logs, stored
// error messages, audit messages, configuration, credentials or session data.
func (s *Server) downloadDiagnostics(w http.ResponseWriter, r *http.Request, _ *model.Session) {
settings, err := s.store.GetSettings(r.Context())
if err != nil {
s.serverError(w, err)
return
}
runs, err := s.store.RecentRuns(r.Context(), 100)
if err != nil {
s.serverError(w, err)
return
}
type run struct {
ID int64 `json:"id"`
StartedAt time.Time `json:"started_at"`
Status string `json:"status"`
}
report := struct {
Format int `json:"format"`
Version string `json:"version"`
ExportedAt time.Time `json:"exported_at"`
Network *diagnostics.Network `json:"current_network"`
UpdaterEnabled bool `json:"updater_enabled"`
IPv6Enabled bool `json:"ipv6_enabled"`
IntervalSeconds int `json:"interval_seconds"`
LastIPv4 string `json:"last_ipv4,omitempty"`
LastIPv6 string `json:"last_ipv6,omitempty"`
Runs []run `json:"recent_runs"`
Events []diagnostics.Event `json:"events"`
}{
Format: 1, Version: buildinfo.Version, ExportedAt: time.Now().UTC(), Network: diagnostics.CurrentNetwork(),
UpdaterEnabled: settings.UpdaterEnabled, IPv6Enabled: settings.IPv6Enabled, IntervalSeconds: settings.UpdateIntervalSeconds,
Events: diagnostics.Snapshot(),
}
if ip, err := netip.ParseAddr(settings.LastIPv4); err == nil && ip.Zone() == "" {
report.LastIPv4 = ip.String()
}
if ip, err := netip.ParseAddr(settings.LastIPv6); err == nil && ip.Zone() == "" {
report.LastIPv6 = ip.String()
}
for _, item := range runs {
status := "unknown"
switch item.Status {
case "running", "ok", "error", "partial":
status = item.Status
}
report.Runs = append(report.Runs, run{item.ID, item.StartedAt, status})
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("Content-Disposition", `attachment; filename="domain-control-diagnostics.json"`)
w.Header().Set("Cache-Control", "no-store")
w.Header().Set("X-Content-Type-Options", "nosniff")
encoder := json.NewEncoder(w)
encoder.SetIndent("", " ")
_ = encoder.Encode(report)
}