1
0
mirror of https://github.com/gogf/gf.git synced 2025-04-05 11:18:50 +08:00

add new validation rule "enums" (#2690)

This commit is contained in:
John Guo 2023-06-07 09:48:29 +08:00 committed by GitHub
parent 1bbfc56121
commit 2ece368810
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 141 additions and 0 deletions

View File

@ -21,6 +21,15 @@ func SetGlobalEnums(enumsJson string) error {
return json.Unmarshal([]byte(enumsJson), &enumsMap)
}
// GetGlobalEnums retrieves and returns the global enums.
func GetGlobalEnums() (string, error) {
enumsByes, err := json.Marshal(enumsMap)
if err != nil {
return "", err
}
return string(enumsByes), nil
}
// GetEnumsByType retrieves and returns the stored enums json by type name.
// The type name is like: github.com/gogf/gf/v2/encoding/gjson.ContentType
func GetEnumsByType(typeName string) string {

View File

@ -134,3 +134,23 @@ func Test_Parse(t *testing.T) {
t.Assert(gtag.Parse(content), expect)
})
}
func Test_SetGlobalEnums(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
oldEnumsJson, err := gtag.GetGlobalEnums()
t.AssertNil(err)
err = gtag.SetGlobalEnums(`{"k8s.io/apimachinery/pkg/api/resource.Format": [
"BinarySI",
"DecimalExponent",
"DecimalSI"
]}`)
t.AssertNil(err)
t.Assert(gtag.GetEnumsByType("k8s.io/apimachinery/pkg/api/resource.Format"), `[
"BinarySI",
"DecimalExponent",
"DecimalSI"
]`)
t.AssertNil(gtag.SetGlobalEnums(oldEnumsJson))
})
}

View File

@ -16,6 +16,7 @@ import (
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/gtag"
)
var (
@ -1550,3 +1551,36 @@ func Test_LTE(t *testing.T) {
t.AssertNil(err)
})
}
func Test_Enums(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type EnumsTest string
const (
EnumsTestA EnumsTest = "a"
EnumsTestB EnumsTest = "b"
)
type Params struct {
Id int
Enums EnumsTest `v:"enums"`
}
oldEnumsJson, err := gtag.GetGlobalEnums()
t.AssertNil(err)
defer t.AssertNil(gtag.SetGlobalEnums(oldEnumsJson))
err = gtag.SetGlobalEnums(`{"github.com/gogf/gf/v2/util/gvalid_test.EnumsTest": ["a","b"]}`)
t.AssertNil(err)
err = g.Validator().Data(&Params{
Id: 1,
Enums: EnumsTestB,
}).Run(ctx)
t.AssertNil(err)
err = g.Validator().Data(&Params{
Id: 1,
Enums: "c",
}).Run(ctx)
t.Assert(err, "The Enums value `c` should be in enums of: [\"a\",\"b\"]")
})
}

View File

@ -0,0 +1,78 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// 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,
// You can obtain one at https://github.com/gogf/gf.
package builtin
import (
"errors"
"fmt"
"reflect"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/reflection"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"
)
// RuleEnums implements `enums` rule:
// Value should be in enums of its constant type.
//
// Format: enums
type RuleEnums struct{}
func init() {
Register(RuleEnums{})
}
func (r RuleEnums) Name() string {
return "enums"
}
func (r RuleEnums) Message() string {
return "The {field} value `{value}` should be in enums of: {enums}"
}
func (r RuleEnums) Run(in RunInput) error {
originTypeAndKind := reflection.OriginTypeAndKind(in.Data.Val())
switch originTypeAndKind.OriginKind {
case reflect.Struct:
for i := 0; i < originTypeAndKind.OriginType.NumField(); i++ {
field := originTypeAndKind.OriginType.Field(i)
if in.Field == field.Name {
var (
typeId = fmt.Sprintf(`%s.%s`, field.Type.PkgPath(), field.Type.Name())
tagEnums = gtag.GetEnumsByType(typeId)
)
if tagEnums == "" {
return gerror.NewCodef(
gcode.CodeInvalidOperation,
`no enums found for type "%s"`,
typeId,
)
}
var enumsValues = make([]interface{}, 0)
if err := json.Unmarshal([]byte(tagEnums), &enumsValues); err != nil {
return err
}
if !gstr.InArray(gconv.Strings(enumsValues), in.Value.String()) {
return errors.New(gstr.Replace(
in.Message, `{enums}`, tagEnums,
))
}
}
}
default:
return gerror.NewCode(
gcode.CodeInvalidOperation,
`"enums" validation rule can only be used in struct validation currently`,
)
}
return nil
}