305 lines
7.6 KiB
Go
305 lines
7.6 KiB
Go
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Rules 验证规则类型
|
|
type Rules map[string][]string
|
|
|
|
// RulesMap 规则映射类型
|
|
type RulesMap map[string]Rules
|
|
|
|
// CustomizeMap 自定义规则映射
|
|
var CustomizeMap = make(map[string]Rules)
|
|
|
|
// 预定义验证规则
|
|
var (
|
|
IdVerify = Rules{"ID": []string{NotEmpty()}}
|
|
ApiVerify = Rules{"Path": {NotEmpty()}, "Description": {NotEmpty()}, "ApiGroup": {NotEmpty()}, "Method": {NotEmpty()}}
|
|
MenuVerify = Rules{"Path": {NotEmpty()}, "Name": {NotEmpty()}, "Component": {NotEmpty()}, "Sort": {Ge("0")}}
|
|
MenuMetaVerify = Rules{"Title": {NotEmpty()}}
|
|
LoginVerify = Rules{"Username": {NotEmpty()}, "Password": {NotEmpty()}}
|
|
RegisterVerify = Rules{"Username": {NotEmpty()}, "NickName": {NotEmpty()}, "Password": {NotEmpty()}, "AuthorityId": {NotEmpty()}}
|
|
PageInfoVerify = Rules{"Page": {NotEmpty()}, "PageSize": {NotEmpty()}}
|
|
CustomerVerify = Rules{"CustomerName": {NotEmpty()}, "CustomerPhoneData": {NotEmpty()}}
|
|
AutoCodeVerify = Rules{"Abbreviation": {NotEmpty()}, "StructName": {NotEmpty()}, "PackageName": {NotEmpty()}}
|
|
AutoPackageVerify = Rules{"PackageName": {NotEmpty()}}
|
|
AuthorityVerify = Rules{"AuthorityId": {NotEmpty()}, "AuthorityName": {NotEmpty()}}
|
|
AuthorityIdVerify = Rules{"AuthorityId": {NotEmpty()}}
|
|
OldAuthorityVerify = Rules{"OldAuthorityId": {NotEmpty()}}
|
|
ChangePasswordVerify = Rules{"Password": {NotEmpty()}, "NewPassword": {NotEmpty()}}
|
|
SetUserAuthorityVerify = Rules{"AuthorityId": {NotEmpty()}}
|
|
)
|
|
|
|
// RegisterRule 注册自定义规则方案建议在路由初始化层即注册
|
|
func RegisterRule(key string, rule Rules) (err error) {
|
|
if CustomizeMap[key] != nil {
|
|
return errors.New(key + "已注册,无法重复注册")
|
|
}
|
|
CustomizeMap[key] = rule
|
|
return nil
|
|
}
|
|
|
|
// NotEmpty 非空验证
|
|
func NotEmpty() string {
|
|
return "notEmpty"
|
|
}
|
|
|
|
// Ge 大于等于验证
|
|
func Ge(value string) string {
|
|
return "ge=" + value
|
|
}
|
|
|
|
// Le 小于等于验证
|
|
func Le(value string) string {
|
|
return "le=" + value
|
|
}
|
|
|
|
// Gt 大于验证
|
|
func Gt(value string) string {
|
|
return "gt=" + value
|
|
}
|
|
|
|
// Lt 小于验证
|
|
func Lt(value string) string {
|
|
return "lt=" + value
|
|
}
|
|
|
|
// Eq 等于验证
|
|
func Eq(value string) string {
|
|
return "eq=" + value
|
|
}
|
|
|
|
// Ne 不等于验证
|
|
func Ne(value string) string {
|
|
return "ne=" + value
|
|
}
|
|
|
|
// Len 长度验证
|
|
func Len(value string) string {
|
|
return "len=" + value
|
|
}
|
|
|
|
// MinLen 最小长度验证
|
|
func MinLen(value string) string {
|
|
return "minLen=" + value
|
|
}
|
|
|
|
// MaxLen 最大长度验证
|
|
func MaxLen(value string) string {
|
|
return "maxLen=" + value
|
|
}
|
|
|
|
// Regexp 正则验证
|
|
func Regexp(value string) string {
|
|
return "regexp=" + value
|
|
}
|
|
|
|
// RegexpMatch 正则校验 校验输入项是否满足正则表达式
|
|
func RegexpMatch(rule string) string {
|
|
return "regexp=" + rule
|
|
}
|
|
|
|
// Verify 验证结构体字段
|
|
func Verify(st interface{}, rules Rules) error {
|
|
compareMap := map[string]bool{
|
|
"lt": true, "le": true, "eq": true, "ne": true, "ge": true, "gt": true,
|
|
}
|
|
|
|
typ := reflect.TypeOf(st)
|
|
val := reflect.ValueOf(st)
|
|
|
|
// 处理指针类型
|
|
if typ.Kind() == reflect.Ptr {
|
|
typ = typ.Elem()
|
|
val = val.Elem()
|
|
}
|
|
|
|
kd := val.Kind()
|
|
if kd != reflect.Struct {
|
|
return errors.New("expect struct")
|
|
}
|
|
|
|
num := val.NumField()
|
|
for i := 0; i < num; i++ {
|
|
tagVal := typ.Field(i)
|
|
fieldVal := val.Field(i)
|
|
fieldName := tagVal.Name
|
|
|
|
// 递归处理嵌套结构体
|
|
if tagVal.Type.Kind() == reflect.Struct {
|
|
if err := Verify(fieldVal.Interface(), rules); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// 检查是否有验证规则
|
|
if ruleList, ok := rules[fieldName]; ok {
|
|
for _, rule := range ruleList {
|
|
switch {
|
|
case rule == "notEmpty":
|
|
if isBlank(fieldVal) {
|
|
return errors.New(fieldName + "值不能为空")
|
|
}
|
|
case strings.HasPrefix(rule, "regexp="):
|
|
if !regexpMatch(strings.Split(rule, "=")[1], fieldVal.String()) {
|
|
return errors.New(fieldName + "格式校验不通过")
|
|
}
|
|
case compareMap[strings.Split(rule, "=")[0]]:
|
|
if !compareVerify(fieldVal, rule) {
|
|
return errors.New(fieldName + "长度或值不在合法范围," + rule)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// isBlank 非空校验
|
|
func isBlank(value reflect.Value) bool {
|
|
switch value.Kind() {
|
|
case reflect.String, reflect.Slice:
|
|
return value.Len() == 0
|
|
case reflect.Bool:
|
|
return !value.Bool()
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return value.Int() == 0
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
return value.Uint() == 0
|
|
case reflect.Float32, reflect.Float64:
|
|
return value.Float() == 0
|
|
case reflect.Interface, reflect.Ptr:
|
|
return value.IsNil()
|
|
}
|
|
return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
|
|
}
|
|
|
|
// compareVerify 长度和数字的校验方法 根据类型自动校验
|
|
func compareVerify(value reflect.Value, VerifyStr string) bool {
|
|
switch value.Kind() {
|
|
case reflect.String:
|
|
return compareInt(len([]rune(value.String())), VerifyStr)
|
|
case reflect.Slice, reflect.Array:
|
|
return compareInt(value.Len(), VerifyStr)
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
return compareUint(value.Uint(), VerifyStr)
|
|
case reflect.Float32, reflect.Float64:
|
|
return compareFloat64(value.Float(), VerifyStr)
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return compareInt64(value.Int(), VerifyStr)
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// compareInt 整数比较
|
|
func compareInt(value int, VerifyStr string) bool {
|
|
VerifyStrArr := strings.Split(VerifyStr, "=")
|
|
VInt, VErr := strconv.Atoi(VerifyStrArr[1])
|
|
if VErr != nil {
|
|
return false
|
|
}
|
|
switch VerifyStrArr[0] {
|
|
case "lt":
|
|
return value < VInt
|
|
case "le":
|
|
return value <= VInt
|
|
case "eq":
|
|
return value == VInt
|
|
case "ne":
|
|
return value != VInt
|
|
case "ge":
|
|
return value >= VInt
|
|
case "gt":
|
|
return value > VInt
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// compareInt64 int64比较
|
|
func compareInt64(value int64, VerifyStr string) bool {
|
|
VerifyStrArr := strings.Split(VerifyStr, "=")
|
|
VInt, VErr := strconv.ParseInt(VerifyStrArr[1], 10, 64)
|
|
if VErr != nil {
|
|
return false
|
|
}
|
|
switch VerifyStrArr[0] {
|
|
case "lt":
|
|
return value < VInt
|
|
case "le":
|
|
return value <= VInt
|
|
case "eq":
|
|
return value == VInt
|
|
case "ne":
|
|
return value != VInt
|
|
case "ge":
|
|
return value >= VInt
|
|
case "gt":
|
|
return value > VInt
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// compareUint uint64比较
|
|
func compareUint(value uint64, VerifyStr string) bool {
|
|
VerifyStrArr := strings.Split(VerifyStr, "=")
|
|
VInt, VErr := strconv.ParseUint(VerifyStrArr[1], 10, 64)
|
|
if VErr != nil {
|
|
return false
|
|
}
|
|
switch VerifyStrArr[0] {
|
|
case "lt":
|
|
return value < VInt
|
|
case "le":
|
|
return value <= VInt
|
|
case "eq":
|
|
return value == VInt
|
|
case "ne":
|
|
return value != VInt
|
|
case "ge":
|
|
return value >= VInt
|
|
case "gt":
|
|
return value > VInt
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// compareFloat64 float64比较
|
|
func compareFloat64(value float64, VerifyStr string) bool {
|
|
VerifyStrArr := strings.Split(VerifyStr, "=")
|
|
VFloat, VErr := strconv.ParseFloat(VerifyStrArr[1], 64)
|
|
if VErr != nil {
|
|
return false
|
|
}
|
|
switch VerifyStrArr[0] {
|
|
case "lt":
|
|
return value < VFloat
|
|
case "le":
|
|
return value <= VFloat
|
|
case "eq":
|
|
return value == VFloat
|
|
case "ne":
|
|
return value != VFloat
|
|
case "ge":
|
|
return value >= VFloat
|
|
case "gt":
|
|
return value > VFloat
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// regexpMatch 正则匹配
|
|
func regexpMatch(rule, matchStr string) bool {
|
|
return regexp.MustCompile(rule).MatchString(matchStr)
|
|
}
|