graphql 1.12.18 → 1.12.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +7 -1
- data/lib/graphql/schema/resolver.rb +10 -0
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/format_validator.rb +2 -1
- data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/length_validator.rb +5 -3
- data/lib/graphql/schema/validator/numericality_validator.rb +7 -1
- data/lib/graphql/schema/validator.rb +36 -25
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92aba0a1935a0022b97ea1630cde64884a727ce714fae6a2bca543666c73bde0
|
4
|
+
data.tar.gz: 5db896ad77a52ec4a025f526bab4f3c4b3d18206e009c2d8c3e14dd434f12ae6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2985936af9bba4d0feec8263dd4a6c60c09110e39aba1a97359e4d02900732f02900e30d798074932bb6fe2a5ed0e00441be859bb3035ab0c819ccec3c9a0f66
|
7
|
+
data.tar.gz: e8e961e540b54a5c54d6d78c444eef422bd55264ee8ffc9c3a231f2614c570ee75de5c2888f3b13974304c48f60072e04bb0d0444ea6e1a13f4a37652dbd2f0b
|
@@ -12,9 +12,25 @@ module GraphQL
|
|
12
12
|
# The value which couldn't be encoded
|
13
13
|
attr_reader :integer_value
|
14
14
|
|
15
|
-
|
15
|
+
# @return [GraphQL::Schema::Field] The field that returned a too-big integer
|
16
|
+
attr_reader :field
|
17
|
+
|
18
|
+
# @return [Array<String, Integer>] Where the field appeared in the GraphQL response
|
19
|
+
attr_reader :path
|
20
|
+
|
21
|
+
def initialize(value, context:)
|
16
22
|
@integer_value = value
|
17
|
-
|
23
|
+
@field = context[:current_field]
|
24
|
+
@path = context[:current_path]
|
25
|
+
message = "Integer out of bounds: #{value}".dup
|
26
|
+
if @path
|
27
|
+
message << " @ #{@path.join(".")}"
|
28
|
+
end
|
29
|
+
if @field
|
30
|
+
message << " (#{@field.path})"
|
31
|
+
end
|
32
|
+
message << ". Consider using ID or GraphQL::Types::BigInt instead."
|
33
|
+
super(message)
|
18
34
|
end
|
19
35
|
end
|
20
36
|
end
|
@@ -72,7 +72,7 @@ module GraphQL
|
|
72
72
|
elsif @operation_name_error
|
73
73
|
@validation_errors << @operation_name_error
|
74
74
|
else
|
75
|
-
validation_result = @schema.static_validator.validate(@query, validate: @validate, timeout: @schema.validate_timeout)
|
75
|
+
validation_result = @schema.static_validator.validate(@query, validate: @validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
|
76
76
|
@validation_errors.concat(validation_result[:errors])
|
77
77
|
@internal_representation = validation_result[:irep]
|
78
78
|
|
@@ -254,11 +254,17 @@ module GraphQL
|
|
254
254
|
if authed
|
255
255
|
application_object
|
256
256
|
else
|
257
|
-
|
257
|
+
err = GraphQL::UnauthorizedError.new(
|
258
258
|
object: application_object,
|
259
259
|
type: class_based_type,
|
260
260
|
context: context,
|
261
261
|
)
|
262
|
+
if self.respond_to?(:unauthorized_object)
|
263
|
+
err.set_backtrace(caller)
|
264
|
+
unauthorized_object(err)
|
265
|
+
else
|
266
|
+
raise err
|
267
|
+
end
|
262
268
|
end
|
263
269
|
end
|
264
270
|
else
|
@@ -160,6 +160,16 @@ module GraphQL
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
+
# Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
|
164
|
+
#
|
165
|
+
# By default, the error is re-raised and passed along to {{Schema.unauthorized_object}}.
|
166
|
+
#
|
167
|
+
# Any value returned here will be used _instead of_ of the loaded object.
|
168
|
+
# @param err [GraphQL::UnauthorizedError]
|
169
|
+
def unauthorized_object(err)
|
170
|
+
raise err
|
171
|
+
end
|
172
|
+
|
163
173
|
private
|
164
174
|
|
165
175
|
def load_arguments(args)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Validator
|
6
|
+
# Use this to specifically reject values that respond to `.blank?` and respond truthy for that method.
|
7
|
+
#
|
8
|
+
# @example Require a non-empty string for an argument
|
9
|
+
# argument :name, String, required: true, validate: { allow_blank: false }
|
10
|
+
class AllowBlankValidator < Validator
|
11
|
+
def initialize(allow_blank_positional, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
|
12
|
+
@message = message
|
13
|
+
super(**default_options)
|
14
|
+
@allow_blank = allow_blank.nil? ? allow_blank_positional : allow_blank
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate(_object, _context, value)
|
18
|
+
if value.respond_to?(:blank?) && value.blank?
|
19
|
+
if (value.nil? && @allow_null) || @allow_blank
|
20
|
+
# pass
|
21
|
+
else
|
22
|
+
@message
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Validator
|
6
|
+
# Use this to specifically reject or permit `nil` values (given as `null` from GraphQL).
|
7
|
+
#
|
8
|
+
# @example require a non-null value for an argument if it is provided
|
9
|
+
# argument :name, String, required: false, validates: { allow_null: false }
|
10
|
+
class AllowNullValidator < Validator
|
11
|
+
MESSAGE = "%{validated} can't be null"
|
12
|
+
def initialize(allow_null_positional, allow_null: nil, message: MESSAGE, **default_options)
|
13
|
+
@message = message
|
14
|
+
super(**default_options)
|
15
|
+
@allow_null = allow_null.nil? ? allow_null_positional : allow_null
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate(_object, _context, value)
|
19
|
+
if value.nil? && !@allow_null
|
20
|
+
@message
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -38,7 +38,8 @@ module GraphQL
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def validate(_object, _context, value)
|
41
|
-
if
|
41
|
+
if value.nil? ||
|
42
|
+
(@with_pattern && !value.match?(@with_pattern)) ||
|
42
43
|
(@without_pattern && value.match?(@without_pattern))
|
43
44
|
@message
|
44
45
|
end
|
@@ -43,11 +43,13 @@ module GraphQL
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def validate(_object, _context, value)
|
46
|
-
if
|
46
|
+
return if permitted_empty_value?(value) # pass in this case
|
47
|
+
length = value.nil? ? 0 : value.length
|
48
|
+
if @maximum && length > @maximum
|
47
49
|
partial_format(@too_long, { count: @maximum })
|
48
|
-
elsif @minimum &&
|
50
|
+
elsif @minimum && length < @minimum
|
49
51
|
partial_format(@too_short, { count: @minimum })
|
50
|
-
elsif @is &&
|
52
|
+
elsif @is && length != @is
|
51
53
|
partial_format(@wrong_length, { count: @is })
|
52
54
|
end
|
53
55
|
end
|
@@ -32,6 +32,7 @@ module GraphQL
|
|
32
32
|
equal_to: nil, other_than: nil,
|
33
33
|
odd: nil, even: nil, within: nil,
|
34
34
|
message: "%{validated} must be %{comparison} %{target}",
|
35
|
+
null_message: Validator::AllowNullValidator::MESSAGE,
|
35
36
|
**default_options
|
36
37
|
)
|
37
38
|
|
@@ -45,11 +46,16 @@ module GraphQL
|
|
45
46
|
@even = even
|
46
47
|
@within = within
|
47
48
|
@message = message
|
49
|
+
@null_message = null_message
|
48
50
|
super(**default_options)
|
49
51
|
end
|
50
52
|
|
51
53
|
def validate(object, context, value)
|
52
|
-
if
|
54
|
+
if permitted_empty_value?(value)
|
55
|
+
# pass in this case
|
56
|
+
elsif value.nil? # @allow_null is handled in the parent class
|
57
|
+
@null_message
|
58
|
+
elsif @greater_than && value <= @greater_than
|
53
59
|
partial_format(@message, { comparison: "greater than", target: @greater_than })
|
54
60
|
elsif @greater_than_or_equal_to && value < @greater_than_or_equal_to
|
55
61
|
partial_format(@message, { comparison: "greater than or equal to", target: @greater_than_or_equal_to })
|
@@ -7,7 +7,6 @@ module GraphQL
|
|
7
7
|
# @return [GraphQL::Schema::Argument, GraphQL::Schema::Field, GraphQL::Schema::Resolver, Class<GraphQL::Schema::InputObject>]
|
8
8
|
attr_reader :validated
|
9
9
|
|
10
|
-
# TODO should this implement `if:` and `unless:` ?
|
11
10
|
# @param validated [GraphQL::Schema::Argument, GraphQL::Schema::Field, GraphQL::Schema::Resolver, Class<GraphQL::Schema::InputObject>] The argument or argument owner this validator is attached to
|
12
11
|
# @param allow_blank [Boolean] if `true`, then objects that respond to `.blank?` and return true for `.blank?` will skip this validation
|
13
12
|
# @param allow_null [Boolean] if `true`, then incoming `null`s will skip this validation
|
@@ -25,26 +24,6 @@ module GraphQL
|
|
25
24
|
raise GraphQL::RequiredImplementationMissingError, "Validator classes should implement #validate"
|
26
25
|
end
|
27
26
|
|
28
|
-
# This is called by the validation system and eventually calls {#validate}.
|
29
|
-
# @api private
|
30
|
-
def apply(object, context, value)
|
31
|
-
if value.nil?
|
32
|
-
if @allow_null
|
33
|
-
nil # skip this
|
34
|
-
else
|
35
|
-
"%{validated} can't be null"
|
36
|
-
end
|
37
|
-
elsif value.respond_to?(:blank?) && value.blank?
|
38
|
-
if @allow_blank
|
39
|
-
nil # skip this
|
40
|
-
else
|
41
|
-
"%{validated} can't be blank"
|
42
|
-
end
|
43
|
-
else
|
44
|
-
validate(object, context, value)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
27
|
# This is like `String#%`, but it supports the case that only some of `string`'s
|
49
28
|
# values are present in `substitutions`
|
50
29
|
def partial_format(string, substitutions)
|
@@ -55,6 +34,12 @@ module GraphQL
|
|
55
34
|
string
|
56
35
|
end
|
57
36
|
|
37
|
+
# @return [Boolean] `true` if `value` is `nil` and this validator has `allow_null: true` or if value is `.blank?` and this validator has `allow_blank: true`
|
38
|
+
def permitted_empty_value?(value)
|
39
|
+
(value.nil? && @allow_null) ||
|
40
|
+
(@allow_blank && value.respond_to?(:blank?) && value.blank?)
|
41
|
+
end
|
42
|
+
|
58
43
|
# @param schema_member [GraphQL::Schema::Field, GraphQL::Schema::Argument, Class<GraphQL::Schema::InputObject>]
|
59
44
|
# @param validates_hash [Hash{Symbol => Hash}, Hash{Class => Hash} nil] A configuration passed as `validates:`
|
60
45
|
# @return [Array<Validator>]
|
@@ -62,6 +47,24 @@ module GraphQL
|
|
62
47
|
if validates_hash.nil? || validates_hash.empty?
|
63
48
|
EMPTY_ARRAY
|
64
49
|
else
|
50
|
+
validates_hash = validates_hash.dup
|
51
|
+
allow_null = validates_hash.delete(:allow_null)
|
52
|
+
allow_blank = validates_hash.delete(:allow_blank)
|
53
|
+
|
54
|
+
# This could be {...}.compact on Ruby 2.4+
|
55
|
+
default_options = {}
|
56
|
+
if !allow_null.nil?
|
57
|
+
default_options[:allow_null] = allow_null
|
58
|
+
end
|
59
|
+
if !allow_blank.nil?
|
60
|
+
default_options[:allow_blank] = allow_blank
|
61
|
+
end
|
62
|
+
|
63
|
+
# allow_nil or allow_blank are the _only_ validations:
|
64
|
+
if validates_hash.empty?
|
65
|
+
validates_hash = default_options
|
66
|
+
end
|
67
|
+
|
65
68
|
validates_hash.map do |validator_name, options|
|
66
69
|
validator_class = case validator_name
|
67
70
|
when Class
|
@@ -69,7 +72,11 @@ module GraphQL
|
|
69
72
|
else
|
70
73
|
all_validators[validator_name] || raise(ArgumentError, "unknown validation: #{validator_name.inspect}")
|
71
74
|
end
|
72
|
-
|
75
|
+
if options.is_a?(Hash)
|
76
|
+
validator_class.new(validated: schema_member, **(default_options.merge(options)))
|
77
|
+
else
|
78
|
+
validator_class.new(options, validated: schema_member, **default_options)
|
79
|
+
end
|
73
80
|
end
|
74
81
|
end
|
75
82
|
end
|
@@ -122,10 +129,10 @@ module GraphQL
|
|
122
129
|
|
123
130
|
validators.each do |validator|
|
124
131
|
validated = as || validator.validated
|
125
|
-
errors = validator.
|
132
|
+
errors = validator.validate(object, context, value)
|
126
133
|
if errors &&
|
127
|
-
|
128
|
-
|
134
|
+
(errors.is_a?(Array) && errors != EMPTY_ARRAY) ||
|
135
|
+
(errors.is_a?(String))
|
129
136
|
if all_errors.frozen? # It's empty
|
130
137
|
all_errors = []
|
131
138
|
end
|
@@ -161,3 +168,7 @@ require "graphql/schema/validator/exclusion_validator"
|
|
161
168
|
GraphQL::Schema::Validator.install(:exclusion, GraphQL::Schema::Validator::ExclusionValidator)
|
162
169
|
require "graphql/schema/validator/required_validator"
|
163
170
|
GraphQL::Schema::Validator.install(:required, GraphQL::Schema::Validator::RequiredValidator)
|
171
|
+
require "graphql/schema/validator/allow_null_validator"
|
172
|
+
GraphQL::Schema::Validator.install(:allow_null, GraphQL::Schema::Validator::AllowNullValidator)
|
173
|
+
require "graphql/schema/validator/allow_blank_validator"
|
174
|
+
GraphQL::Schema::Validator.install(:allow_blank, GraphQL::Schema::Validator::AllowBlankValidator)
|
@@ -1,10 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module GraphQL
|
3
3
|
class StringEncodingError < GraphQL::RuntimeTypeError
|
4
|
-
attr_reader :string
|
5
|
-
def initialize(str)
|
4
|
+
attr_reader :string, :field, :path
|
5
|
+
def initialize(str, context:)
|
6
6
|
@string = str
|
7
|
-
|
7
|
+
@field = context[:current_field]
|
8
|
+
@path = context[:current_path]
|
9
|
+
message = "String #{str.inspect} was encoded as #{str.encoding}".dup
|
10
|
+
if @path
|
11
|
+
message << " @ #{@path.join(".")}"
|
12
|
+
end
|
13
|
+
if @field
|
14
|
+
message << " (#{@field.path})"
|
15
|
+
end
|
16
|
+
message << ". GraphQL requires an encoding compatible with UTF-8."
|
17
|
+
super(message)
|
8
18
|
end
|
9
19
|
end
|
10
20
|
end
|
data/lib/graphql/types/int.rb
CHANGED
data/lib/graphql/types/string.rb
CHANGED
@@ -12,7 +12,7 @@ module GraphQL
|
|
12
12
|
attr_reader :type
|
13
13
|
|
14
14
|
# @return [GraphQL::Query::Context] the context for the current query
|
15
|
-
|
15
|
+
attr_accessor :context
|
16
16
|
|
17
17
|
def initialize(message = nil, object: nil, type: nil, context: nil)
|
18
18
|
if message.nil? && object.nil? && type.nil?
|
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: 1.12.
|
4
|
+
version: 1.12.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -544,6 +544,8 @@ files:
|
|
544
544
|
- lib/graphql/schema/unique_within_type.rb
|
545
545
|
- lib/graphql/schema/validation.rb
|
546
546
|
- lib/graphql/schema/validator.rb
|
547
|
+
- lib/graphql/schema/validator/allow_blank_validator.rb
|
548
|
+
- lib/graphql/schema/validator/allow_null_validator.rb
|
547
549
|
- lib/graphql/schema/validator/exclusion_validator.rb
|
548
550
|
- lib/graphql/schema/validator/format_validator.rb
|
549
551
|
- lib/graphql/schema/validator/inclusion_validator.rb
|