From 5d99c5c22834e29853e4f7234396248ac455242a Mon Sep 17 00:00:00 2001 From: DimuthuMadushan Date: Fri, 1 Nov 2024 08:11:15 +0530 Subject: [PATCH] Fix service crashing when input object variable value includes additional field --- .../Dependencies.toml | 4 +-- .../Dependencies.toml | 4 +-- .../Dependencies.toml | 4 +-- .../Dependencies.toml | 4 +-- .../Dependencies.toml | 4 +-- .../Dependencies.toml | 4 +-- .../tests/23_input_objects.bal | 20 +++++++++++- ...t_with_unexpected_variable_fields1.graphql | 9 ++++++ ...t_with_unexpected_variable_fields2.graphql | 9 ++++++ ...ject_with_unexpected_variable_fields1.json | 13 ++++++++ ...ject_with_unexpected_variable_fields2.json | 31 +++++++++++++++++++ .../Dependencies.toml | 4 +-- .../Dependencies.toml | 4 +-- .../graphql-test-common/Dependencies.toml | 6 ++-- ballerina/Dependencies.toml | 6 ++-- ballerina/field_validator_visitor.bal | 12 ++++++- changelog.md | 3 ++ 17 files changed, 117 insertions(+), 24 deletions(-) create mode 100644 ballerina-tests/graphql-service-test-suite/tests/resources/documents/input_object_with_unexpected_variable_fields1.graphql create mode 100644 ballerina-tests/graphql-service-test-suite/tests/resources/documents/input_object_with_unexpected_variable_fields2.graphql create mode 100644 ballerina-tests/graphql-service-test-suite/tests/resources/expected_results/input_object_with_unexpected_variable_fields1.json create mode 100644 ballerina-tests/graphql-service-test-suite/tests/resources/expected_results/input_object_with_unexpected_variable_fields2.json diff --git a/ballerina-tests/graphql-advanced-test-suite/Dependencies.toml b/ballerina-tests/graphql-advanced-test-suite/Dependencies.toml index 579b1af0c..cc1bcb89c 100644 --- a/ballerina-tests/graphql-advanced-test-suite/Dependencies.toml +++ b/ballerina-tests/graphql-advanced-test-suite/Dependencies.toml @@ -131,7 +131,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -292,7 +292,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, diff --git a/ballerina-tests/graphql-client-test-suite/Dependencies.toml b/ballerina-tests/graphql-client-test-suite/Dependencies.toml index 50aa2ee08..224fda848 100644 --- a/ballerina-tests/graphql-client-test-suite/Dependencies.toml +++ b/ballerina-tests/graphql-client-test-suite/Dependencies.toml @@ -129,7 +129,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "auth"}, @@ -294,7 +294,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "io"}, diff --git a/ballerina-tests/graphql-dataloader-test-suite/Dependencies.toml b/ballerina-tests/graphql-dataloader-test-suite/Dependencies.toml index d309d6fd9..f8aafca24 100644 --- a/ballerina-tests/graphql-dataloader-test-suite/Dependencies.toml +++ b/ballerina-tests/graphql-dataloader-test-suite/Dependencies.toml @@ -131,7 +131,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "auth"}, @@ -300,7 +300,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "io"}, diff --git a/ballerina-tests/graphql-interceptor-test-suite/Dependencies.toml b/ballerina-tests/graphql-interceptor-test-suite/Dependencies.toml index 59b605b5a..7ec9662dc 100644 --- a/ballerina-tests/graphql-interceptor-test-suite/Dependencies.toml +++ b/ballerina-tests/graphql-interceptor-test-suite/Dependencies.toml @@ -131,7 +131,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "auth"}, @@ -303,7 +303,7 @@ modules = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "io"}, diff --git a/ballerina-tests/graphql-security-test-suite/Dependencies.toml b/ballerina-tests/graphql-security-test-suite/Dependencies.toml index 3e38dc6cc..2d6ee893e 100644 --- a/ballerina-tests/graphql-security-test-suite/Dependencies.toml +++ b/ballerina-tests/graphql-security-test-suite/Dependencies.toml @@ -130,7 +130,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "auth"}, @@ -299,7 +299,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "io"}, diff --git a/ballerina-tests/graphql-service-test-suite/Dependencies.toml b/ballerina-tests/graphql-service-test-suite/Dependencies.toml index c1f9359fb..7bcdbbae4 100644 --- a/ballerina-tests/graphql-service-test-suite/Dependencies.toml +++ b/ballerina-tests/graphql-service-test-suite/Dependencies.toml @@ -128,7 +128,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -289,7 +289,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, diff --git a/ballerina-tests/graphql-service-test-suite/tests/23_input_objects.bal b/ballerina-tests/graphql-service-test-suite/tests/23_input_objects.bal index eefffee71..0c3f405c9 100644 --- a/ballerina-tests/graphql-service-test-suite/tests/23_input_objects.bal +++ b/ballerina-tests/graphql-service-test-suite/tests/23_input_objects.bal @@ -84,6 +84,22 @@ function dataProviderInputObject() returns map<[string, json]> { dir: "Chris Columbus" }; + json var8 = { + bName: "Harry", + bAuthor: {name:"J.K Rowling", age:44, address: {street: "Baker Street", city: "London"}}, + dir: "Chris Columbus" + }; + + json var9 = { + bInfo: { + bookName: "Harry", + author: {name:"J.K Rowling", age:44, address: {street: "Baker Street", city: "London"}}, + dir: "Chris Columbus", + movie: {movieName: "End Game", director: "Russo", episodes: [{timeDuration: 120}]}, + edition: 6 + } + }; + map<[string, json]> dataSet = { "1": ["input_object"], "2": ["input_object_with_missing_arguments"], @@ -109,7 +125,9 @@ function dataProviderInputObject() returns map<[string, json]> { "22": ["input_object_with_unexpected_variable_values", var7], "23": ["input_object_variables_with_invalid_type_name", {profile: {name: "Arthur", age: 5}}], "24": ["input_object_with_missing_nullable_variable_value"], - "25": ["default_values_in_input_object_fields"] + "25": ["default_values_in_input_object_fields"], + "26": ["input_object_with_unexpected_variable_fields1", var8], + "27": ["input_object_with_unexpected_variable_fields2", var9] }; return dataSet; } diff --git a/ballerina-tests/graphql-service-test-suite/tests/resources/documents/input_object_with_unexpected_variable_fields1.graphql b/ballerina-tests/graphql-service-test-suite/tests/resources/documents/input_object_with_unexpected_variable_fields1.graphql new file mode 100644 index 000000000..bd7306517 --- /dev/null +++ b/ballerina-tests/graphql-service-test-suite/tests/resources/documents/input_object_with_unexpected_variable_fields1.graphql @@ -0,0 +1,9 @@ +query getBook($bName:String!, $bAuthor:ProfileDetail!, $dir:String) { + ...on Query { + book(info: {bookName: $bName, edition: 6, author: $bAuthor, movie:{movieName: "End Game", director: $dir}}) { + ...on Book { + name + } + } + } +} diff --git a/ballerina-tests/graphql-service-test-suite/tests/resources/documents/input_object_with_unexpected_variable_fields2.graphql b/ballerina-tests/graphql-service-test-suite/tests/resources/documents/input_object_with_unexpected_variable_fields2.graphql new file mode 100644 index 000000000..786c7d62c --- /dev/null +++ b/ballerina-tests/graphql-service-test-suite/tests/resources/documents/input_object_with_unexpected_variable_fields2.graphql @@ -0,0 +1,9 @@ +query getBook($bInfo:Info!) { + ...on Query { + book(info: $bInfo) { + ...on Book { + name + } + } + } +} diff --git a/ballerina-tests/graphql-service-test-suite/tests/resources/expected_results/input_object_with_unexpected_variable_fields1.json b/ballerina-tests/graphql-service-test-suite/tests/resources/expected_results/input_object_with_unexpected_variable_fields1.json new file mode 100644 index 000000000..71a0c0bfc --- /dev/null +++ b/ballerina-tests/graphql-service-test-suite/tests/resources/expected_results/input_object_with_unexpected_variable_fields1.json @@ -0,0 +1,13 @@ +{ + "errors": [ + { + "message":"Input type \"ProfileDetail\" does not have a field \"address\".", + "locations": [ + { + "line": 3, + "column": 60 + } + ] + } + ] +} diff --git a/ballerina-tests/graphql-service-test-suite/tests/resources/expected_results/input_object_with_unexpected_variable_fields2.json b/ballerina-tests/graphql-service-test-suite/tests/resources/expected_results/input_object_with_unexpected_variable_fields2.json new file mode 100644 index 000000000..1c50255fa --- /dev/null +++ b/ballerina-tests/graphql-service-test-suite/tests/resources/expected_results/input_object_with_unexpected_variable_fields2.json @@ -0,0 +1,31 @@ +{ + "errors": [ + { + "message": "Input type \"ProfileDetail\" does not have a field \"address\".", + "locations": [ + { + "line": 3, + "column": 21 + } + ] + }, + { + "message": "Input type \"Movie\" does not have a field \"episodes\".", + "locations": [ + { + "line": 3, + "column": 21 + } + ] + }, + { + "message": "Input type \"Info\" does not have a field \"dir\".", + "locations": [ + { + "line": 3, + "column": 21 + } + ] + } + ] +} diff --git a/ballerina-tests/graphql-subgraph-test-suite/Dependencies.toml b/ballerina-tests/graphql-subgraph-test-suite/Dependencies.toml index b8f639904..f9d898463 100644 --- a/ballerina-tests/graphql-subgraph-test-suite/Dependencies.toml +++ b/ballerina-tests/graphql-subgraph-test-suite/Dependencies.toml @@ -123,7 +123,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -274,7 +274,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, diff --git a/ballerina-tests/graphql-subscription-test-suite/Dependencies.toml b/ballerina-tests/graphql-subscription-test-suite/Dependencies.toml index af58def84..1b50a12ce 100644 --- a/ballerina-tests/graphql-subscription-test-suite/Dependencies.toml +++ b/ballerina-tests/graphql-subscription-test-suite/Dependencies.toml @@ -142,7 +142,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "auth"}, @@ -314,7 +314,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "io"}, diff --git a/ballerina-tests/graphql-test-common/Dependencies.toml b/ballerina-tests/graphql-test-common/Dependencies.toml index f8e626c1c..06e2d8d4e 100644 --- a/ballerina-tests/graphql-test-common/Dependencies.toml +++ b/ballerina-tests/graphql-test-common/Dependencies.toml @@ -112,7 +112,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -269,7 +269,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -332,7 +332,7 @@ modules = [ [[package]] org = "ballerina" name = "time" -version = "2.4.0" +version = "2.4.1" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 0f822b5fc..bdebcfd33 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -106,7 +106,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.12.1" +version = "2.12.2" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -282,7 +282,7 @@ modules = [ [[package]] org = "ballerina" name = "mime" -version = "2.10.0" +version = "2.10.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -359,7 +359,7 @@ modules = [ [[package]] org = "ballerina" name = "time" -version = "2.4.0" +version = "2.4.1" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] diff --git a/ballerina/field_validator_visitor.bal b/ballerina/field_validator_visitor.bal index e358f6b53..dffffce83 100644 --- a/ballerina/field_validator_visitor.bal +++ b/ballerina/field_validator_visitor.bal @@ -327,11 +327,14 @@ class FieldValidatorVisitor { __Type argType = getOfType(inputValue.'type); __InputValue[]? inputFields = argType?.inputFields; if inputFields is __InputValue[] { + string[] keys = variableValues.keys(); foreach __InputValue subInputValue in inputFields { if getOfType(subInputValue.'type).name == UPLOAD { return; } - if variableValues.hasKey(subInputValue.name) { + int? index = keys.indexOf(subInputValue.name); + if index is int { + _ = keys.remove(index); anydata fieldValue = variableValues.get(subInputValue.name); if fieldValue is Scalar { if getOfType(subInputValue.'type).kind == ENUM { @@ -370,6 +373,13 @@ class FieldValidatorVisitor { } } } + if keys.length() > 0 { + foreach string 'key in keys { + string expectedTypeName = getOfTypeName(argType); + string message = string `Input type "${expectedTypeName}" does not have a field "${'key}".`; + self.errors.push(getErrorDetailRecord(message, location)); + } + } } else { string expectedTypeName = getOfTypeName(inputValue.'type); string listError = getListElementError(self.argumentPath); diff --git a/changelog.md b/changelog.md index 3c23e2f35..0a87aea46 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Fixed +- [[#7317] Fix Service Crashing when Input Object Type Variable Value Includes an Additional Field](https://github.com/ballerina-platform/ballerina-library/issues/7317) + ## [1.14.0] - 2024-08-20 ### Added