fix(17): T-17-15 refuse an unsafe frontend_url on save and import

- Settings.BeforeValidate answers a cabana validation error on
  frontend_url, so the settings save is a 422 and the row is unchanged
- sitemap:import-winter stops on a frontend_url that
  models.AllowedFrontendURL refuses, before the dry-run branch and before
  any database use; the value is printed quoted
- errors.frontend_url phrase in en and pl
- TestSettingsBeforeValidate, TestWinterSettingsFrontendURL and the save
  and import refusals in the Postgres smokes
This commit is contained in:
Jakub Zych
2026-10-13 00:59:24 +02:00
parent b9804ddf17
commit 1bb89ce006
9 changed files with 204 additions and 8 deletions

View File

@@ -1,11 +1,18 @@
package models_test
import (
"errors"
"reflect"
"testing"
"git.golem15.com/golem15/sm-sitemap-plugin/models"
"git.golem15.com/golem15/summercms/modules/cabana"
"git.golem15.com/golem15/summercms/modules/lagoon"
)
// cabana calls the hook on a settings save through this interface.
var _ lagoon.HasBeforeValidate = (*models.Settings)(nil)
// TestAllowedFrontendURL pins the one definition of a frontend_url that may
// be saved, imported and applied (T-17-15): empty, or an absolute http(s)
// URL with a host and without whitespace, control characters, a double
@@ -59,3 +66,32 @@ func TestAllowedFrontendURL(t *testing.T) {
}
}
}
// TestSettingsBeforeValidate pins the save check of T-17-15: the hook cabana
// calls on a settings save passes a null, empty or accepted frontend_url and
// answers a validation error keyed frontend_url for any other value.
func TestSettingsBeforeValidate(t *testing.T) {
text := func(s string) *string { return &s }
for _, url := range []*string{nil, text(""), text("https://www.ex.pl/")} {
if err := (&models.Settings{FrontendURL: url}).BeforeValidate(nil); err != nil {
t.Errorf("BeforeValidate(%q) = %v, want nil", models.Text(url), err)
}
}
want := map[string]any{"frontend_url": []string{"golem15.sitemap::lang.errors.frontend_url"}}
for _, url := range []string{
"javascript:alert(document.domain)//",
`https://x"/><y a="`,
"0",
" https://www.ex.pl",
} {
err := (&models.Settings{FrontendURL: &url}).BeforeValidate(nil)
var invalid *cabana.ValidationError
if !errors.As(err, &invalid) {
t.Errorf("BeforeValidate(%q) = %v, want a *cabana.ValidationError", url, err)
continue
}
if !reflect.DeepEqual(invalid.Details, want) {
t.Errorf("BeforeValidate(%q) details = %v, want %v", url, invalid.Details, want)
}
}
}