Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate enum values in input variables #4753

Merged
merged 13 commits into from
May 2, 2024
5 changes: 5 additions & 0 deletions .changesets/fix_geal_input_enum_validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Validate enum values in input variables ([Issue #4633](https://github.com/apollographql/router/issues/4633))

The Router will now validate enum values provided in JSON variables.

By [@Geal](https://github.com/Geal) in https://github.com/apollographql/router/pull/4753
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
source: apollo-router/src/services/supergraph/tests.rs
expression: response
---
{
"errors": [
{
"message": "invalid type for variable: 'input'",
"extensions": {
"name": "input",
"code": "VALIDATION_INVALID_TYPE_VARIABLE"
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
source: apollo-router/src/services/supergraph/tests.rs
expression: response
---
{
"errors": [
{
"message": "Value \"C does not exist in \"InputEnum\" enum.",
"locations": [
{
"line": 1,
"column": 21
}
],
"extensions": {
"code": "GRAPHQL_VALIDATION_FAILED"
}
}
]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
source: apollo-router/src/services/supergraph_service.rs
source: apollo-router/src/services/supergraph/tests.rs
expression: stream.next_response().await.unwrap()
---
{
Expand Down
73 changes: 73 additions & 0 deletions apollo-router/src/services/supergraph/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3549,3 +3549,76 @@ async fn abstract_types_in_requires() {
let mut stream = service.oneshot(request).await.unwrap();
insta::assert_json_snapshot!(stream.next_response().await.unwrap());
}

const ENUM_SCHEMA: &str = r#"schema
@core(feature: "https://specs.apollo.dev/core/v0.1")
@core(feature: "https://specs.apollo.dev/join/v0.1")
@core(feature: "https://specs.apollo.dev/inaccessible/v0.1")
{
query: Query
}
directive @core(feature: String!) repeatable on SCHEMA
directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION
directive @join__type(graph: join__Graph!, key: join__FieldSet) repeatable on OBJECT | INTERFACE
directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE
directive @join__graph(name: String!, url: String!) on ENUM_VALUE
directive @inaccessible on OBJECT | FIELD_DEFINITION | INTERFACE | UNION
scalar join__FieldSet
enum join__Graph {
USER @join__graph(name: "user", url: "http://localhost:4001/graphql")
ORGA @join__graph(name: "orga", url: "http://localhost:4002/graphql")
}
type Query {
test(input: InputEnum): String @join__field(graph: USER)
}

enum InputEnum {
A
B
}"#;

#[tokio::test]
async fn invalid_input_enum() {
let service = TestHarness::builder()
.configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } }))
.unwrap()
.schema(ENUM_SCHEMA)
//.extra_plugin(subgraphs)
.build_supergraph()
.await
.unwrap();

let request = supergraph::Request::fake_builder()
.query("query { test(input: C) }")
.context(defer_context())
// Request building here
.build()
.unwrap();
let response = service
.clone()
.oneshot(request)
.await
.unwrap()
.next_response()
.await
.unwrap();

insta::assert_json_snapshot!(response);

let request = supergraph::Request::fake_builder()
.query("query($input: InputEnum) { test(input: $input) }")
.variable("input", "INVALID")
.context(defer_context())
// Request building here
.build()
.unwrap();
let response = service
.oneshot(request)
.await
.unwrap()
.next_response()
.await
.unwrap();

insta::assert_json_snapshot!(response);
}
9 changes: 4 additions & 5 deletions apollo-router/src/spec/field_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,10 @@ fn validate_input_value(
// Custom scalar: accept any JSON value
(schema::ExtendedType::Scalar(_), _) => Ok(()),

// TODO: check enum value?
// (schema::ExtendedType::Enum(def), Value::String(s)) => {
// from_bool(def.values.contains_key(s))
// },
(schema::ExtendedType::Enum(_), _) => Ok(()),
(schema::ExtendedType::Enum(def), Value::String(s)) => {
from_bool(def.values.contains_key(s.as_str()))
}
(schema::ExtendedType::Enum(_), _) => Err(InvalidValue),

(schema::ExtendedType::InputObject(def), Value::Object(obj)) => {
// TODO: check keys in `obj` but not in `def.fields`?
Expand Down
Loading