graphql 2.3.14 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  3. data/lib/generators/graphql/templates/base_resolver.erb +2 -0
  4. data/lib/generators/graphql/type_generator.rb +1 -1
  5. data/lib/graphql/analysis.rb +1 -1
  6. data/lib/graphql/dataloader/async_dataloader.rb +3 -2
  7. data/lib/graphql/dataloader/source.rb +1 -1
  8. data/lib/graphql/dataloader.rb +31 -10
  9. data/lib/graphql/execution/interpreter/resolve.rb +10 -6
  10. data/lib/graphql/invalid_null_error.rb +1 -1
  11. data/lib/graphql/language/comment.rb +18 -0
  12. data/lib/graphql/language/document_from_schema_definition.rb +38 -4
  13. data/lib/graphql/language/lexer.rb +15 -12
  14. data/lib/graphql/language/nodes.rb +22 -14
  15. data/lib/graphql/language/parser.rb +5 -0
  16. data/lib/graphql/language/printer.rb +23 -7
  17. data/lib/graphql/language.rb +6 -5
  18. data/lib/graphql/query/null_context.rb +1 -1
  19. data/lib/graphql/query.rb +49 -16
  20. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +23 -8
  21. data/lib/graphql/schema/always_visible.rb +6 -3
  22. data/lib/graphql/schema/argument.rb +14 -1
  23. data/lib/graphql/schema/build_from_definition.rb +1 -0
  24. data/lib/graphql/schema/enum.rb +3 -0
  25. data/lib/graphql/schema/enum_value.rb +9 -1
  26. data/lib/graphql/schema/field.rb +35 -14
  27. data/lib/graphql/schema/input_object.rb +20 -7
  28. data/lib/graphql/schema/interface.rb +1 -0
  29. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
  30. data/lib/graphql/schema/member/has_arguments.rb +2 -2
  31. data/lib/graphql/schema/member/has_fields.rb +2 -2
  32. data/lib/graphql/schema/printer.rb +1 -0
  33. data/lib/graphql/schema/resolver.rb +3 -4
  34. data/lib/graphql/schema/validator/required_validator.rb +28 -4
  35. data/lib/graphql/schema/visibility/migration.rb +186 -0
  36. data/lib/graphql/schema/visibility/profile.rb +523 -0
  37. data/lib/graphql/schema/visibility.rb +75 -0
  38. data/lib/graphql/schema/warden.rb +77 -15
  39. data/lib/graphql/schema.rb +203 -61
  40. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +2 -1
  41. data/lib/graphql/static_validation/rules/directives_are_defined.rb +2 -1
  42. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  43. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +2 -1
  44. data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -0
  45. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +11 -1
  46. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +10 -1
  47. data/lib/graphql/static_validation/validation_context.rb +15 -0
  48. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -1
  49. data/lib/graphql/subscriptions.rb +3 -1
  50. data/lib/graphql/testing/helpers.rb +2 -1
  51. data/lib/graphql/tracing/notifications_trace.rb +2 -2
  52. data/lib/graphql/version.rb +1 -1
  53. metadata +11 -9
  54. data/lib/graphql/schema/subset.rb +0 -509
  55. data/lib/graphql/schema/types_migration.rb +0 -187
@@ -19,6 +19,10 @@ module GraphQL
19
19
  PassThruWarden
20
20
  end
21
21
 
22
+ def self.use(schema)
23
+ # no-op
24
+ end
25
+
22
26
  # @param visibility_method [Symbol] a Warden method to call for this entry
23
27
  # @param entry [Object, Array<Object>] One or more definitions for a given name in a GraphQL Schema
24
28
  # @param context [GraphQL::Query::Context]
@@ -61,8 +65,8 @@ module GraphQL
61
65
  def interface_type_memberships(obj_t, ctx); obj_t.interface_type_memberships; end
62
66
  def arguments(owner, ctx); owner.arguments(ctx); end
63
67
  def loadable?(type, ctx); type.visible?(ctx); end
64
- def schema_subset
65
- @schema_subset ||= Warden::SchemaSubset.new(self)
68
+ def visibility_profile
69
+ @visibility_profile ||= Warden::VisibilityProfile.new(self)
66
70
  end
67
71
  end
68
72
  end
@@ -70,17 +74,20 @@ module GraphQL
70
74
  class NullWarden
71
75
  def initialize(_filter = nil, context:, schema:)
72
76
  @schema = schema
73
- @schema_subset = Warden::SchemaSubset.new(self)
77
+ @visibility_profile = Warden::VisibilityProfile.new(self)
74
78
  end
75
79
 
80
+ # No-op, but for compatibility:
81
+ attr_writer :skip_warning
82
+
76
83
  # @api private
77
- module NullSubset
84
+ module NullVisibilityProfile
78
85
  def self.new(context:, schema:)
79
- NullWarden.new(context: context, schema: schema).schema_subset
86
+ NullWarden.new(context: context, schema: schema).visibility_profile
80
87
  end
81
88
  end
82
89
 
83
- attr_reader :schema_subset
90
+ attr_reader :visibility_profile
84
91
 
85
92
  def visible_field?(field_defn, _ctx = nil, owner = nil); true; end
86
93
  def visible_argument?(arg_defn, _ctx = nil); true; end
@@ -88,7 +95,7 @@ module GraphQL
88
95
  def visible_enum_value?(enum_value, _ctx = nil); true; end
89
96
  def visible_type_membership?(type_membership, _ctx = nil); true; end
90
97
  def interface_type_memberships(obj_type, _ctx = nil); obj_type.interface_type_memberships; end
91
- def get_type(type_name); @schema.get_type(type_name); end # rubocop:disable Development/ContextIsPassedCop
98
+ def get_type(type_name); @schema.get_type(type_name, Query::NullContext.instance, false); end # rubocop:disable Development/ContextIsPassedCop
92
99
  def arguments(argument_owner, ctx = nil); argument_owner.all_argument_definitions; end
93
100
  def enum_values(enum_defn); enum_defn.enum_values; end # rubocop:disable Development/ContextIsPassedCop
94
101
  def get_argument(parent_type, argument_name); parent_type.get_argument(argument_name); end # rubocop:disable Development/ContextIsPassedCop
@@ -100,15 +107,15 @@ module GraphQL
100
107
  def reachable_type?(type_name); true; end
101
108
  def loadable?(type, _ctx); true; end
102
109
  def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
103
- def possible_types(type_defn); @schema.possible_types(type_defn); end
110
+ def possible_types(type_defn); @schema.possible_types(type_defn, Query::NullContext.instance, false); end
104
111
  def interfaces(obj_type); obj_type.interfaces; end
105
112
  end
106
113
 
107
- def schema_subset
108
- @schema_subset ||= SchemaSubset.new(self)
114
+ def visibility_profile
115
+ @visibility_profile ||= VisibilityProfile.new(self)
109
116
  end
110
117
 
111
- class SchemaSubset
118
+ class VisibilityProfile
112
119
  def initialize(warden)
113
120
  @warden = warden
114
121
  end
@@ -187,16 +194,19 @@ module GraphQL
187
194
  @mutation = @schema.mutation
188
195
  @subscription = @schema.subscription
189
196
  @context = context
190
- @visibility_cache = read_through { |m| schema.visible?(m, context) }
197
+ @visibility_cache = read_through { |m| check_visible(schema, m) }
191
198
  # Initialize all ivars to improve object shape consistency:
192
199
  @types = @visible_types = @reachable_types = @visible_parent_fields =
193
200
  @visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
194
201
  @visible_enum_values = @visible_interfaces = @type_visibility = @type_memberships =
195
202
  @visible_and_reachable_type = @unions = @unfiltered_interfaces =
196
- @reachable_type_set = @schema_subset =
203
+ @reachable_type_set = @visibility_profile =
197
204
  nil
205
+ @skip_warning = schema.plugins.any? { |(plugin, _opts)| plugin == GraphQL::Schema::Warden }
198
206
  end
199
207
 
208
+ attr_writer :skip_warning
209
+
200
210
  # @return [Hash<String, GraphQL::BaseType>] Visible types in the schema
201
211
  def types
202
212
  @types ||= begin
@@ -218,7 +228,7 @@ module GraphQL
218
228
  # @return [GraphQL::BaseType, nil] The type named `type_name`, if it exists (else `nil`)
219
229
  def get_type(type_name)
220
230
  @visible_types ||= read_through do |name|
221
- type_defn = @schema.get_type(name, @context)
231
+ type_defn = @schema.get_type(name, @context, false)
222
232
  if type_defn && visible_and_reachable_type?(type_defn)
223
233
  type_defn
224
234
  else
@@ -265,7 +275,7 @@ module GraphQL
265
275
  # @return [Array<GraphQL::BaseType>] The types which may be member of `type_defn`
266
276
  def possible_types(type_defn)
267
277
  @visible_possible_types ||= read_through { |type_defn|
268
- pt = @schema.possible_types(type_defn, @context)
278
+ pt = @schema.possible_types(type_defn, @context, false)
269
279
  pt.select { |t| visible_and_reachable_type?(t) }
270
280
  }
271
281
  @visible_possible_types[type_defn]
@@ -465,6 +475,58 @@ module GraphQL
465
475
  Hash.new { |h, k| h[k] = yield(k) }.compare_by_identity
466
476
  end
467
477
 
478
+ def check_visible(schema, member)
479
+ if schema.visible?(member, @context)
480
+ true
481
+ elsif @skip_warning
482
+ false
483
+ else
484
+ member_s = member.respond_to?(:path) ? member.path : member.inspect
485
+ member_type = case member
486
+ when Module
487
+ if member.respond_to?(:kind)
488
+ member.kind.name.downcase
489
+ else
490
+ ""
491
+ end
492
+ when GraphQL::Schema::Field
493
+ "field"
494
+ when GraphQL::Schema::EnumValue
495
+ "enum value"
496
+ when GraphQL::Schema::Argument
497
+ "argument"
498
+ else
499
+ ""
500
+ end
501
+
502
+ schema_s = schema.name ? "#{schema.name}'s" : ""
503
+ schema_name = schema.name ? "#{schema.name}" : "your schema"
504
+ warn(ADD_WARDEN_WARNING % { schema_s: schema_s, schema_name: schema_name, member: member_s, member_type: member_type })
505
+ @skip_warning = true # only warn once per query
506
+ # If there's no schema name, add the backtrace for additional context:
507
+ if schema_s == ""
508
+ puts caller.map { |l| " #{l}"}
509
+ end
510
+ false
511
+ end
512
+ end
513
+
514
+ ADD_WARDEN_WARNING = <<~WARNING
515
+ DEPRECATION: %{schema_s} "%{member}" %{member_type} returned `false` for `.visible?` but `GraphQL::Schema::Visibility` isn't configured yet.
516
+
517
+ Address this warning by adding:
518
+
519
+ use GraphQL::Schema::Visibility
520
+
521
+ to the definition for %{schema_name}. (Future GraphQL-Ruby versions won't check `.visible?` methods by default.)
522
+
523
+ Alternatively, for legacy behavior, add:
524
+
525
+ use GraphQL::Schema::Warden # legacy visibility behavior
526
+
527
+ For more information see: https://graphql-ruby.org/authorization/visibility.html
528
+ WARNING
529
+
468
530
  def reachable_type_set
469
531
  return @reachable_type_set if @reachable_type_set
470
532