2021-01-12 10:46:39 +08:00
|
|
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
2017-12-29 16:03:30 +08:00
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
2019-02-02 16:18:25 +08:00
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
2018-01-03 10:38:53 +08:00
|
|
|
|
2019-01-15 23:27:47 +08:00
|
|
|
// Package gvalid implements powerful and useful data/form validation functionality.
|
2018-01-03 10:53:45 +08:00
|
|
|
package gvalid
|
|
|
|
|
|
|
|
import (
|
2022-03-21 22:36:06 +08:00
|
|
|
"context"
|
2022-03-25 17:53:58 +08:00
|
|
|
"reflect"
|
2021-01-12 10:46:39 +08:00
|
|
|
"regexp"
|
2019-06-19 09:06:52 +08:00
|
|
|
"strings"
|
2019-07-29 21:01:19 +08:00
|
|
|
|
2022-03-21 22:36:06 +08:00
|
|
|
"github.com/gogf/gf/v2/internal/intlog"
|
2021-10-11 21:41:56 +08:00
|
|
|
"github.com/gogf/gf/v2/text/gregex"
|
2022-11-07 17:51:37 +08:00
|
|
|
"github.com/gogf/gf/v2/util/gtag"
|
2018-01-03 10:53:45 +08:00
|
|
|
)
|
|
|
|
|
2020-05-10 16:48:00 +08:00
|
|
|
// CustomMsg is the custom error message type,
|
|
|
|
// like: map[field] => string|map[rule]string
|
2018-11-13 00:12:35 +08:00
|
|
|
type CustomMsg = map[string]interface{}
|
2017-12-29 15:42:42 +08:00
|
|
|
|
2021-08-01 23:50:44 +08:00
|
|
|
// fieldRule defined the alias name and rule string for specified field.
|
|
|
|
type fieldRule struct {
|
2022-03-25 17:53:58 +08:00
|
|
|
Name string // Alias name for the field.
|
|
|
|
Rule string // Rule string like: "max:6"
|
|
|
|
IsMeta bool // Is this rule is from gmeta.Meta, which marks it as whole struct rule.
|
2023-10-09 20:00:08 +08:00
|
|
|
FieldKind reflect.Kind // Original kind of struct field, which is used for parameter type checks.
|
|
|
|
FieldType reflect.Type // Type of struct field, which is used for parameter type checks.
|
2021-08-01 23:50:44 +08:00
|
|
|
}
|
|
|
|
|
2021-09-17 19:26:56 +08:00
|
|
|
// iNoValidation is an interface that marks current struct not validated by package `gvalid`.
|
|
|
|
type iNoValidation interface {
|
2021-05-17 19:59:34 +08:00
|
|
|
NoValidation()
|
|
|
|
}
|
|
|
|
|
2021-01-12 10:46:39 +08:00
|
|
|
const (
|
2021-05-19 13:29:40 +08:00
|
|
|
singleRulePattern = `^([\w-]+):{0,1}(.*)` // regular expression pattern for single validation rule.
|
|
|
|
internalRulesErrRuleName = "InvalidRules" // rule name for internal invalid rules validation error.
|
|
|
|
internalParamsErrRuleName = "InvalidParams" // rule name for internal invalid params validation error.
|
|
|
|
internalObjectErrRuleName = "InvalidObject" // rule name for internal invalid object validation error.
|
|
|
|
internalErrorMapKey = "__InternalError__" // error map key for internal errors.
|
|
|
|
internalDefaultRuleName = "__default__" // default rule name for i18n error message format if no i18n message found for specified error rule.
|
|
|
|
ruleMessagePrefixForI18n = "gf.gvalid.rule." // prefix string for each rule configuration in i18n content.
|
2022-11-07 17:51:37 +08:00
|
|
|
noValidationTagName = gtag.NoValidation // no validation tag name for struct attribute.
|
2022-09-26 22:11:13 +08:00
|
|
|
ruleNameRegex = "regex" // the name for rule "regex"
|
|
|
|
ruleNameNotRegex = "not-regex" // the name for rule "not-regex"
|
|
|
|
ruleNameForeach = "foreach" // the name for rule "foreach"
|
2021-11-22 14:41:33 +08:00
|
|
|
ruleNameBail = "bail" // the name for rule "bail"
|
|
|
|
ruleNameCi = "ci" // the name for rule "ci"
|
2022-03-25 17:53:58 +08:00
|
|
|
emptyJsonArrayStr = "[]" // Empty json string for array type.
|
|
|
|
emptyJsonObjectStr = "{}" // Empty json string for object type.
|
2022-09-26 22:11:13 +08:00
|
|
|
requiredRulesPrefix = "required" // requiredRulesPrefix specifies the rule prefix that must be validated even the value is empty (nil or empty).
|
2021-01-12 10:46:39 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2022-09-26 22:11:13 +08:00
|
|
|
// defaultErrorMessages is the default error messages.
|
2021-05-19 13:29:40 +08:00
|
|
|
// Note that these messages are synchronized from ./i18n/en/validation.toml .
|
2022-09-26 22:11:13 +08:00
|
|
|
defaultErrorMessages = map[string]string{
|
|
|
|
internalDefaultRuleName: "The {field} value `{value}` is invalid",
|
2021-11-22 14:41:33 +08:00
|
|
|
}
|
|
|
|
|
2022-11-07 17:51:37 +08:00
|
|
|
// structTagPriority specifies the validation tag priority array.
|
|
|
|
structTagPriority = []string{gtag.Valid, gtag.ValidShort}
|
|
|
|
|
|
|
|
// aliasNameTagPriority specifies the alias tag priority array.
|
|
|
|
aliasNameTagPriority = []string{gtag.Param, gtag.ParamShort}
|
2021-11-22 14:41:33 +08:00
|
|
|
|
|
|
|
// all internal error keys.
|
|
|
|
internalErrKeyMap = map[string]string{
|
|
|
|
internalRulesErrRuleName: internalRulesErrRuleName,
|
|
|
|
internalParamsErrRuleName: internalParamsErrRuleName,
|
|
|
|
internalObjectErrRuleName: internalObjectErrRuleName,
|
|
|
|
}
|
|
|
|
// regular expression object for single rule
|
|
|
|
// which is compiled just once and of repeatable usage.
|
|
|
|
ruleRegex, _ = regexp.Compile(singleRulePattern)
|
|
|
|
|
2022-09-26 22:11:13 +08:00
|
|
|
// decorativeRuleMap defines all rules that are just marked rules which have neither functional meaning
|
2021-08-01 22:12:44 +08:00
|
|
|
// nor error messages.
|
2022-09-26 22:11:13 +08:00
|
|
|
decorativeRuleMap = map[string]bool{
|
|
|
|
ruleNameForeach: true,
|
|
|
|
ruleNameBail: true,
|
|
|
|
ruleNameCi: true,
|
2021-08-01 22:12:44 +08:00
|
|
|
}
|
2021-01-12 10:46:39 +08:00
|
|
|
)
|
|
|
|
|
2022-03-02 20:00:40 +08:00
|
|
|
// ParseTagValue parses one sequence tag to field, rule and error message.
|
2020-05-10 16:48:00 +08:00
|
|
|
// The sequence tag is like: [alias@]rule[...#msg...]
|
2022-03-02 20:00:40 +08:00
|
|
|
func ParseTagValue(tag string) (field, rule, msg string) {
|
2020-01-01 14:18:00 +08:00
|
|
|
// Complete sequence tag.
|
2020-07-05 18:55:38 +08:00
|
|
|
// Example: name@required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致
|
2019-06-19 09:06:52 +08:00
|
|
|
match, _ := gregex.MatchString(`\s*((\w+)\s*@){0,1}\s*([^#]+)\s*(#\s*(.*)){0,1}\s*`, tag)
|
2022-03-21 22:36:06 +08:00
|
|
|
if len(match) > 5 {
|
|
|
|
msg = strings.TrimSpace(match[5])
|
|
|
|
rule = strings.TrimSpace(match[3])
|
|
|
|
field = strings.TrimSpace(match[2])
|
|
|
|
} else {
|
|
|
|
intlog.Errorf(context.TODO(), `invalid validation tag value: %s`, tag)
|
|
|
|
}
|
|
|
|
return
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
2022-03-01 11:43:42 +08:00
|
|
|
|
|
|
|
// GetTags returns the validation tags.
|
|
|
|
func GetTags() []string {
|
|
|
|
return structTagPriority
|
|
|
|
}
|