From ff3090ece5af90fe8033bf6c80fd4999c3f37936 Mon Sep 17 00:00:00 2001 From: Maarten van Vliet Date: Tue, 18 Jan 2022 12:09:28 +0100 Subject: [PATCH] Ensure input/output types are correctly placed for SDL schemas The InputOutputTypesCorrectlyPlaced phase did not work for SDL schema's since it would unwrap a TypeReference, which yields the TypeReference and not the type atom. The subsequent lookup in the schema types would therefore fail, as it expects atoms not typereferences, and it would not add errors. It now correctly fetches the atom type identifier, though in a bit of a roundabout way. --- .../input_output_types_correctly_placed.ex | 20 ++++-- ...put_output_types_correctly_placed_test.exs | 72 ++++++++++++++++++- .../dynamic/invalid_input_types_sdl.exs | 15 ++++ .../dynamic/invalid_output_types_sdl.exs | 17 +++++ 4 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 test/support/fixtures/dynamic/invalid_input_types_sdl.exs create mode 100644 test/support/fixtures/dynamic/invalid_output_types_sdl.exs diff --git a/lib/absinthe/phase/schema/validation/input_output_types_correctly_placed.ex b/lib/absinthe/phase/schema/validation/input_output_types_correctly_placed.ex index 442b7c55f5..7ea2b06a23 100644 --- a/lib/absinthe/phase/schema/validation/input_output_types_correctly_placed.ex +++ b/lib/absinthe/phase/schema/validation/input_output_types_correctly_placed.ex @@ -9,7 +9,7 @@ defmodule Absinthe.Phase.Schema.Validation.InputOutputTypesCorrectlyPlaced do defp handle_schemas(%Blueprint.Schema.SchemaDefinition{} = schema) do types = Map.new(schema.type_definitions, &{&1.identifier, &1}) - schema = Blueprint.prewalk(schema, &validate_type(&1, types)) + schema = Blueprint.prewalk(schema, &validate_type(&1, types, schema)) {:halt, schema} end @@ -17,8 +17,12 @@ defmodule Absinthe.Phase.Schema.Validation.InputOutputTypesCorrectlyPlaced do obj end - defp validate_type(%Blueprint.Schema.InputValueDefinition{} = arg, types) do - arg_type = Map.get(types, Blueprint.TypeReference.unwrap(arg.type)) + defp validate_type(%Blueprint.Schema.InputValueDefinition{} = arg, types, schema) do + type = + Blueprint.TypeReference.unwrap(arg.type) + |> Blueprint.TypeReference.to_type(schema) + + arg_type = Map.get(types, type) if arg_type && wrong_type?(Blueprint.Schema.InputValueDefinition, arg_type) do detail = %{ @@ -33,11 +37,15 @@ defmodule Absinthe.Phase.Schema.Validation.InputOutputTypesCorrectlyPlaced do end end - defp validate_type(%struct{fields: fields} = type, types) do + defp validate_type(%struct{fields: fields} = type, types, schema) do fields = Enum.map(fields, fn %{type: _} = field -> - field_type = Map.get(types, Blueprint.TypeReference.unwrap(field.type)) + type = + Blueprint.TypeReference.unwrap(field.type) + |> Blueprint.TypeReference.to_type(schema) + + field_type = Map.get(types, type) if field_type && wrong_type?(struct, field_type) do detail = %{ @@ -59,7 +67,7 @@ defmodule Absinthe.Phase.Schema.Validation.InputOutputTypesCorrectlyPlaced do %{type | fields: fields} end - defp validate_type(type, _types) do + defp validate_type(type, _types, _schema) do type end diff --git a/test/absinthe/schema/rule/input_output_types_correctly_placed_test.exs b/test/absinthe/schema/rule/input_output_types_correctly_placed_test.exs index fe861c6c45..18e7dd6999 100644 --- a/test/absinthe/schema/rule/input_output_types_correctly_placed_test.exs +++ b/test/absinthe/schema/rule/input_output_types_correctly_placed_test.exs @@ -1,7 +1,7 @@ defmodule Absinthe.Schema.Rule.InputOutputTypesCorrectlyPlacedTest do use Absinthe.Case, async: true - describe "rule" do + describe "macro schema" do test "is enforced with output types on arguments" do assert_schema_error("invalid_output_types", [ %{ @@ -56,4 +56,74 @@ defmodule Absinthe.Schema.Rule.InputOutputTypesCorrectlyPlacedTest do ]) end end + + describe "sdl schema" do + test "is enforced with output types on arguments" do + assert_schema_error("invalid_output_types_sdl", [ + %{ + extra: %{ + field: :blah, + parent: Absinthe.Blueprint.Schema.ObjectTypeDefinition, + struct: Absinthe.Blueprint.Schema.InputObjectTypeDefinition, + type: :input + }, + locations: [ + %{ + file: "test/support/fixtures/dynamic/invalid_output_types_sdl.exs", + line: 4 + } + ], + phase: Absinthe.Phase.Schema.Validation.InputOutputTypesCorrectlyPlaced + }, + %{ + extra: %{ + argument: :invalid_arg, + struct: Absinthe.Blueprint.Schema.ObjectTypeDefinition, + type: :user + }, + locations: [ + %{ + file: "test/support/fixtures/dynamic/invalid_output_types_sdl.exs", + line: 4 + } + ], + phase: Absinthe.Phase.Schema.Validation.InputOutputTypesCorrectlyPlaced + } + ]) + end + + test "is enforced with input types on arguments" do + assert_schema_error("invalid_input_types_sdl", [ + %{ + extra: %{ + argument: :blah, + struct: Absinthe.Blueprint.Schema.ObjectTypeDefinition, + type: :user + }, + locations: [ + %{ + file: "test/support/fixtures/dynamic/invalid_input_types_sdl.exs", + line: 4 + } + ], + phase: Absinthe.Phase.Schema.Validation.InputOutputTypesCorrectlyPlaced + }, + %{ + extra: %{ + field: :blah, + parent: Absinthe.Blueprint.Schema.InputObjectTypeDefinition, + struct: Absinthe.Blueprint.Schema.ObjectTypeDefinition, + type: :user + }, + locations: [ + %{ + file: "test/support/fixtures/dynamic/invalid_input_types_sdl.exs", + line: 4 + } + ], + phase: Absinthe.Phase.Schema.Validation.InputOutputTypesCorrectlyPlaced + } + ]) + end + end end diff --git a/test/support/fixtures/dynamic/invalid_input_types_sdl.exs b/test/support/fixtures/dynamic/invalid_input_types_sdl.exs new file mode 100644 index 0000000000..0f87f2dc77 --- /dev/null +++ b/test/support/fixtures/dynamic/invalid_input_types_sdl.exs @@ -0,0 +1,15 @@ +defmodule Absinthe.Fixtures.InvalidOutputTypesSdlSchema do + use Absinthe.Schema + + import_sdl """ + type User + + input Foo { + blah: User + } + + type Query { + foo(arg: Foo): User + } + """ +end diff --git a/test/support/fixtures/dynamic/invalid_output_types_sdl.exs b/test/support/fixtures/dynamic/invalid_output_types_sdl.exs new file mode 100644 index 0000000000..c313726e4b --- /dev/null +++ b/test/support/fixtures/dynamic/invalid_output_types_sdl.exs @@ -0,0 +1,17 @@ +defmodule Absinthe.Fixtures.InvalidInputTypesSdlSchema do + use Absinthe.Schema + + import_sdl """ + type User + + input Input + + type BadObject { + blah: Input + } + + type Query { + foo(invalidArg: User): User + } + """ +end