From 188217c0b6698de6c205ef175f2575b5b8c254ea Mon Sep 17 00:00:00 2001 From: Jie Ma Date: Sun, 1 Sep 2019 11:44:16 +1000 Subject: [PATCH] Add enum value validation in input object --- validator/testdata/vars.graphql | 5 +++++ validator/vars.go | 16 +++++++++++++--- validator/vars_test.go | 22 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/validator/testdata/vars.graphql b/validator/testdata/vars.graphql index 352aa33f..ebdfc3f3 100644 --- a/validator/testdata/vars.graphql +++ b/validator/testdata/vars.graphql @@ -18,10 +18,15 @@ input InputType { name: String! nullName: String nullEmbedded: Embedded + enum: Enum } input Embedded { name: String! } +enum Enum { + A +} + scalar Custom diff --git a/validator/vars.go b/validator/vars.go index 99816dc4..40af5461 100644 --- a/validator/vars.go +++ b/validator/vars.go @@ -2,6 +2,7 @@ package validator import ( "reflect" + "strings" "fmt" @@ -117,10 +118,19 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr switch def.Kind { case ast.Enum: kind := val.Type().Kind() - if kind == reflect.Int || kind == reflect.Int32 || kind == reflect.Int64 || kind == reflect.String { - return nil + if kind != reflect.Int && kind != reflect.Int32 && kind != reflect.Int64 && kind != reflect.String { + return gqlerror.ErrorPathf(v.path, "enums must be ints or strings") + } + isValidEnum := false + for _, enumVal := range def.EnumValues { + if strings.EqualFold(val.String(), enumVal.Name) { + isValidEnum = true + } } - return gqlerror.ErrorPathf(v.path, "enums must be ints or strings") + if !isValidEnum { + return gqlerror.ErrorPathf(v.path, "%s is not a valid %s", val.String(), def.Name) + } + return nil case ast.Scalar: kind := val.Type().Kind() switch typ.NamedType { diff --git a/validator/vars_test.go b/validator/vars_test.go index 48a65134..09b0245c 100644 --- a/validator/vars_test.go +++ b/validator/vars_test.go @@ -126,6 +126,28 @@ func TestValidateVars(t *testing.T) { }) require.EqualError(t, gerr, "input: variable.var.foobard unknown field") }) + + t.Run("enum input object", func(t *testing.T) { + q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) + _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ + "var": map[string]interface{}{ + "name": "foobar", + "enum": "A", + }, + }) + require.Nil(t, gerr) + }) + + t.Run("unknown enum value input object", func(t *testing.T) { + q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) + _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ + "var": map[string]interface{}{ + "name": "foobar", + "enum": "B", + }, + }) + require.EqualError(t, gerr, "input: variable.var.enum B is not a valid Enum") + }) }) t.Run("array", func(t *testing.T) {