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

+29 -25
View File
@@ -13,6 +13,7 @@ import (
"golang.org/x/net/idna"
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/diagnostics"
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/model"
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/pihole"
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/store"
@@ -44,18 +45,12 @@ func (s *Server) piHolePage(w http.ResponseWriter, r *http.Request, session *mod
var view *piHoleView
if len(integrations) > 0 {
integration := integrations[0]
current := piHoleView{Integration: integration}
client, password, accessErr := s.piHoleAccess(r.Context(), integration.ID)
var links []model.PiHoleRecordLink
if accessErr == nil {
var hosts []string
hosts, accessErr = client.ListHosts(r.Context(), password)
if accessErr == nil {
links, accessErr = s.store.SyncPiHoleRecordLinks(r.Context(), integration.ID, hosts)
}
}
if accessErr != nil {
links, _ = s.store.ListPiHoleRecordLinks(r.Context(), integration.ID)
current := piHoleView{Integration: integration, FetchError: integration.LastError}
// Navigation and removing an obsolete connection must work offline.
links, err := s.store.ListPiHoleRecordLinks(r.Context(), integration.ID)
if err != nil {
s.serverError(w, err)
return
}
for _, link := range links {
record := parsePiHoleRecord(link.Value)
@@ -68,15 +63,6 @@ func (s *Server) piHolePage(w http.ResponseWriter, r *http.Request, session *mod
current.ArchivedRecords = append(current.ArchivedRecords, record)
}
}
if accessErr != nil {
current.FetchError = safeMessage(accessErr)
current.Integration.LastError = current.FetchError
_ = s.store.MarkPiHoleSynced(r.Context(), integration.ID, current.FetchError)
} else {
current.Integration.LastError = ""
current.Integration.LastSyncAt = time.Now().UTC()
_ = s.store.MarkPiHoleSynced(r.Context(), integration.ID, "")
}
sortPiHoleRecords(current.Records)
sortPiHoleRecords(current.ArchivedRecords)
view = &current
@@ -122,7 +108,8 @@ func (s *Server) piHoleConnect(w http.ResponseWriter, r *http.Request, session *
s.redirectNotice(w, r, "/pihole", err.Error(), "error")
return
}
if _, err := client.ListHosts(r.Context(), password); err != nil {
hosts, err := client.ListHosts(r.Context(), password)
if err != nil {
s.redirectNotice(w, r, "/pihole", "Pi-hole-Verbindung fehlgeschlagen: "+safeMessage(err), "error")
return
}
@@ -140,6 +127,10 @@ func (s *Server) piHoleConnect(w http.ResponseWriter, r *http.Request, session *
s.redirectNotice(w, r, "/pihole", message, "error")
return
}
if _, err := s.store.SyncPiHoleRecordLinks(r.Context(), integration.ID, hosts); err != nil {
s.serverError(w, err)
return
}
_ = s.store.MarkPiHoleSynced(r.Context(), integration.ID, "")
_ = s.store.AddAudit(r.Context(), "pihole.connected", "Pi-hole verbunden: "+integration.Name+" durch "+session.Username)
s.redirectNotice(w, r, piHoleURL(integration.ID), "Pi-hole verbunden und lokale DNS-Einträge eingelesen.")
@@ -180,7 +171,8 @@ func (s *Server) piHoleSave(w http.ResponseWriter, r *http.Request, session *mod
s.redirectNotice(w, r, piHoleURL(id), err.Error(), "error")
return
}
if _, err := client.ListHosts(r.Context(), password); err != nil {
hosts, err := client.ListHosts(r.Context(), password)
if err != nil {
s.redirectNotice(w, r, piHoleURL(id), "Neue Pi-hole-Konfiguration nicht gespeichert: "+safeMessage(err), "error")
return
}
@@ -194,6 +186,10 @@ func (s *Server) piHoleSave(w http.ResponseWriter, r *http.Request, session *mod
s.redirectNotice(w, r, piHoleURL(id), "Pi-hole-Verbindung konnte nicht gespeichert werden: "+safeMessage(err), "error")
return
}
if _, err := s.store.SyncPiHoleRecordLinks(r.Context(), id, hosts); err != nil {
s.serverError(w, err)
return
}
_ = s.store.MarkPiHoleSynced(r.Context(), id, "")
_ = s.store.AddAudit(r.Context(), "pihole.updated", "Pi-hole-Verbindung geändert: "+integration.Name+" durch "+session.Username)
s.redirectNotice(w, r, piHoleURL(id), "Pi-hole-Verbindung geprüft und gespeichert.")
@@ -254,16 +250,24 @@ func (s *Server) piHoleRefresh(w http.ResponseWriter, r *http.Request, session *
if !ok {
return
}
client, password, err := s.piHoleAccess(r.Context(), id)
ctx, cancel := context.WithTimeout(r.Context(), 8*time.Second)
defer cancel()
client, password, err := s.piHoleAccess(ctx, id)
var hosts []string
if err == nil {
_, err = client.ListHosts(r.Context(), password)
hosts, err = client.ListHosts(ctx, password)
}
if err == nil {
_, err = s.store.SyncPiHoleRecordLinks(r.Context(), id, hosts)
}
if err != nil {
diagnostics.Record(diagnostics.Event{Code: "pihole_refresh_failed", Target: "pihole", Failure: diagnostics.Failure(err), HTTPStatus: diagnostics.HTTPStatus(err)})
message := safeMessage(err)
_ = s.store.MarkPiHoleSynced(r.Context(), id, message)
s.redirectNotice(w, r, piHoleURL(id), "Pi-hole konnte nicht neu eingelesen werden: "+message, "error")
return
}
diagnostics.Record(diagnostics.Event{Code: "pihole_refresh_ok", Target: "pihole"})
_ = s.store.MarkPiHoleSynced(r.Context(), id, "")
s.redirectNotice(w, r, piHoleURL(id), "Lokale DNS-Einträge wurden neu eingelesen.")
}