Skip to content

Commit 68b893a

Browse files
author
Robert Mosolgo
authored
Merge pull request #3120 from rmosolgo/validate-input-types
Assert valid input types when adding arguments to schema
2 parents 5d69eac + 232b584 commit 68b893a

2 files changed

Lines changed: 67 additions & 4 deletions

File tree

lib/graphql/schema/argument.rb

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,21 @@ def to_graphql
146146
argument
147147
end
148148

149-
attr_writer :type
149+
def type=(new_type)
150+
validate_input_type(new_type)
151+
@type = new_type
152+
end
150153

151154
def type
152-
@type ||= Member::BuildType.parse_type(@type_expr, null: @null)
153-
rescue StandardError => err
154-
raise ArgumentError, "Couldn't build type for Argument #{@owner.name}.#{name}: #{err.class.name}: #{err.message}", err.backtrace
155+
@type ||= begin
156+
parsed_type = begin
157+
Member::BuildType.parse_type(@type_expr, null: @null)
158+
rescue StandardError => err
159+
raise ArgumentError, "Couldn't build type for Argument #{@owner.name}.#{name}: #{err.class.name}: #{err.message}", err.backtrace
160+
end
161+
validate_input_type(parsed_type)
162+
parsed_type
163+
end
155164
end
156165

157166
def statically_coercible?
@@ -186,6 +195,18 @@ def prepare_value(obj, value, context: nil)
186195
raise "Invalid prepare for #{@owner.name}.name: #{@prepare.inspect}"
187196
end
188197
end
198+
199+
def validate_input_type(input_type)
200+
if input_type.is_a?(String) || input_type.is_a?(GraphQL::Schema::LateBoundType)
201+
# Do nothing; assume this will be validated later
202+
elsif input_type.kind.non_null? || input_type.kind.list?
203+
validate_input_type(input_type.unwrap)
204+
elsif !input_type.kind.input?
205+
raise ArgumentError, "Invalid input type for #{path}: #{input_type.graphql_name}. Must be scalar, enum, or input object, not #{input_type.kind.name}."
206+
else
207+
# It's an input type, we're OK
208+
end
209+
end
189210
end
190211
end
191212
end

spec/graphql/schema/argument_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,4 +266,46 @@ def self.object_from_id(id, ctx)
266266
assert_nil res5["data"].fetch("nullableEnsemble")
267267
end
268268
end
269+
270+
describe "invalid input types" do
271+
class InvalidArgumentTypeSchema < GraphQL::Schema
272+
class InvalidArgumentType < GraphQL::Schema::Object
273+
end
274+
275+
class InvalidArgumentObject < GraphQL::Schema::Object
276+
field :invalid, Boolean, null: false do
277+
argument :object_ref, InvalidArgumentType, required: false
278+
end
279+
end
280+
281+
class InvalidLazyArgumentObject < GraphQL::Schema::Object
282+
field :invalid, Boolean, null: false do
283+
argument :lazy_object_ref, "InvalidArgumentTypeSchema::InvalidArgumentType", required: false
284+
end
285+
end
286+
287+
use GraphQL::Execution::Interpreter
288+
use GraphQL::Analysis::AST
289+
end
290+
291+
it "rejects them" do
292+
err = assert_raises ArgumentError do
293+
Class.new(InvalidArgumentTypeSchema) do
294+
query(InvalidArgumentTypeSchema::InvalidArgumentObject)
295+
end
296+
end
297+
298+
expected_message = "Invalid input type for InvalidArgumentObject.invalid.objectRef: InvalidArgument. Must be scalar, enum, or input object, not OBJECT."
299+
assert_equal expected_message, err.message
300+
301+
err = assert_raises ArgumentError do
302+
Class.new(InvalidArgumentTypeSchema) do
303+
query(InvalidArgumentTypeSchema::InvalidLazyArgumentObject)
304+
end
305+
end
306+
307+
expected_message = "Invalid input type for InvalidLazyArgumentObject.invalid.lazyObjectRef: InvalidArgument. Must be scalar, enum, or input object, not OBJECT."
308+
assert_equal expected_message, err.message
309+
end
310+
end
269311
end

0 commit comments

Comments
 (0)