Permitted provides character-level whitelisting and length constraints for string validation. It is embedded in the Field struct and forms the basis of field-level validation rules.
The Permitted type enables positive whitelisting — only explicitly enabled characters pass validation. This approach provides inherent XSS protection when used with standard widgets.
type Permitted struct {
Letters bool // a-z, A-Z, ñ, Ñ
Tilde bool // á, é, í, ó, ú (and uppercase) — uses AL/AU from fmt/mapping.go
Numbers bool // 0-9
Spaces bool // ' '
BreakLine bool // '\n'
Tab bool // '\t'
Extra []rune // additional allowed characters (e.g., '@', '.', '-')
NotAllowed []string // forbidden substrings
Minimum int // min length (0 = no limit)
Maximum int // max length (0 = no limit)
StartWith *Permitted // rules for first character (nil = same as main rules)
}Only characters that match enabled flags are allowed. This is a positive whitelist — no character passes unless explicitly enabled.
| Flag | Characters |
|---|---|
Letters |
a-z, A-Z, ñ, Ñ |
Tilde |
á, à, ã, â, ä, é, è, ê, ë, í, ì, î, ï, ó, ò, õ, ô, ö, ú, ù, û, ü, ý (and uppercase) |
Numbers |
0-9 |
Spaces |
' ' (space character) |
BreakLine |
'\n' (newline) |
Tab |
'\t' (tab) |
Minimum: Enforced if > 0 (measured in runes, not bytes)Maximum: Enforced if > 0 (measured in runes, not bytes)
If only Minimum/Maximum are set (no character flags), validation only checks length and never rejects characters.
Extra: Array of additional allowed characters (e.g.,[]rune{'@', '.', '-'}for email-like strings)NotAllowed: Array of forbidden substrings (checked anywhere in the string)StartWith: OptionalPermittedrules for the first character only; ifnil, uses main rules
HTML-dangerous characters (<, >, &, ", ') are not included in any standard widget's whitelist. This means data validated through standard widgets is safe for HTML output without additional escaping at the output layer.
If custom code adds dangerous chars to Extra, it must:
- Document the XSS risk
- Ensure proper output encoding (e.g., via
fmt.Convert(v).EscapeHTML())
Checks that text conforms to the permitted rules. Validation order: length → forbidden substrings → start-with → characters.
func (p Permitted) Validate(field, text string) errorReturns nil if valid, or an error describing the first validation failure.
Creates a copy with HTML-dangerous characters (<, >, &, ", ') added to NotAllowed as an explicit safety layer.
p := model.Permitted{Letters: true, Extra: []rune{'@'}}.NoHTML()
// Now rejects: < > & " 'Use when custom Extra characters could appear in HTML injection attempts.
model.Permitted{
Letters: true,
Spaces: true,
Minimum: 1,
Maximum: 100,
}Allows: letters, spaces, 1-100 runes.
model.Permitted{
Letters: true,
Numbers: true,
Extra: []rune{'@', '.', '-'},
Minimum: 5,
}Allows: letters, numbers, @, ., -, min 5 runes. Safe for HTML output.
model.Permitted{
Numbers: true,
Extra: []rune{'-', '+'},
Minimum: 1,
Maximum: 10,
}Allows: digits, -, +, 1-10 runes. (Typical for phone or numeric ID).
model.Permitted{
Numbers: true,
Extra: []rune{'-', '(', ')'},
StartWith: &model.Permitted{
Numbers: true, // First char must be a digit
},
}Allows: digits, -, (, ) anywhere, but first char must be a digit.
model.Permitted{
Letters: true,
Spaces: true,
NotAllowed: []string{"admin", "root", "system"},
}Allows: letters and spaces, but rejects if the string contains "admin", "root", or "system".
Permitted is embedded in Field:
type Field struct {
Name string
Type FieldType
NotNull bool
OmitEmpty bool
Widget Widget
DB *FieldDB
Permitted // embedded
}When Field.Validate(value) is called:
- NotNull check (if enabled)
- Widget.Validate() call (if set)
- Length check (via
Permitted.validateLength) - Character and substring validation (via
Permitted.validateChars)
The order ensures widget-level validation runs before character-level rules.
- Zero allocations: Uses ASCII ranges and slice lookups, not maps or regex.
- Early termination: Stops at first validation failure.
- Rune counting: Uses range iteration (single pass) without importing
unicode/utf8.
type RoleGrant struct {
Role RoleCode
Grant Grant
}
type PolicyDescriber interface {
Grants() []RoleGrant
}
func RolesFor(p PolicyDescriber, r Resource, a Action) []RoleCodeRoleGrant es el par en que una política se declara y en que la introspección la lee de
vuelta. PolicyDescriber lo expone quien posee el Authorizer cuando puede enumerar lo
que concede. RolesFor es su inversa sobre un slice de grants: devuelve los roles que
conceden (r, a) en el orden de declaración de la política y sin repeticiones; nil si
p == nil ("desconocido", no "nadie"); vacío si ningún rol lo tiene — el hallazgo que
esta API existe para reportar (ruta muerta con 403 permanente).
- Field and Fielder API for how
Permittedintegrates into schema validation webtyp/fmtforPermittedsource and character mapping (AL/AU tables)