common/helpers: make validation work for SubnetMap

This commit is contained in:
Vincent Bernat
2022-08-14 15:06:53 +02:00
parent 574ec7e79e
commit d9a8262f76
3 changed files with 66 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ package helpers
import ( import (
"net" "net"
"reflect"
"strconv" "strconv"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
@@ -13,6 +14,20 @@ import (
// Validate is a validator instance to be used everywhere. // Validate is a validator instance to be used everywhere.
var Validate *validator.Validate var Validate *validator.Validate
// RegisterSubnetMapValidation register a new SubnetMap[] type for
// validation. As validator requires an explicit type, we cannot just
// register all subnetmaps.
func RegisterSubnetMapValidation[V any]() {
var zero SubnetMap[V]
validatorFunc := func(field reflect.Value) interface{} {
if subnetMap, ok := field.Interface().(SubnetMap[V]); ok {
return subnetMap.ToMap()
}
return nil
}
Validate.RegisterCustomTypeFunc(validatorFunc, zero)
}
// isListen validates a <dns>:<port> combination for fields typically used for listening address // isListen validates a <dns>:<port> combination for fields typically used for listening address
func isListen(fl validator.FieldLevel) bool { func isListen(fl validator.FieldLevel) bool {
val := fl.Field().String() val := fl.Field().String()
@@ -35,4 +50,5 @@ func isListen(fl validator.FieldLevel) bool {
func init() { func init() {
Validate = validator.New() Validate = validator.New()
Validate.RegisterValidation("listen", isListen) Validate.RegisterValidation("listen", isListen)
RegisterSubnetMapValidation[string]()
} }

View File

@@ -37,3 +37,52 @@ func TestListenValidator(t *testing.T) {
} }
} }
} }
func TestSubnetMapValidator(t *testing.T) {
type SomeStruct struct {
Blip *helpers.SubnetMap[string] `validate:"min=2,dive,min=3"`
}
cases := []struct {
Description string
Value interface{}
Error bool
}{
{
Description: "Valid SomeStruct",
Value: SomeStruct{
Blip: helpers.MustNewSubnetMap(map[string]string{
"2001:db8::/64": "hello",
"2001:db8:1::/64": "bye",
}),
},
}, {
Description: "Missing one key",
Value: SomeStruct{
Blip: helpers.MustNewSubnetMap(map[string]string{
"2001:db8::/64": "hello",
}),
},
Error: true,
}, {
Description: "One value is too short",
Value: SomeStruct{
Blip: helpers.MustNewSubnetMap(map[string]string{
"2001:db8::/64": "he",
"2001:db8:1::/64": "bye",
}),
},
Error: true,
},
}
for _, tc := range cases {
t.Run(tc.Description, func(t *testing.T) {
err := helpers.Validate.Struct(tc.Value)
if err != nil && !tc.Error {
t.Fatalf("Validate() error:\n%+v", err)
} else if err == nil && tc.Error {
t.Fatal("Validate() did not error")
}
})
}
}

View File

@@ -191,4 +191,5 @@ func init() {
helpers.AddMapstructureUnmarshallerHook(ConfigurationUnmarshallerHook()) helpers.AddMapstructureUnmarshallerHook(ConfigurationUnmarshallerHook())
helpers.AddMapstructureUnmarshallerHook(helpers.SubnetMapUnmarshallerHook[string]()) helpers.AddMapstructureUnmarshallerHook(helpers.SubnetMapUnmarshallerHook[string]())
helpers.AddMapstructureUnmarshallerHook(helpers.SubnetMapUnmarshallerHook[SecurityParameters]()) helpers.AddMapstructureUnmarshallerHook(helpers.SubnetMapUnmarshallerHook[SecurityParameters]())
helpers.RegisterSubnetMapValidation[SecurityParameters]()
} }