feat(lagoon): check min and max as character length on string and url fields (quick-261104-f4x)
- on a string or url field that is not numeric or integer, min and max compare utf8.RuneCountInString (Laravel's mb_strlen) and answer with the lagoon::validation min.string / max.string messages - a min or max argument that is not a whole number is the unrecognized-rule error, whatever the value - rule strings without string or url keep their results (pinned by a test); between is unchanged
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"git.golem15.com/golem15/summercms/modules/phrasebook"
|
||||
"github.com/go-playground/validator/v10"
|
||||
@@ -118,6 +119,20 @@ func validateField(ctx context.Context, tx *gorm.DB, model any, field, rule stri
|
||||
return nil, fmt.Errorf("lagoon: unrecognized validation rule %q", tok)
|
||||
}
|
||||
}
|
||||
// On a string or url field min and max are a length in characters. A
|
||||
// malformed bound fails loudly whatever the value, so a typo in Rules()
|
||||
// cannot disable the limit unnoticed.
|
||||
lengthRange := (hasString || hasURL) && !hasNumeric && !hasInteger
|
||||
minLen, maxLen := -1, -1
|
||||
if lengthRange {
|
||||
var err error
|
||||
if minLen, err = lengthBound("min", minArg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if maxLen, err = lengthBound("max", maxArg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if nullable && isEmptyValue(val) && !required {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -173,6 +188,16 @@ func validateField(ctx context.Context, tx *gorm.DB, model any, field, rule stri
|
||||
if hasURL && (!isStr || !urlPattern.MatchString(s)) {
|
||||
msgs = append(msgs, validateMessage(ctx, tr, "url", field, nil))
|
||||
}
|
||||
if lengthRange && isStr {
|
||||
n := utf8.RuneCountInString(s)
|
||||
params := map[string]string{"min": minArg, "max": maxArg}
|
||||
if minLen >= 0 && n < minLen {
|
||||
msgs = append(msgs, validateMessage(ctx, tr, "min.string", field, params))
|
||||
}
|
||||
if maxLen >= 0 && n > maxLen {
|
||||
msgs = append(msgs, validateMessage(ctx, tr, "max.string", field, params))
|
||||
}
|
||||
}
|
||||
if len(msgs) > 0 {
|
||||
return msgs, nil
|
||||
}
|
||||
@@ -350,6 +375,19 @@ func isIntegerValue(val any) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// lengthBound parses a min or max argument used as a character length; an
|
||||
// absent one is -1 and a malformed one the unrecognized-rule error.
|
||||
func lengthBound(name, arg string) (int, error) {
|
||||
if arg == "" {
|
||||
return -1, nil
|
||||
}
|
||||
n, err := strconv.Atoi(strings.TrimSpace(arg))
|
||||
if err != nil || n < 0 {
|
||||
return -1, fmt.Errorf("lagoon: unrecognized validation rule %q", name+":"+arg)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// ruleString answers the string a string or url rule checks: it
|
||||
// dereferences pointers and interfaces (a nil one is no string) and accepts
|
||||
// any value whose kind is string, named string types included.
|
||||
@@ -470,8 +508,9 @@ func validateMessage(ctx context.Context, tr *phrasebook.Translator, rule, field
|
||||
}
|
||||
params["attribute"] = laravelAttribute(field)
|
||||
key := "lagoon::validate." + rule
|
||||
if rule == "between.numeric" {
|
||||
key = "lagoon::validation.between.numeric"
|
||||
switch rule {
|
||||
case "between.numeric", "min.string", "max.string":
|
||||
key = "lagoon::validation." + rule
|
||||
}
|
||||
if tr != nil {
|
||||
s := tr.Get(ctx, key, params)
|
||||
@@ -513,6 +552,10 @@ func validateMessage(ctx context.Context, tr *phrasebook.Translator, rule, field
|
||||
return "The " + attr + " must be a string."
|
||||
case "url":
|
||||
return "The " + attr + " format is invalid."
|
||||
case "min.string":
|
||||
return "The " + attr + " must be at least " + params["min"] + " characters."
|
||||
case "max.string":
|
||||
return "The " + attr + " may not be greater than " + params["max"] + " characters."
|
||||
default:
|
||||
return "The " + attr + " is invalid."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user