Files
felhom-controller/controller/internal/web/kept_copies.go
T

71 lines
2.4 KiB
Go

package web
import (
"errors"
"net/http"
"strings"
"gitea.dooplex.hu/admin/felhom-controller/internal/backup"
)
// D25 (operator ruling 2026-10-21; R-1175 + R-1181): the restore page lists the second-drive copies whose source is
// gone and lets the household release one with „Eltávolítás". Nothing else removes them.
// keptCopyRow is one line of the „Megőrzött másolatok" list.
type keptCopyRow struct {
ID string
Source string
Line string // „a(z) <drive> meghajtóról megőrzött másolat · <why>"
SizeHuman string
Since string
}
func (s *Server) keptCopyRows(lang string) []keptCopyRow {
if s.backupMgr == nil {
return nil
}
var out []keptCopyRow
for _, k := range s.backupMgr.KeptCopies() {
why := s.msgLang(lang, "kept.reason."+k.Reason)
out = append(out, keptCopyRow{
ID: k.ID,
Source: k.Source,
Line: s.msgLang(lang, "kept.from_drive", k.Drive) + " · " + why,
SizeHuman: backup.HumanizeBytes(k.SizeBytes),
Since: k.Since,
})
}
return out
}
// keptCopyRemoveHandler is „Eltávolítás": POST /backup/kept/remove (id, confirm=1). It removes ONE kept copy by its
// record (backup.RemoveKeptCopy: the recorded path, inside its copy tree, same device + inode) and nothing else.
func (s *Server) keptCopyRemoveHandler(w http.ResponseWriter, r *http.Request) {
if s.backupMgr == nil {
offboxRedirectTo(w, r, "/backups/restore", "flash.offbox.mgr_unreachable", true)
return
}
_ = r.ParseForm()
id := strings.TrimSpace(r.FormValue("id"))
if r.FormValue("confirm") != "1" {
offboxRedirectTo(w, r, "/backups/restore", "flash.kept.needs_confirmation", true)
return
}
if msg, blocked := s.restoreOpBlocked(); blocked {
s.logger.Printf("[WARN] [web] kept-copy removal refused (%s): a backup/restore op is running", id)
offboxRedirectTo(w, r, "/backups/restore", msg, true)
return
}
switch err := s.backupMgr.RemoveKeptCopy(id); {
case err == nil:
offboxRedirectTo(w, r, "/backups/restore", "flash.kept.removed", false)
case errors.Is(err, backup.ErrKeptCopyNotFound):
offboxRedirectTo(w, r, "/backups/restore", "flash.kept.not_found", true)
case errors.Is(err, backup.ErrKeptCopyChanged):
offboxRedirectTo(w, r, "/backups/restore", "flash.kept.changed", true)
default:
s.logger.Printf("[WARN] [web] kept-copy removal %s failed: %v", id, err)
offboxRedirectTo(w, r, "/backups/restore", "flash.kept.remove_failed", true, err.Error())
}
}