mirror of
https://github.com/go-admin-team/go-admin.git
synced 2026-09-23 02:40:56 +00:00
fix🐛: jsonField format check relaxed to any legal identifier
jsonFieldPattern copied businessName's rule (^[a-z][A-Za-z]+$: at least
two letters, no digits) on the theory that jsonField should tighten to
the same identifier shape. That does not hold: businessName is typed
by a person on genInfoForm.vue, so a strict pattern is a reasonable
guardrail on human input. jsonField is computed by the importer from
the column name (sys_tables.go's namelist/JsonField loop) - nobody
types it, so the same pattern only rejected names the importer
legitimately produces: a single-letter column ("x") or one whose last
segment ends in a digit ("address2", "a1") both collapse to a single
camelCase word with nothing left to re-capitalize, and both failed the
old check.
The blast radius is wider than "this one column can't be edited":
validateAndSanitizeColumns runs over every column on every Update, so
a table that merely contains one such column could not save any
config change at all, including edits with nothing to do with that
column.
Relaxed to ^[a-z][A-Za-z0-9]*$ - any legal JS/TS identifier starting
with a lowercase letter. Still rejects what has to be rejected: empty,
whitespace/punctuation, and leading-digit names, since those cannot be
unquoted object keys in the generated interface/lang file at all.
Uniqueness and the expression-content check on defaultValue are
unchanged - defaultValue is genuinely user-typed (F6's config page),
so tightening it was the right call to begin with; this was the only
place a human-input rule had been copied onto machine-generated data.
Verified against the real import path, not hand-typed jsonField values:
built a table with columns id/x/address2/a1 in a fake information_schema,
ran it through the real SysTable.Insert, confirmed the importer computes
exactly jsonField x/address2/a1, then submitted an update through the
real SysTable.Update changing only tableComment (nothing about those
columns). Confirmed red first - 500, "jsonField 格式不合法:\"x\"" - a
change unrelated to any of the three columns was rejected solely because
they existed on the table. Restored the fix - 200, "修改成功".
This commit is contained in:
@@ -10,11 +10,31 @@ import (
|
||||
"go-admin/app/other/models/tools"
|
||||
)
|
||||
|
||||
// jsonFieldPattern mirrors genInfoForm.vue's businessName rule
|
||||
// (`/^[a-z][A-Za-z]+$/`) - jsonField has never had a format rule of its own,
|
||||
// unlike businessName/tableName/className, and API契约.md §1.2 recommends
|
||||
// tightening it to the same identifier shape the other three already use.
|
||||
var jsonFieldPattern = regexp.MustCompile(`^[a-z][A-Za-z]+$`)
|
||||
// jsonFieldPattern accepts any legal JS/TS identifier that starts with a
|
||||
// lowercase letter - not businessName's rule.
|
||||
//
|
||||
// This used to be businessName's own pattern (^[a-z][A-Za-z]+$, requiring at
|
||||
// least two letters and no digits), copied over on the theory that jsonField
|
||||
// "should tighten to the same identifier shape". That theory does not hold:
|
||||
// businessName is typed by a person on genInfoForm.vue, so a strict pattern
|
||||
// is a reasonable guardrail on human input. jsonField is computed by the
|
||||
// importer from the column name (sys_tables.go's namelist/JsonField loop) -
|
||||
// nobody types it, so the same pattern only rejects names the importer
|
||||
// legitimately produces. A one-letter column ("x") or a column ending in a
|
||||
// digit ("address2", "a1") both import to a single camelCase word with no
|
||||
// separators to re-capitalize, and both used to fail this check - meaning a
|
||||
// table that merely contained such a column could never save any config
|
||||
// again, unrelated columns included, since this check runs over every
|
||||
// column on every Update.
|
||||
//
|
||||
// What still has to be rejected is a jsonField that cannot be a raw object
|
||||
// key at all: empty, containing whitespace/punctuation, or leading with a
|
||||
// digit (`2faEnabled: 1` is not valid JS - identifiers cannot start with a
|
||||
// digit, and this is what lands as the property name in gen.go's generated
|
||||
// interface / lang file, both unquoted). Hence still anchoring on a
|
||||
// lowercase letter first, but no longer requiring a second character or
|
||||
// forbidding digits after it.
|
||||
var jsonFieldPattern = regexp.MustCompile(`^[a-z][A-Za-z0-9]*$`)
|
||||
|
||||
// colWidthMin/colWidthMax are API契约.md §2.1's suggested range for colWidth.
|
||||
const (
|
||||
|
||||
@@ -17,9 +17,17 @@ func TestValidateAndSanitizeColumns_JsonFieldFormat(t *testing.T) {
|
||||
}{
|
||||
{"lower camelCase", "userName", false},
|
||||
{"two-letter lowercase", "id", false},
|
||||
// The importer's own output (sys_tables.go's namelist/JsonField
|
||||
// loop), not made up: a single-letter column ("x"), and a column
|
||||
// whose last name segment ends in a digit ("address2", "a1") both
|
||||
// produce a jsonField with no separator left to re-capitalize.
|
||||
// These three used to be rejected - the whole point of this fix.
|
||||
{"single letter, real importer output for a column named x", "x", false},
|
||||
{"letters then a trailing digit, real importer output for address2", "address2", false},
|
||||
{"two letters then a digit, real importer output for a1", "a1", false},
|
||||
{"leading underscore rejected", "_id", true},
|
||||
{"leading digit rejected", "1name", true},
|
||||
{"snake_case rejected", "user_name", true},
|
||||
{"leading digit rejected (not a legal identifier start)", "1name", true},
|
||||
{"snake_case rejected (importer never emits an underscore)", "user_name", true},
|
||||
{"dot rejected, would break the gen/{pkg}/{biz}.ts key path", "user.name", true},
|
||||
{"empty rejected", "", true},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user