graphql 2.0.12 → 2.0.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/execution/interpreter/runtime.rb +2 -4
- data/lib/graphql/query/variable_validation_error.rb +2 -2
- data/lib/graphql/query/variables.rb +13 -3
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/schema/argument.rb +15 -3
- data/lib/graphql/schema/enum.rb +1 -1
- data/lib/graphql/schema/field.rb +12 -11
- data/lib/graphql/schema/input_object.rb +1 -1
- data/lib/graphql/schema/list.rb +19 -5
- data/lib/graphql/schema/member/validates_input.rb +2 -2
- data/lib/graphql/schema/non_null.rb +2 -2
- data/lib/graphql/schema/scalar.rb +1 -1
- data/lib/graphql/static_validation/error.rb +2 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +12 -6
- data/lib/graphql/subscriptions.rb +2 -5
- data/lib/graphql/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8f389d3b7c8052a74ccd4bd9e8412a1fa9d93415e6caeec883b8f179a167395
|
4
|
+
data.tar.gz: f2e6ab7ba5c1e76b0c44557855ab3af55fb2b718b8de1ff6483917de603734b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10a24271a65c65a402d3243d2e43b3b257f74eb7bbc0ec13c254304bdce3122c444a41fbccf943bd3d626d301aec4b973485f742b831e8658ea252a0c95cfcfa
|
7
|
+
data.tar.gz: 9762008c699f2a53b14913e057dc31ec6c97b4203b1dd28a7a2a4fc18153d5bc200d0a95e3d2a04da80d0486131f5b1ce8d597e1ad6a7085b0766e35e0982959
|
@@ -401,8 +401,7 @@ module GraphQL
|
|
401
401
|
end
|
402
402
|
return_type = field_defn.type
|
403
403
|
|
404
|
-
next_path = path
|
405
|
-
next_path << result_name
|
404
|
+
next_path = path + [result_name]
|
406
405
|
next_path.freeze
|
407
406
|
|
408
407
|
# This seems janky, but we need to know
|
@@ -768,8 +767,7 @@ module GraphQL
|
|
768
767
|
set_result(selection_result, result_name, response_list)
|
769
768
|
result_was_set = true
|
770
769
|
end
|
771
|
-
next_path = path
|
772
|
-
next_path << idx
|
770
|
+
next_path = path + [idx]
|
773
771
|
this_idx = idx
|
774
772
|
next_path.freeze
|
775
773
|
idx += 1
|
@@ -4,11 +4,11 @@ module GraphQL
|
|
4
4
|
class VariableValidationError < GraphQL::ExecutionError
|
5
5
|
attr_accessor :value, :validation_result
|
6
6
|
|
7
|
-
def initialize(variable_ast, type, value, validation_result)
|
7
|
+
def initialize(variable_ast, type, value, validation_result, msg: nil)
|
8
8
|
@value = value
|
9
9
|
@validation_result = validation_result
|
10
10
|
|
11
|
-
msg
|
11
|
+
msg ||= "Variable $#{variable_ast.name} of type #{type.to_type_signature} was provided invalid value"
|
12
12
|
|
13
13
|
if problem_fields.any?
|
14
14
|
msg += " for #{problem_fields.join(", ")}"
|
@@ -17,6 +17,10 @@ module GraphQL
|
|
17
17
|
@provided_variables = deep_stringify(provided_variables)
|
18
18
|
@errors = []
|
19
19
|
@storage = ast_variables.each_with_object({}) do |ast_variable, memo|
|
20
|
+
if schema.validate_max_errors && schema.validate_max_errors <= @errors.count
|
21
|
+
add_max_errors_reached_message
|
22
|
+
break
|
23
|
+
end
|
20
24
|
# Find the right value for this variable:
|
21
25
|
# - First, use the value provided at runtime
|
22
26
|
# - Then, fall back to the default value from the query string
|
@@ -29,8 +33,9 @@ module GraphQL
|
|
29
33
|
default_value = ast_variable.default_value
|
30
34
|
provided_value = @provided_variables[variable_name]
|
31
35
|
value_was_provided = @provided_variables.key?(variable_name)
|
36
|
+
max_errors = schema.validate_max_errors - @errors.count if schema.validate_max_errors
|
32
37
|
begin
|
33
|
-
validation_result = variable_type.validate_input(provided_value, ctx)
|
38
|
+
validation_result = variable_type.validate_input(provided_value, ctx, max_errors: max_errors)
|
34
39
|
if validation_result.valid?
|
35
40
|
if value_was_provided
|
36
41
|
# Add the variable if a value was provided
|
@@ -48,8 +53,7 @@ module GraphQL
|
|
48
53
|
# like InputValidationResults generated by validate_non_null_input but unfortunately we don't
|
49
54
|
# have this information available in the coerce_input call chain. Note this path is the path
|
50
55
|
# that appears under errors.extensions.problems.path and NOT the result path under errors.path.
|
51
|
-
validation_result = GraphQL::Query::InputValidationResult.
|
52
|
-
validation_result.add_problem(ex.message)
|
56
|
+
validation_result = GraphQL::Query::InputValidationResult.from_problem(ex.message)
|
53
57
|
end
|
54
58
|
|
55
59
|
if !validation_result.valid?
|
@@ -76,6 +80,12 @@ module GraphQL
|
|
76
80
|
else
|
77
81
|
val
|
78
82
|
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_max_errors_reached_message
|
86
|
+
message = "Too many errors processing variables, max validation error limit reached. Execution aborted"
|
87
|
+
validation_result = GraphQL::Query::InputValidationResult.from_problem(message)
|
88
|
+
errors << GraphQL::Query::VariableValidationError.new(nil, nil, nil, validation_result, msg: message)
|
79
89
|
end
|
80
90
|
end
|
81
91
|
end
|
@@ -15,7 +15,7 @@ module GraphQL
|
|
15
15
|
puts "Validating graphql-pro v#{version}"
|
16
16
|
puts " - Checking for graphql-pro credentials..."
|
17
17
|
|
18
|
-
creds = `bundle config gems.graphql.pro`[/[a-z0-9]{11}:[a-z0-9]{11}/]
|
18
|
+
creds = `bundle config gems.graphql.pro --parseable`[/[a-z0-9]{11}:[a-z0-9]{11}/]
|
19
19
|
if creds.nil?
|
20
20
|
puts " #{ex} failed, please set with `bundle config gems.graphql.pro $MY_CREDENTIALS`"
|
21
21
|
exit(1)
|
@@ -18,8 +18,14 @@ module GraphQL
|
|
18
18
|
# @return [GraphQL::Schema::Field, Class] The field or input object this argument belongs to
|
19
19
|
attr_reader :owner
|
20
20
|
|
21
|
-
# @
|
22
|
-
|
21
|
+
# @param new_prepare [Method, Proc]
|
22
|
+
# @return [Symbol] A method or proc to call to transform this value before sending it to field resolution method
|
23
|
+
def prepare(new_prepare = NO_DEFAULT)
|
24
|
+
if new_prepare != NO_DEFAULT
|
25
|
+
@prepare = new_prepare
|
26
|
+
end
|
27
|
+
@prepare
|
28
|
+
end
|
23
29
|
|
24
30
|
# @return [Symbol] This argument's name in Ruby keyword arguments
|
25
31
|
attr_reader :keyword
|
@@ -96,8 +102,14 @@ module GraphQL
|
|
96
102
|
"#<#{self.class} #{path}: #{type.to_type_signature}#{description ? " @description=#{description.inspect}" : ""}>"
|
97
103
|
end
|
98
104
|
|
105
|
+
# @param default_value [Object] The value to use when the client doesn't provide one
|
99
106
|
# @return [Object] the value used when the client doesn't provide a value for this argument
|
100
|
-
|
107
|
+
def default_value(new_default_value = NO_DEFAULT)
|
108
|
+
if new_default_value != NO_DEFAULT
|
109
|
+
@default_value = new_default_value
|
110
|
+
end
|
111
|
+
@default_value
|
112
|
+
end
|
101
113
|
|
102
114
|
# @return [Boolean] True if this argument has a default value
|
103
115
|
def default_value?
|
data/lib/graphql/schema/enum.rb
CHANGED
@@ -122,7 +122,7 @@ module GraphQL
|
|
122
122
|
GraphQL::TypeKinds::ENUM
|
123
123
|
end
|
124
124
|
|
125
|
-
def validate_non_null_input(value_name, ctx)
|
125
|
+
def validate_non_null_input(value_name, ctx, max_errors: nil)
|
126
126
|
allowed_values = ctx.warden.enum_values(self)
|
127
127
|
matching_value = allowed_values.find { |v| v.graphql_name == value_name }
|
128
128
|
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -666,7 +666,18 @@ module GraphQL
|
|
666
666
|
inner_object = obj.object
|
667
667
|
|
668
668
|
if defined?(@hash_key)
|
669
|
-
|
669
|
+
hash_value = if inner_object.is_a?(Hash)
|
670
|
+
inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
|
671
|
+
elsif inner_object.respond_to?(:[])
|
672
|
+
inner_object[@hash_key]
|
673
|
+
else
|
674
|
+
nil
|
675
|
+
end
|
676
|
+
if hash_value == false
|
677
|
+
hash_value
|
678
|
+
else
|
679
|
+
hash_value || (@fallback_value != :not_given ? @fallback_value : nil)
|
680
|
+
end
|
670
681
|
elsif obj.respond_to?(resolver_method)
|
671
682
|
method_to_call = resolver_method
|
672
683
|
method_receiver = obj
|
@@ -679,16 +690,6 @@ module GraphQL
|
|
679
690
|
elsif inner_object.is_a?(Hash)
|
680
691
|
if @dig_keys
|
681
692
|
inner_object.dig(*@dig_keys)
|
682
|
-
elsif defined?(@hash_key)
|
683
|
-
if inner_object.key?(@hash_key)
|
684
|
-
inner_object[@hash_key]
|
685
|
-
elsif inner_object.key?(@hash_key_str)
|
686
|
-
inner_object[@hash_key_str]
|
687
|
-
elsif @fallback_value != :not_given
|
688
|
-
@fallback_value
|
689
|
-
else
|
690
|
-
nil
|
691
|
-
end
|
692
693
|
elsif inner_object.key?(@method_sym)
|
693
694
|
inner_object[@method_sym]
|
694
695
|
elsif inner_object.key?(@method_str)
|
@@ -126,7 +126,7 @@ module GraphQL
|
|
126
126
|
# @api private
|
127
127
|
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object responding to `to_h` or `to_unsafe_h`."
|
128
128
|
|
129
|
-
def validate_non_null_input(input, ctx)
|
129
|
+
def validate_non_null_input(input, ctx, max_errors: nil)
|
130
130
|
warden = ctx.warden
|
131
131
|
|
132
132
|
if input.is_a?(Array)
|
data/lib/graphql/schema/list.rb
CHANGED
@@ -45,16 +45,24 @@ module GraphQL
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
def validate_non_null_input(value, ctx)
|
49
|
-
result =
|
48
|
+
def validate_non_null_input(value, ctx, max_errors: nil)
|
49
|
+
result = GraphQL::Query::InputValidationResult.new
|
50
50
|
ensure_array(value).each_with_index do |item, index|
|
51
51
|
item_result = of_type.validate_input(item, ctx)
|
52
|
-
|
53
|
-
|
52
|
+
unless item_result.valid?
|
53
|
+
if max_errors
|
54
|
+
if max_errors == 0
|
55
|
+
add_max_errros_reached_message(result)
|
56
|
+
break
|
57
|
+
end
|
58
|
+
|
59
|
+
max_errors -= 1
|
60
|
+
end
|
61
|
+
|
54
62
|
result.merge_result!(index, item_result)
|
55
63
|
end
|
56
64
|
end
|
57
|
-
result
|
65
|
+
result.valid? ? nil : result
|
58
66
|
end
|
59
67
|
|
60
68
|
private
|
@@ -67,6 +75,12 @@ module GraphQL
|
|
67
75
|
[value]
|
68
76
|
end
|
69
77
|
end
|
78
|
+
|
79
|
+
def add_max_errros_reached_message(result)
|
80
|
+
message = "Too many errors processing list variable, max validation error limit reached. Execution aborted"
|
81
|
+
item_result = GraphQL::Query::InputValidationResult.from_problem(message)
|
82
|
+
result.merge_result!(nil, item_result)
|
83
|
+
end
|
70
84
|
end
|
71
85
|
end
|
72
86
|
end
|
@@ -8,11 +8,11 @@ module GraphQL
|
|
8
8
|
validate_input(val, ctx).valid?
|
9
9
|
end
|
10
10
|
|
11
|
-
def validate_input(val, ctx)
|
11
|
+
def validate_input(val, ctx, max_errors: nil)
|
12
12
|
if val.nil?
|
13
13
|
Query::InputValidationResult::VALID
|
14
14
|
else
|
15
|
-
validate_non_null_input(val, ctx) || Query::InputValidationResult::VALID
|
15
|
+
validate_non_null_input(val, ctx, max_errors: max_errors) || Query::InputValidationResult::VALID
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -31,13 +31,13 @@ module GraphQL
|
|
31
31
|
"#<#{self.class.name} @of_type=#{@of_type.inspect}>"
|
32
32
|
end
|
33
33
|
|
34
|
-
def validate_input(value, ctx)
|
34
|
+
def validate_input(value, ctx, max_errors: nil)
|
35
35
|
if value.nil?
|
36
36
|
result = GraphQL::Query::InputValidationResult.new
|
37
37
|
result.add_problem("Expected value to not be null")
|
38
38
|
result
|
39
39
|
else
|
40
|
-
of_type.validate_input(value, ctx)
|
40
|
+
of_type.validate_input(value, ctx, max_errors: max_errors)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -9,11 +9,17 @@ module GraphQL
|
|
9
9
|
|
10
10
|
def on_directive(node, parent)
|
11
11
|
if !@directive_names.include?(node.name)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
@directives_are_defined_errors_by_name ||= {}
|
13
|
+
error = @directives_are_defined_errors_by_name[node.name] ||= begin
|
14
|
+
err = GraphQL::StaticValidation::DirectivesAreDefinedError.new(
|
15
|
+
"Directive @#{node.name} is not defined",
|
16
|
+
nodes: [],
|
17
|
+
directive: node.name
|
18
|
+
)
|
19
|
+
add_error(err)
|
20
|
+
err
|
21
|
+
end
|
22
|
+
error.nodes << node
|
17
23
|
else
|
18
24
|
super
|
19
25
|
end
|
@@ -34,12 +34,18 @@ module GraphQL
|
|
34
34
|
used_directives = {}
|
35
35
|
node.directives.each do |ast_directive|
|
36
36
|
directive_name = ast_directive.name
|
37
|
-
if used_directives[directive_name]
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
if (first_node = used_directives[directive_name])
|
38
|
+
@directives_are_unique_errors_by_first_node ||= {}
|
39
|
+
err = @directives_are_unique_errors_by_first_node[first_node] ||= begin
|
40
|
+
error = GraphQL::StaticValidation::UniqueDirectivesPerLocationError.new(
|
41
|
+
"The directive \"#{directive_name}\" can only be used once at this location.",
|
42
|
+
nodes: [used_directives[directive_name]],
|
43
|
+
directive: directive_name,
|
44
|
+
)
|
45
|
+
add_error(error)
|
46
|
+
error
|
47
|
+
end
|
48
|
+
err.nodes << ast_directive
|
43
49
|
elsif !((dir_defn = context.schema_directives[directive_name]) && dir_defn.repeatable?)
|
44
50
|
used_directives[directive_name] = ast_directive
|
45
51
|
end
|
@@ -62,11 +62,8 @@ module GraphQL
|
|
62
62
|
# @return [void]
|
63
63
|
def trigger(event_name, args, object, scope: nil, context: {})
|
64
64
|
# Make something as context-like as possible, even though there isn't a current query:
|
65
|
-
|
66
|
-
|
67
|
-
object: nil,
|
68
|
-
values: context
|
69
|
-
)
|
65
|
+
dummy_query = GraphQL::Query.new(@schema, "", validate: false, context: context)
|
66
|
+
context = dummy_query.context
|
70
67
|
event_name = event_name.to_s
|
71
68
|
|
72
69
|
# Try with the verbatim input first:
|
data/lib/graphql/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|