8dbbc98ff2
gates / gates (push) Successful in 18s
R-249. settings_security.html rendered the passphrase into a display:none span behind a Megjelenit button. That toggle stops a browser DRAWING the value and nothing else — the plaintext was in the response body of every render, so a curl of the page returned it. Found by exactly that: it landed in a session transcript while driving the documented rebuild path. The codebase already stated this rule for the recovery code and this page did not follow it (escrow_handlers.go: 'reveal (claim XHR only — R is NEVER templated server-side into HTML)'). The page now carries only HasRetrievalPassword; the value comes from POST /settings/retrieval-password/reveal — CSRF-covered because POST, no-store, and LOGGED as an act, which reading it off the markup never was. The tests assert the RAW RESPONSE BODY. Every test that asked what the customer sees passed while the bytes carried the secret; that is why this survived. Census: the render-then-hide pattern appears twice more — app_info.html (a real per-install app password in a hidden span) and deploy.html. Filed as R-254, NOT fixed here. R-252. A rebuilt box keeps its drives but loses their REGISTRATION. The restore page now states that before the customer presses anything, says the backups and drives are both still there, and links to Tarhely > Meghajtok. Page and resolver ask ONE question — HasRestoreDestination() reads the same GetSchedulableStoragePaths() the scratch resolver reads. R-253. The list promised 'a visszaallitas elobb ujratelepiti' three lines above a refusal that fired BECAUSE the app was not installed. The promise was the wrong half: reconstitution writes to the app's own GetStackHDDPath, which exists only once the CUSTOMER has chosen a drive at deploy time. Auto-reinstalling would mean the product making that choice for them. Copy now says to install first and routes to /stacks/<app>/deploy. Both notices are conditional — a healthy box renders as before, pinned by a test that fails if either becomes unconditional.
94 lines
4.7 KiB
Go
94 lines
4.7 KiB
Go
package web
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// R-252 / R-253 — A REFUSAL ON THE RECOVERY PATH NAMES A REASON A PERSON CAN ACT ON, AND THE WAY TO
|
|
// ACT ON IT.
|
|
//
|
|
// Both of these were met on the fifth walk (2026-08-07) at the LAST step of a successful recovery —
|
|
// the customer had entered their recovery code, seen their data listed, and pressed through. Neither
|
|
// needed a shell to clear, which is why the walk's journey half passed; both required knowing
|
|
// something the product never said, which is why they are filed.
|
|
//
|
|
// These assert the RENDERED page, not the state that feeds it: the defect in both cases was copy
|
|
// that disagreed with behaviour, and only the rendered bytes can show that.
|
|
|
|
// restoreData is the healthy fixture — app in the store, installed here, drives registered. Every
|
|
// test below overlays exactly one field, so what it proves is attributable.
|
|
func restoreData() map[string]interface{} {
|
|
d := splitTestData()
|
|
d["NoRestoreDestination"] = false
|
|
d["OffsiteRestoreRows"] = []OffsiteRestoreRow{
|
|
{App: "calibre-web", DisplayName: "Calibre-Web", InStore: true, Installed: true, Enabled: true},
|
|
}
|
|
return d
|
|
}
|
|
|
|
// ── SCENARIO C — a refusal for a missing drive says what to do ──────────────────────────────────
|
|
|
|
// RED-PROOF: restore the old copy — delete the `{{if .NoRestoreDestination}}` block from
|
|
// backups_restore.html — and this fails on both assertions: the customer is left with a page that
|
|
// looks normal and a button that will refuse with a message naming no next step.
|
|
func TestRestorePage_NoRegisteredDrive_NamesTheReasonAndTheRoute(t *testing.T) {
|
|
d := restoreData()
|
|
d["NoRestoreDestination"] = true
|
|
html := renderBackupPage(t, "backups_restore", d)
|
|
|
|
if !strings.Contains(html, "csatold vissza az adatmeghajtót") {
|
|
t.Error("R-252: the restore page says nothing about the drives being unregistered — the " +
|
|
"customer presses through and gets a refusal that names no next step")
|
|
}
|
|
if !strings.Contains(html, `href="/storage"`) {
|
|
t.Error("R-252: the notice does not ROUTE to the place that fixes it — a reason without a " +
|
|
"route is what made this an obstacle rather than a message")
|
|
}
|
|
// It must say the data is safe. „nincs elérhető adatmeghajtó" reads like data loss; it is not.
|
|
if !strings.Contains(html, "megvannak") {
|
|
t.Error("R-252: the notice does not say the backups and the drives are both still there")
|
|
}
|
|
}
|
|
|
|
// ── SCENARIO E — a healthy box is unchanged ─────────────────────────────────────────────────────
|
|
|
|
// RED-PROOF: make the notice unconditional (drop the `{{if .NoRestoreDestination}}` guard) and this
|
|
// fails — a box with every precondition satisfied is warned about a problem it does not have, which
|
|
// is the R-215 shape (a screen about a situation the customer is not in).
|
|
func TestRestorePage_HealthyBox_HasNoPreconditionNotice(t *testing.T) {
|
|
html := renderBackupPage(t, "backups_restore", restoreData())
|
|
|
|
if strings.Contains(html, "csatold vissza az adatmeghajtót") {
|
|
t.Error("the drive notice rendered on a box whose drives ARE registered")
|
|
}
|
|
if strings.Contains(html, "előbb") && strings.Contains(html, "telepítsd újra") {
|
|
t.Error("the not-installed copy rendered for an app that IS installed")
|
|
}
|
|
}
|
|
|
|
// ── SCENARIO D — the page and the handler agree about reinstalling ──────────────────────────────
|
|
|
|
// RED-PROOF: restore the old string „Nincs telepítve — a visszaállítás előbb újratelepíti." and this
|
|
// fails on the first assertion — the page promises a reinstall the reconstitute path refuses to do,
|
|
// which is the contradiction R-253 filed.
|
|
func TestRestorePage_NotInstalled_DoesNotPromiseAReinstall(t *testing.T) {
|
|
d := restoreData()
|
|
d["OffsiteRestoreRows"] = []OffsiteRestoreRow{
|
|
{App: "calibre-web", DisplayName: "Calibre-Web", InStore: true, Installed: false, Enabled: true},
|
|
}
|
|
html := renderBackupPage(t, "backups_restore", d)
|
|
|
|
if strings.Contains(html, "a visszaállítás előbb újratelepíti") {
|
|
t.Error("R-253: the page still promises that the restore reinstalls the app — the " +
|
|
"reconstitute path refuses precisely because it is not installed, and cannot deploy it " +
|
|
"itself (the destination is the app's own HDD path, a drive the CUSTOMER chooses)")
|
|
}
|
|
if !strings.Contains(html, "telepítsd újra") {
|
|
t.Error("R-253: the page no longer tells the customer to install the app first")
|
|
}
|
|
if !strings.Contains(html, `href="/stacks/calibre-web/deploy"`) {
|
|
t.Error("R-253: the copy names the step but does not route to it")
|
|
}
|
|
}
|