Agreed with the owner on 2026-10-13, taken up on 2026-10-16 ("Да"); the
mockup is 1888dce. Both secret downloads - the full backup on Server ›
Backup and a domain's export on its settings - ask for "Your account
password": reauth (handlers_backup.go) checks the signed-in user's own
password with bcrypt, as a password change does, under the same limiter
(auth.AllowPasswordChange: ten in fifteen minutes per user, shared with the
Account form). A wrong or missing one is 401 on the same page with "Your
account password is incorrect.", logged; nothing is sent. The import and
the selfpost-backup CLI are not asked.
Also, the owner's phone screenshot of 2026-10-16 ("кнопка выбора файла не
такая, как в макете. Это косяк?"): the import's file field was a bare
<input type="file"> drawn by the browser ("Browse…"), where the mockup has
Bulma's .file - "Choose a file…" and the name chosen. The template now
follows the mockup; panel.js writes the name into .file-name on change and
at load (testdata/filename_test.js, run by TestPanelJS). No other file
field exists.
Tests: TestSecretDownloadsAskForTheAccountPassword (missing, wrong, right,
the limiter), the export refusals of the settings page with the password,
cmd/panel's restore tests and e2e's backups with it, e2e's refusal of a
backup without and with a wrong password. go vet + go test (26 packages)
and make e2e on the test server for this tree.
Docs: security.md § Backup and domain export, guide § Full backup and
restore, help (word for word with the mockup); CHANGELOG [Unreleased];
roadmap row done.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
29 lines
902 B
Go
29 lines
902 B
Go
package view
|
|
|
|
import (
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// panel.js run in node against a stand-in for the parts of the DOM and htmx
|
|
// it uses (testdata/*_test.js): the refreshes of the monitoring boxes
|
|
// survive a failure and back off (audit 2026-10-12, M11), and a button that
|
|
// leaves the page asks first when a field holds an unsaved edit (L19).
|
|
// Skipped where node is not installed - the test server's Go has none; the
|
|
// workstation runs it.
|
|
func TestPanelJS(t *testing.T) {
|
|
node, err := exec.LookPath("node")
|
|
if err != nil {
|
|
t.Skip("node is not installed")
|
|
}
|
|
for _, script := range []string{"poll_test.js", "unsaved_test.js", "filename_test.js"} {
|
|
t.Run(script, func(t *testing.T) {
|
|
out, err := exec.Command(node, filepath.Join("testdata", script), filepath.Join("static", "panel.js")).CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("%v\n%s", err, out)
|
|
}
|
|
})
|
|
}
|
|
}
|