From d24123fc6ca91bd6461693aa01956199f8cb0f2e Mon Sep 17 00:00:00 2001 From: Anurag Sharma Date: Fri, 19 Mar 2021 13:09:20 +0530 Subject: [PATCH 1/2] fix(Parser): Add Directive argument validator --- validator/schema.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/validator/schema.go b/validator/schema.go index 4f482fec..72499b02 100644 --- a/validator/schema.go +++ b/validator/schema.go @@ -289,12 +289,30 @@ func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective return nil } +func validateDirectiveArgs(dir *Directive, schema *Schema) *gqlerror.Error { + allowedArgs := make(map[string]struct{}, len(schema.Directives[dir.Name].Arguments)) + for _, arg := range schema.Directives[dir.Name].Arguments { + allowedArgs[arg.Name] = struct{}{} + } + + for _, arg := range dir.Arguments { + if _, ok := allowedArgs[arg.Name]; !ok { + return gqlerror.Errorf("%s is not supported as an argument for %s directive.", arg.Name, dir.Name) + } + } + return nil + +} + func validateDirectives(schema *Schema, dirs DirectiveList, location DirectiveLocation, currentDirective *DirectiveDefinition) *gqlerror.Error { for _, dir := range dirs { if err := validateName(dir.Position, dir.Name); err != nil { // now, GraphQL spec doesn't have reserved directive name return err } + if err := validateDirectiveArgs(dir, schema); err != nil { + return err + } if currentDirective != nil && dir.Name == currentDirective.Name { return gqlerror.ErrorPosf(dir.Position, "Directive %s cannot refer to itself.", currentDirective.Name) } From f3f3532a84f1d1cfc768659bafbeddaa1573d8f0 Mon Sep 17 00:00:00 2001 From: Anurag Sharma Date: Fri, 19 Mar 2021 14:34:33 +0530 Subject: [PATCH 2/2] Add tests --- validator/schema.go | 10 +++++----- validator/schema_test.yml | 10 ++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/validator/schema.go b/validator/schema.go index 72499b02..25ee7469 100644 --- a/validator/schema.go +++ b/validator/schema.go @@ -290,14 +290,14 @@ func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective } func validateDirectiveArgs(dir *Directive, schema *Schema) *gqlerror.Error { - allowedArgs := make(map[string]struct{}, len(schema.Directives[dir.Name].Arguments)) + allowedArgs := make(map[string]struct{}) for _, arg := range schema.Directives[dir.Name].Arguments { allowedArgs[arg.Name] = struct{}{} } for _, arg := range dir.Arguments { if _, ok := allowedArgs[arg.Name]; !ok { - return gqlerror.Errorf("%s is not supported as an argument for %s directive.", arg.Name, dir.Name) + return gqlerror.ErrorPosf(dir.Position, "%s is not supported as an argument for %s directive.", arg.Name, dir.Name) } } return nil @@ -310,15 +310,15 @@ func validateDirectives(schema *Schema, dirs DirectiveList, location DirectiveLo // now, GraphQL spec doesn't have reserved directive name return err } - if err := validateDirectiveArgs(dir, schema); err != nil { - return err - } if currentDirective != nil && dir.Name == currentDirective.Name { return gqlerror.ErrorPosf(dir.Position, "Directive %s cannot refer to itself.", currentDirective.Name) } if schema.Directives[dir.Name] == nil { return gqlerror.ErrorPosf(dir.Position, "Undefined directive %s.", dir.Name) } + if err := validateDirectiveArgs(dir, schema); err != nil { + return err + } validKind := false for _, dirLocation := range schema.Directives[dir.Name].Locations { if dirLocation == location { diff --git a/validator/schema_test.yml b/validator/schema_test.yml index 05dba9e0..85373bd9 100644 --- a/validator/schema_test.yml +++ b/validator/schema_test.yml @@ -505,6 +505,16 @@ directives: directive @A(a: Input, b: Scalar, c: Enum) on FIELD_DEFINITION + - name: Valid arg for directive + input: | + type User @include(aggregate: false) { + name: String + } + + error: + message: 'aggregate is not supported as an argument for include directive.' + locations: [{line: 1, column: 12}] + - name: Objects not allowed input: | type Object { id: ID }