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

@@ -5,8 +5,14 @@ import (
"strings"
"unicode"
"unicode/utf8"
"git.golem15.com/golem15/summercms/modules/cabana"
"gorm.io/gorm"
)
// errFrontendURL is the phrase key of the frontend_url refusal.
const errFrontendURL = "golem15.sitemap::lang.errors.frontend_url"
// The settings keys of the five priority tiers, in the order PHP checked
// them. A tier rule names one of them.
const (
@@ -34,6 +40,8 @@ var PriorityDefaults = map[string]string{
// UpdatesManifestPath names a JSON file of URL path to last-modified date;
// EnablePriorityTiers turns the tier priorities on, and the priority fields
// hold each tier's value as text. A null priority reads as its PHP default.
// The PHP settings form validated nothing; the port checks FrontendURL in
// BeforeValidate.
type Settings struct {
ID uint `gorm:"column:id;primaryKey"`
FrontendURL *string `gorm:"column:frontend_url"`
@@ -58,9 +66,21 @@ func (Settings) Fillable() []string {
}
}
// Rules is empty: the PHP settings form validated nothing.
// Rules is empty: the PHP settings form validated nothing. The one check of
// the port, on frontend_url, is in BeforeValidate.
func (Settings) Rules() map[string]string { return map[string]string{} }
// BeforeValidate is the lagoon.HasBeforeValidate hook cabana calls on a
// settings save, after the fill and before the row is written: a
// frontend_url that AllowedFrontendURL refuses is a validation error on
// frontend_url, so the save answers 422 and the row is left as it was.
func (s Settings) BeforeValidate(*gorm.DB) error {
if AllowedFrontendURL(Text(s.FrontendURL)) {
return nil
}
return &cabana.ValidationError{Details: map[string]any{"frontend_url": []string{errFrontendURL}}}
}
// AllowedFrontendURL reports whether u may be the frontend_url setting: the
// empty string, or an absolute http or https URL with a host and without
// whitespace, control characters, a double quote, <, > or &. The PHP plugin