controller v0.121.0: backups page truth pass — remove dead Részletek card, real Tier-3 off-box state, SQLite-honest DB messaging
MinAgent: 0.81.0 (unchanged). Controller-only; no agent-API change, no backup-engine behavior change. Fixes the self-contradicting /backups page (v0.120.0 live): - Remove the dead "Részletek" card (redundant; kills never-set Tier2DriveGroups/ ResticPassword fields + restic-pw element + toggleTier/toggleResticPw/copyResticPw JS). - Per-app "3. mentés" row shows real off-box state via pure tier3State (unconfigured/off/escrow_pending/active) — "Hamarosan" placeholder gone. - SQLite-honest DB messaging via pure dbSectionState (dumps/pending/embedded). - Populate Tier1LastRun/Tier1LastStatus from ListRestorePoints; Tier-1/Tier-2 labels via timeAgoStr (relative), confirm() dialog keeps raw timestamp. - Terminology split: "Távoli mentés (3. mentés)" (off-box, +#offbox-section anchor) vs "Távoli rendszermentés" (PBS whole-CT). - Deploy page: add "Mentési beállítások →" link. +9 internal/web tests (pure helper tables + buildAppBackupRows wiring + template renders), 4 companion red-proofs run→fail→revert.
This commit is contained in:
@@ -125,8 +125,8 @@
|
||||
|
||||
{{if .Backup}}
|
||||
<!-- Off-box (NAS) backup — Part B: encrypted restic repo over SFTP (the off-site 3-2-1 leg). -->
|
||||
<h3 class="backup-tier-divider">Külső (NAS) mentés — titkosított, off-site</h3>
|
||||
<p class="form-hint" style="margin:-0.25rem 0 1rem">Az alkalmazások adatainak + adatbázis-kiírásainak titkosított mentése a saját NAS-odra (restic, SFTP-n). A NAS csak titkosított adatot lát. Ez a 3-2-1 „1 off-site" lába — független a helyi másodpéldánytól és a teljes rendszermentéstől.</p>
|
||||
<h3 id="offbox-section" class="backup-tier-divider">Távoli mentés (3. mentés) — titkosított, offsite</h3>
|
||||
<p class="form-hint" style="margin:-0.25rem 0 1rem">Az alkalmazás-mentések titkosított másolata egy távoli tárolóra — saját NAS vagy Felhom offsite tárhely — restic + SFTP kapcsolaton. A tároló csak titkosított adatot lát. Ez a 3-2-1 szabály „1 off-site" lába — független a helyi másodpéldánytól és a teljes rendszermentéstől.</p>
|
||||
<div class="card" style="margin-bottom:1.5rem">
|
||||
{{if .Offbox}}
|
||||
<div class="stats-grid backup-page-cards">
|
||||
@@ -245,20 +245,25 @@
|
||||
{{if and .GuestBackup .GuestBackup.Offsite}}
|
||||
<div class="stat-card stat-running">
|
||||
<div class="stat-value">✓</div>
|
||||
<div class="stat-label">Távoli mentés<br><span class="relative-time">külön hardveren (PBS)</span></div>
|
||||
<div class="stat-label">Távoli rendszermentés<br><span class="relative-time">külön hardveren (PBS)</span></div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="stat-card" style="border-left-color: var(--text-3);">
|
||||
<div class="stat-value" style="background:var(--text-3);-webkit-background-clip:text;background-clip:text;">–</div>
|
||||
<div class="stat-label">Távoli mentés<br><span class="relative-time">nincs beállítva</span></div>
|
||||
<div class="stat-label">Távoli rendszermentés<br><span class="relative-time">nincs beállítva</span></div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="stat-card stat-total">
|
||||
{{if eq .DBSectionState "embedded"}}
|
||||
<div class="stat-value">–</div>
|
||||
<div class="stat-label">Adatbázis mentve<br><span class="relative-time">beágyazott DB-k a kötetmentésben</span></div>
|
||||
{{else}}
|
||||
<div class="stat-value">
|
||||
{{if .Backup.LastDBDump}}{{len .Backup.LastDBDump.Results}}{{else}}{{len .Backup.DumpFiles}}{{end}}
|
||||
</div>
|
||||
<div class="stat-label">Adatbázis mentve</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -360,8 +365,10 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{else if eq .DBSectionState "pending"}}
|
||||
<div class="backup-table-empty">Még nem készült adatbázis-mentés — az első ütemezett mentés éjjel fut le.</div>
|
||||
{{else}}
|
||||
<div class="backup-table-empty">Nem található adatbázis mentés.</div>
|
||||
<div class="backup-table-empty">A telepített alkalmazások beágyazott adatbázist használnak (pl. SQLite) — adatbázisuk a fájl- és kötetmentés része, külön adatbázis-kiírás nem szükséges.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
@@ -406,7 +413,7 @@
|
||||
<span class="layer-badge">Auto</span>
|
||||
<span class="tier-location">helyi</span>
|
||||
{{if .Tier1LastRun}}
|
||||
<span class="layer-last">Utolsó: {{.Tier1LastRun}}
|
||||
<span class="layer-last">Utolsó: {{timeAgoStr .Tier1LastRun}}
|
||||
{{if eq .Tier1LastStatus "ok"}}<span class="text-ok"><svg class="ico ico-sm"><use href="#i-check"/></svg></span>
|
||||
{{else if eq .Tier1LastStatus "error"}}<span class="text-error"><svg class="ico ico-sm"><use href="#i-x"/></svg></span>{{end}}
|
||||
</span>
|
||||
@@ -429,7 +436,7 @@
|
||||
<span class="layer-dest" style="opacity:.6">→ {{.Tier2Dest}}</span>
|
||||
<span class="tag tag-warn">Cél meghajtó leválasztva</span>
|
||||
{{if .Tier2LastRun}}
|
||||
<span class="layer-last" style="opacity:.6">Utolsó: {{.Tier2LastRun}}</span>
|
||||
<span class="layer-last" style="opacity:.6">Utolsó: {{timeAgoStr .Tier2LastRun}}</span>
|
||||
{{end}}
|
||||
<span class="tier-contents" style="opacity:.6">{{.BackupContents}}</span>
|
||||
<div class="layer-actions">
|
||||
@@ -440,7 +447,7 @@
|
||||
<span class="layer-dest" style="opacity:.6">→ {{.Tier2Dest}}</span>
|
||||
<span class="tag tag-warn">Cél meghajtó inaktív</span>
|
||||
{{if .Tier2LastRun}}
|
||||
<span class="layer-last" style="opacity:.6">Utolsó: {{.Tier2LastRun}}</span>
|
||||
<span class="layer-last" style="opacity:.6">Utolsó: {{timeAgoStr .Tier2LastRun}}</span>
|
||||
{{end}}
|
||||
<span class="tier-contents" style="opacity:.6">{{.BackupContents}}</span>
|
||||
<div class="layer-actions">
|
||||
@@ -451,7 +458,7 @@
|
||||
<span class="layer-dest">→ {{.Tier2Dest}}</span>
|
||||
<span class="layer-schedule">{{.Tier2Schedule}}</span>
|
||||
{{if .Tier2LastRun}}
|
||||
<span class="layer-last">Utolsó: {{.Tier2LastRun}}
|
||||
<span class="layer-last">Utolsó: {{timeAgoStr .Tier2LastRun}}
|
||||
<span class="{{if eq .Tier2LastStatus "ok"}}text-ok{{else if eq .Tier2LastStatus "error"}}text-error{{else if eq .Tier2LastStatus "running"}}text-muted{{end}}">
|
||||
{{.Tier2StatusBadge}}
|
||||
</span>
|
||||
@@ -480,13 +487,41 @@
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<!-- Tier 3: Remote backup (future) -->
|
||||
<!-- Tier 3: Off-box (NAS) backup — real state (see tier3State). -->
|
||||
{{if eq .Tier3State "active"}}
|
||||
<div class="backup-layer-row">
|
||||
<span class="tier-label">3. mentés</span>
|
||||
<span class="layer-badge {{if eq $.Offbox.LastStatus "ok"}}text-ok{{else if eq $.Offbox.LastStatus "error"}}text-error{{else if eq $.Offbox.LastStatus "running"}}text-muted{{end}}">{{if eq $.Offbox.LastStatus "ok"}}Sikeres{{else if eq $.Offbox.LastStatus "error"}}Hiba{{else if eq $.Offbox.LastStatus "running"}}Fut...{{else}}—{{end}}</span>
|
||||
<span class="tier-location">restic → {{$.Offbox.Host}}</span>
|
||||
{{if $.Offbox.LastRun}}<span class="layer-last">Utolsó: {{timeAgoStr $.Offbox.LastRun}}</span>{{end}}
|
||||
<span class="tier-contents">Helyreállítási egység, titkosítva</span>
|
||||
</div>
|
||||
{{else if eq .Tier3State "escrow_pending"}}
|
||||
<div class="backup-layer-row">
|
||||
<span class="tier-label">3. mentés</span>
|
||||
<span class="layer-badge text-error">Kulcsletétre vár</span>
|
||||
<span class="tier-contents">A távoli mentés a titkosítási kulcs letétbe helyezéséig szünetel</span>
|
||||
</div>
|
||||
{{else if eq .Tier3State "off"}}
|
||||
<div class="backup-layer-row" style="opacity:.5">
|
||||
<span class="tier-label">3. mentés</span>
|
||||
<span class="layer-badge" style="background:var(--bg-2);color:var(--text-3)">Hamarosan</span>
|
||||
<span class="tier-location">távoli (offsite)</span>
|
||||
<span class="tier-contents" style="font-style:normal;color:var(--text-3)">B2 / S3 / SFTP — hamarosan elérhető</span>
|
||||
<span class="layer-badge">Kikapcsolva</span>
|
||||
<span class="tier-contents">Ez az alkalmazás nincs kijelölve távoli mentésre</span>
|
||||
<div class="layer-actions">
|
||||
<a href="#offbox-section" class="btn btn-xs btn-outline">Bekapcsolás</a>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="backup-layer-row" style="opacity:.5">
|
||||
<span class="tier-label">3. mentés</span>
|
||||
<span class="layer-badge" style="background:var(--bg-2);color:var(--text-3)">Nincs beállítva</span>
|
||||
<span class="tier-location">távoli (offsite)</span>
|
||||
<span class="tier-contents">Nincs távoli mentési cél beállítva</span>
|
||||
<div class="layer-actions">
|
||||
<a href="#offbox-section" class="btn btn-xs btn-outline">Beállítás</a>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .Warnings}}
|
||||
<div class="layer-warnings">
|
||||
@@ -502,78 +537,6 @@
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<!-- Section 6: Részletek (Details) -->
|
||||
<div class="repo-card">
|
||||
<h3>Részletek</h3>
|
||||
|
||||
<!-- Tier 1: Helyi mentés (collapsible, open by default) -->
|
||||
<div class="details-tier">
|
||||
<div class="details-tier-header" onclick="toggleTier(this)">
|
||||
<span class="expand-icon">▼</span>
|
||||
<h4 class="repo-tier-title">1. szint — Helyi mentés (adatbázis + konfiguráció)</h4>
|
||||
</div>
|
||||
<div class="details-tier-body">
|
||||
<div class="repo-info-rows" style="margin-top:0.5rem">
|
||||
<div class="repo-info-row">
|
||||
<span class="repo-label">Adatbázis mentések:</span>
|
||||
<span class="repo-value">{{if .Backup.DumpFiles}}{{len .Backup.DumpFiles}} dump fájl{{if gt .DBDumpTotalBytes 0}} — {{fmtBytes .DBDumpTotalBytes}}{{end}}{{else}}Nincs dump fájl{{end}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Encryption key -->
|
||||
{{if $.ResticPassword}}
|
||||
<div class="repo-encryption">
|
||||
<span class="repo-label">Titkosítási kulcs:</span>
|
||||
<div class="repo-encryption-row">
|
||||
<input type="password" id="restic-pw" class="restic-pw-field mono" value="{{$.ResticPassword}}" readonly>
|
||||
<button type="button" class="btn btn-sm" onclick="toggleResticPw()">Megjelenítés</button>
|
||||
<button type="button" class="btn btn-sm" onclick="copyResticPw()">Másolás</button>
|
||||
</div>
|
||||
<div class="repo-encryption-warn">
|
||||
Mentse el biztonságos helyre! A kulcs nélkül a biztonsági mentések NEM állíthatók vissza.
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 2: Másodlagos másolat (collapsible, collapsed by default) -->
|
||||
<div class="details-tier">
|
||||
<div class="details-tier-header" onclick="toggleTier(this)">
|
||||
<span class="expand-icon">▶</span>
|
||||
<h4 class="repo-tier-title">2. szint — Másodlagos másolat</h4>
|
||||
</div>
|
||||
<div class="details-tier-body" style="display:none">
|
||||
{{if .Tier2DriveGroups}}
|
||||
{{range .Tier2DriveGroups}}
|
||||
<div class="drive-detail-card">
|
||||
<div class="drive-detail-header">{{.DestLabel}} <span class="relative-time mono">({{.DestPath}})</span></div>
|
||||
{{range .Items}}
|
||||
<div class="repo-info-row">
|
||||
<span class="repo-label">{{.DisplayName}}</span>
|
||||
<span class="repo-value">{{if .SizeHuman}}{{.SizeHuman}}{{else}}—{{end}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<div class="tier-empty-state">Nincs 2. szintű mentés konfigurálva.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 3: Távoli mentés (collapsible, collapsed by default, placeholder) -->
|
||||
<div class="details-tier">
|
||||
<div class="details-tier-header" onclick="toggleTier(this)">
|
||||
<span class="expand-icon">▶</span>
|
||||
<h4 class="repo-tier-title" style="opacity:.6">3. szint — Távoli mentés (offsite)</h4>
|
||||
</div>
|
||||
<div class="details-tier-body" style="display:none">
|
||||
<div class="tier-empty-state">B2 / S3 / SFTP — hamarosan elérhető</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section 7: Restore -->
|
||||
{{if .Backup.AppDataInfo}}
|
||||
<div class="backup-section-card">
|
||||
@@ -671,18 +634,6 @@ function toggleBackupDetail(header) {
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTier(header) {
|
||||
var body = header.nextElementSibling;
|
||||
var icon = header.querySelector('.expand-icon');
|
||||
if (body.style.display === 'none') {
|
||||
body.style.display = 'block';
|
||||
icon.textContent = '▼';
|
||||
} else {
|
||||
body.style.display = 'none';
|
||||
icon.textContent = '▶';
|
||||
}
|
||||
}
|
||||
|
||||
function triggerBackupFromPage() {
|
||||
const btn = document.getElementById('backup-page-btn');
|
||||
btn.disabled = true;
|
||||
@@ -756,20 +707,6 @@ function pollGuestBackup(out, btn) {
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// Restic password toggle/copy
|
||||
function toggleResticPw() {
|
||||
var el = document.getElementById('restic-pw');
|
||||
el.type = el.type === 'password' ? 'text' : 'password';
|
||||
}
|
||||
function copyResticPw() {
|
||||
var el = document.getElementById('restic-pw');
|
||||
navigator.clipboard.writeText(el.value).then(function() {
|
||||
var btn = event.target;
|
||||
btn.textContent = 'Másolva!';
|
||||
setTimeout(function() { btn.textContent = 'Másolás'; }, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
// Restore section
|
||||
var huDays = ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'];
|
||||
function formatSnapshot(s) {
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
<div class="cross-drive-nightly">
|
||||
<span class="form-hint" style="display:block;margin-top:.25rem">
|
||||
Az alkalmazás adatbázisa és Docker kötetei automatikusan bekerülnek az éjszakai biztonsági mentésbe.
|
||||
<a href="/backups" style="color:var(--blue)">Mentési állapot →</a>
|
||||
<a href="/backups" style="color:var(--blue)">Mentési állapot →</a> · <a href="/stacks/{{.Stack.Name}}/backup" style="color:var(--blue)">Mentési beállítások →</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user