Files
felhom-controller/controller/internal/web/app_export_domain_test.go
T
admin 2487681396 style: gofmt normalization — no logic changes
gofmt -w across the controller tree (46 files) so gofmt -l is empty — disarms the
formatting landmine where a targeted edit + accidental gofmt -w swept ~46 unrelated
files. Pure formatting: whitespace + gofmt's optional-semicolon removal in reflowed
inline closures. One doc comment reworded ('' -> 'the empty string') to avoid gofmt's
Go-1.19 doc-comment typographic substitition ('' -> curly quote) muddying its meaning.
No build/vet/test behavior change.
2026-07-25 07:37:02 +02:00

77 lines
2.9 KiB
Go

package web
import (
"strings"
"testing"
"gitea.dooplex.hu/admin/felhom-controller/internal/stacks"
)
// R-53 / F7: app_export.html built the app's public URL as `<subdomain>.{{$.CSRFToken}}` — the
// session CSRF token substituted where the customer domain belongs. That is two defects in one
// token: the „open in browser" link is wrong for every app that has a subdomain, and a CSRF token
// lands in a URL (history, referrers, logs). The correct CSRF usage on this page is the csrfH()
// helper reading the meta tag, which is untouched.
const exportTestToken = "deadbeefcafebabedeadbeefcafebabedeadbeefcafebabedeadbeefcafebabe"
// exportScriptLine returns the `var domain = …` line, so an assertion cannot accidentally match the
// token where it legitimately appears (the meta tag) elsewhere on the page.
func exportScriptLine(t *testing.T, html string) string {
t.Helper()
for _, ln := range strings.Split(html, "\n") {
if strings.Contains(ln, "var domain =") {
return ln
}
}
t.Fatalf("no `var domain =` line in the rendered export page")
return ""
}
func renderExport(t *testing.T, subdomain string) string {
t.Helper()
return renderBackupPage(t, "app_export", map[string]interface{}{
"Stack": stacks.Stack{
Name: "immich", Deployed: true,
Meta: stacks.Metadata{Slug: "immich", DisplayName: "Immich", Subdomain: subdomain},
},
"Drives": nil,
"Domain": "demo-felhom.eu",
"CSRFToken": exportTestToken,
"CSRFField": "",
"Page": "apps",
"Title": "Export",
"ExportPage": true,
})
}
// Scenario C — the domain is joined from the CUSTOMER DOMAIN, and the CSRF token appears nowhere in
// that line. COMPANION red-proof: restore `{{$.CSRFToken}}` in app_export.html's `var domain` line
// → both assertions FAIL. Run → fail → revert (recorded in REPORT).
func TestAppExportDomainUsesCustomerDomainNotCSRFToken(t *testing.T) {
line := exportScriptLine(t, renderExport(t, "photos"))
if !strings.Contains(line, "'photos.demo-felhom.eu'") {
t.Errorf("export link must be built from the customer domain, got: %s", line)
}
if strings.Contains(line, exportTestToken) {
t.Errorf("the CSRF token must NEVER appear in the export URL, got: %s", line)
}
}
// The empty-subdomain branch still yields the empty string — an app without a subdomain must not get
// a link to a bare domain (the truthiness guard is what produces that, and the fix must not disturb it).
func TestAppExportDomainEmptyWithoutSubdomain(t *testing.T) {
line := exportScriptLine(t, renderExport(t, ""))
if !strings.Contains(line, "''") {
t.Errorf("no subdomain must yield an empty domain, got: %s", line)
}
if strings.Contains(line, "demo-felhom.eu'") && !strings.Contains(line, "'' ? ") {
t.Errorf("no subdomain must not produce a bare-domain link, got: %s", line)
}
if strings.Contains(line, exportTestToken) {
t.Errorf("the CSRF token must NEVER appear in the export URL, got: %s", line)
}
}