graphql 1.12.12 → 2.4.8
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +3 -8
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +2 -0
- data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +60 -4
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +5 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +10 -38
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +23 -12
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +8 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/enum.erb +5 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +4 -2
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +3 -1
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/node_type.erb +2 -0
- data/lib/generators/graphql/templates/object.erb +4 -2
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/schema.erb +22 -2
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +46 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/analyzer.rb +89 -0
- data/lib/graphql/analysis/field_usage.rb +65 -28
- data/lib/graphql/analysis/max_query_complexity.rb +11 -17
- data/lib/graphql/analysis/max_query_depth.rb +13 -19
- data/lib/graphql/analysis/query_complexity.rb +156 -61
- data/lib/graphql/analysis/query_depth.rb +38 -23
- data/lib/graphql/analysis/visitor.rb +283 -0
- data/lib/graphql/analysis.rb +90 -6
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/inspect_result.rb +0 -12
- data/lib/graphql/backtrace/table.rb +4 -22
- data/lib/graphql/backtrace/trace.rb +93 -0
- data/lib/graphql/backtrace/tracer.rb +8 -6
- data/lib/graphql/backtrace.rb +3 -8
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/current.rb +52 -0
- data/lib/graphql/dataloader/async_dataloader.rb +89 -0
- data/lib/graphql/dataloader/null_dataloader.rb +4 -2
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +125 -33
- data/lib/graphql/dataloader.rb +193 -143
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/errors.rb +12 -81
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments.rb +2 -2
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -36
- data/lib/graphql/execution/interpreter/resolve.rb +38 -4
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +175 -0
- data/lib/graphql/execution/interpreter/runtime.rb +447 -403
- data/lib/graphql/execution/interpreter.rb +126 -80
- data/lib/graphql/execution/lazy.rb +11 -21
- data/lib/graphql/execution/lookahead.rb +133 -55
- data/lib/graphql/execution/multiplex.rb +4 -172
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +6 -4
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +11 -18
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +4 -4
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +17 -15
- data/lib/graphql/introspection/type_type.rb +29 -16
- data/lib/graphql/introspection.rb +6 -2
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/block_string.rb +37 -25
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +122 -81
- data/lib/graphql/language/lexer.rb +364 -1467
- data/lib/graphql/language/nodes.rb +197 -106
- data/lib/graphql/language/parser.rb +799 -1920
- data/lib/graphql/language/printer.rb +372 -160
- data/lib/graphql/language/sanitized_printer.rb +25 -27
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +62 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +37 -8
- data/lib/graphql/pagination/array_connection.rb +8 -6
- data/lib/graphql/pagination/connection.rb +61 -7
- data/lib/graphql/pagination/connections.rb +22 -23
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/pagination/relation_connection.rb +60 -28
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +146 -222
- data/lib/graphql/query/input_validation_result.rb +10 -1
- data/lib/graphql/query/null_context.rb +15 -32
- data/lib/graphql/query/validation_pipeline.rb +15 -39
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +35 -17
- data/lib/graphql/query.rb +149 -82
- data/lib/graphql/railtie.rb +15 -109
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/rake_task.rb +30 -11
- data/lib/graphql/relay/range_add.rb +9 -16
- data/lib/graphql/relay.rb +0 -15
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +6 -0
- data/lib/graphql/schema/addition.rb +98 -54
- data/lib/graphql/schema/always_visible.rb +14 -0
- data/lib/graphql/schema/argument.rb +179 -82
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +77 -39
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +4 -4
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +2 -2
- data/lib/graphql/schema/directive.rb +36 -22
- data/lib/graphql/schema/enum.rb +158 -63
- data/lib/graphql/schema/enum_value.rb +12 -21
- data/lib/graphql/schema/field/connection_extension.rb +7 -17
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +521 -359
- data/lib/graphql/schema/field_extension.rb +86 -2
- data/lib/graphql/schema/find_inherited_value.rb +3 -7
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +148 -99
- data/lib/graphql/schema/interface.rb +41 -64
- data/lib/graphql/schema/introspection_system.rb +12 -26
- data/lib/graphql/schema/late_bound_type.rb +12 -2
- data/lib/graphql/schema/list.rb +18 -7
- data/lib/graphql/schema/loader.rb +6 -5
- data/lib/graphql/schema/member/base_dsl_methods.rb +32 -18
- data/lib/graphql/schema/member/build_type.rb +16 -13
- data/lib/graphql/schema/member/has_arguments.rb +270 -86
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +169 -31
- data/lib/graphql/schema/member/has_interfaces.rb +143 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +16 -0
- data/lib/graphql/schema/member/validates_input.rb +6 -6
- data/lib/graphql/schema/member.rb +1 -6
- data/lib/graphql/schema/mutation.rb +7 -9
- data/lib/graphql/schema/non_null.rb +7 -7
- data/lib/graphql/schema/object.rb +38 -119
- data/lib/graphql/schema/printer.rb +24 -25
- data/lib/graphql/schema/relay_classic_mutation.rb +13 -91
- data/lib/graphql/schema/resolver/has_payload_type.rb +46 -11
- data/lib/graphql/schema/resolver.rb +118 -115
- data/lib/graphql/schema/scalar.rb +20 -21
- data/lib/graphql/schema/subscription.rb +95 -21
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/type_membership.rb +21 -4
- data/lib/graphql/schema/union.rb +16 -16
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -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 +4 -5
- 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 +13 -2
- data/lib/graphql/schema/validator/required_validator.rb +56 -18
- data/lib/graphql/schema/validator.rb +38 -28
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +359 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +294 -0
- data/lib/graphql/schema/warden.rb +423 -134
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +1015 -1057
- data/lib/graphql/static_validation/all_rules.rb +3 -1
- data/lib/graphql/static_validation/base_visitor.rb +15 -28
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +24 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +4 -3
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +13 -7
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +15 -13
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +13 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +62 -35
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +7 -5
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +14 -8
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +32 -6
- data/lib/graphql/static_validation/validator.rb +11 -27
- data/lib/graphql/static_validation.rb +0 -3
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +49 -11
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +40 -1
- data/lib/graphql/subscriptions/event.rb +87 -38
- data/lib/graphql/subscriptions/serialize.rb +27 -3
- data/lib/graphql/subscriptions.rb +63 -49
- data/lib/graphql/testing/helpers.rb +155 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/appoptics_trace.rb +253 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +4 -2
- data/lib/graphql/tracing/appsignal_trace.rb +79 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +17 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +185 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +27 -15
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +11 -28
- data/lib/graphql/tracing/legacy_trace.rb +12 -0
- data/lib/graphql/tracing/new_relic_trace.rb +77 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/notifications_tracing.rb +61 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/platform_trace.rb +118 -0
- data/lib/graphql/tracing/platform_tracing.rb +46 -49
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +6 -2
- data/lib/graphql/tracing/prometheus_trace.rb +94 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +5 -3
- data/lib/graphql/tracing/scout_trace.rb +74 -0
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +114 -0
- data/lib/graphql/tracing/statsd_trace.rb +58 -0
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +79 -0
- data/lib/graphql/tracing.rb +29 -52
- data/lib/graphql/type_kinds.rb +7 -4
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/iso_8601_date.rb +17 -6
- data/lib/graphql/types/iso_8601_date_time.rb +12 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/types/relay/connection_behaviors.rb +92 -32
- data/lib/graphql/types/relay/edge_behaviors.rb +46 -7
- data/lib/graphql/types/relay/has_node_field.rb +2 -2
- data/lib/graphql/types/relay/has_nodes_field.rb +2 -2
- data/lib/graphql/types/relay/node_behaviors.rb +12 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +2 -2
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +82 -137
- data/readme.md +13 -6
- metadata +127 -186
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -28
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -23
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -234
- data/lib/graphql/analysis/ast/query_depth.rb +0 -56
- data/lib/graphql/analysis/ast/visitor.rb +0 -268
- data/lib/graphql/analysis/ast.rb +0 -91
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
- data/lib/graphql/backwards_compatibility.rb +0 -61
- data/lib/graphql/base_type.rb +0 -230
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -436
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
- data/lib/graphql/compatibility.rb +0 -5
- data/lib/graphql/define/assign_argument.rb +0 -12
- data/lib/graphql/define/assign_connection.rb +0 -13
- data/lib/graphql/define/assign_enum_value.rb +0 -18
- data/lib/graphql/define/assign_global_id_field.rb +0 -11
- data/lib/graphql/define/assign_mutation_function.rb +0 -34
- data/lib/graphql/define/assign_object_field.rb +0 -42
- data/lib/graphql/define/defined_object_proxy.rb +0 -53
- data/lib/graphql/define/instance_definable.rb +0 -240
- data/lib/graphql/define/no_definition_error.rb +0 -7
- data/lib/graphql/define/non_null_with_bang.rb +0 -16
- data/lib/graphql/define/type_definer.rb +0 -31
- data/lib/graphql/define.rb +0 -31
- data/lib/graphql/deprecated_dsl.rb +0 -47
- data/lib/graphql/deprecation.rb +0 -13
- data/lib/graphql/directive/deprecated_directive.rb +0 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -111
- data/lib/graphql/enum_type.rb +0 -129
- data/lib/graphql/execution/execute.rb +0 -333
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -226
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -128
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -138
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -72
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/language/lexer.rl +0 -262
- data/lib/graphql/language/parser.y +0 -543
- data/lib/graphql/language/token.rb +0 -38
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/non_null_type.rb +0 -71
- data/lib/graphql/object_type.rb +0 -130
- data/lib/graphql/query/arguments.rb +0 -189
- data/lib/graphql/query/arguments_cache.rb +0 -24
- data/lib/graphql/query/executor.rb +0 -52
- data/lib/graphql/query/literal_input.rb +0 -136
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -40
- data/lib/graphql/relay/array_connection.rb +0 -83
- data/lib/graphql/relay/base_connection.rb +0 -189
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -41
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- data/lib/graphql/relay/edges_instrumentation.rb +0 -40
- data/lib/graphql/relay/global_id_resolve.rb +0 -18
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -106
- data/lib/graphql/relay/node.rb +0 -39
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -188
- data/lib/graphql/relay/type_extensions.rb +0 -32
- data/lib/graphql/scalar_type.rb +0 -91
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/catchall_middleware.rb +0 -35
- data/lib/graphql/schema/default_parse_error.rb +0 -10
- data/lib/graphql/schema/default_type_error.rb +0 -17
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/member/accepts_definition.rb +0 -152
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -31
- data/lib/graphql/schema/member/instrumentation.rb +0 -131
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -44
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -88
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -313
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/instrumentation.rb +0 -79
- data/lib/graphql/subscriptions/subscription_root.rb +0 -76
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- data/lib/graphql/types/relay/default_relay.rb +0 -27
- data/lib/graphql/types/relay/node_field.rb +0 -25
- data/lib/graphql/types/relay/nodes_field.rb +0 -27
- data/lib/graphql/union_type.rb +0 -115
- data/lib/graphql/upgrader/member.rb +0 -937
- data/lib/graphql/upgrader/schema.rb +0 -38
@@ -4,58 +4,225 @@ require 'set'
|
|
4
4
|
|
5
5
|
module GraphQL
|
6
6
|
class Schema
|
7
|
-
# Restrict access to a {GraphQL::Schema} with a user-defined
|
7
|
+
# Restrict access to a {GraphQL::Schema} with a user-defined `visible?` implementations.
|
8
8
|
#
|
9
9
|
# When validating and executing a query, all access to schema members
|
10
10
|
# should go through a warden. If you access the schema directly,
|
11
11
|
# you may show a client something that it shouldn't be allowed to see.
|
12
12
|
#
|
13
|
-
# @example Hidding private fields
|
14
|
-
# private_members = -> (member, ctx) { member.metadata[:private] }
|
15
|
-
# result = Schema.execute(query_string, except: private_members)
|
16
|
-
#
|
17
|
-
# @example Custom filter implementation
|
18
|
-
# # It must respond to `#call(member)`.
|
19
|
-
# class MissingRequiredFlags
|
20
|
-
# def initialize(user)
|
21
|
-
# @user = user
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# # Return `false` if any required flags are missing
|
25
|
-
# def call(member, ctx)
|
26
|
-
# member.metadata[:required_flags].any? do |flag|
|
27
|
-
# !@user.has_flag?(flag)
|
28
|
-
# end
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# # Then, use the custom filter in query:
|
33
|
-
# missing_required_flags = MissingRequiredFlags.new(current_user)
|
34
|
-
#
|
35
|
-
# # This query can only access members which match the user's flags
|
36
|
-
# result = Schema.execute(query_string, except: missing_required_flags)
|
37
|
-
#
|
38
13
|
# @api private
|
39
14
|
class Warden
|
40
|
-
|
15
|
+
def self.from_context(context)
|
16
|
+
context.warden || PassThruWarden
|
17
|
+
rescue NoMethodError
|
18
|
+
# this might be a hash which won't respond to #warden
|
19
|
+
PassThruWarden
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.types_from_context(context)
|
23
|
+
context.types || PassThruWarden
|
24
|
+
rescue NoMethodError
|
25
|
+
# this might be a hash which won't respond to #warden
|
26
|
+
PassThruWarden
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.use(schema)
|
30
|
+
# no-op
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param visibility_method [Symbol] a Warden method to call for this entry
|
34
|
+
# @param entry [Object, Array<Object>] One or more definitions for a given name in a GraphQL Schema
|
35
|
+
# @param context [GraphQL::Query::Context]
|
36
|
+
# @param warden [Warden]
|
37
|
+
# @return [Object] `entry` or one of `entry`'s items if exactly one of them is visible for this context
|
38
|
+
# @return [nil] If neither `entry` nor any of `entry`'s items are visible for this context
|
39
|
+
def self.visible_entry?(visibility_method, entry, context, warden = Warden.from_context(context))
|
40
|
+
if entry.is_a?(Array)
|
41
|
+
visible_item = nil
|
42
|
+
entry.each do |item|
|
43
|
+
if warden.public_send(visibility_method, item, context)
|
44
|
+
if visible_item.nil?
|
45
|
+
visible_item = item
|
46
|
+
else
|
47
|
+
raise DuplicateNamesError.new(
|
48
|
+
duplicated_name: item.path, duplicated_definition_1: visible_item.inspect, duplicated_definition_2: item.inspect
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
visible_item
|
54
|
+
elsif warden.public_send(visibility_method, entry, context)
|
55
|
+
entry
|
56
|
+
else
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# This is used when a caller provides a Hash for context.
|
62
|
+
# We want to call the schema's hooks, but we don't have a full-blown warden.
|
63
|
+
# The `context` arguments to these methods exist purely to simplify the code that
|
64
|
+
# calls methods on this object, so it will have everything it needs.
|
65
|
+
class PassThruWarden
|
66
|
+
class << self
|
67
|
+
def visible_field?(field, ctx); field.visible?(ctx); end
|
68
|
+
def visible_argument?(arg, ctx); arg.visible?(ctx); end
|
69
|
+
def visible_type?(type, ctx); type.visible?(ctx); end
|
70
|
+
def visible_enum_value?(ev, ctx); ev.visible?(ctx); end
|
71
|
+
def visible_type_membership?(tm, ctx); tm.visible?(ctx); end
|
72
|
+
def interface_type_memberships(obj_t, ctx); obj_t.interface_type_memberships; end
|
73
|
+
def arguments(owner, ctx); owner.arguments(ctx); end
|
74
|
+
def loadable?(type, ctx); type.visible?(ctx); end
|
75
|
+
def loadable_possible_types(type, ctx); type.possible_types(ctx); end
|
76
|
+
def visibility_profile
|
77
|
+
@visibility_profile ||= Warden::VisibilityProfile.new(self)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class NullWarden
|
83
|
+
def initialize(_filter = nil, context:, schema:)
|
84
|
+
@schema = schema
|
85
|
+
@visibility_profile = Warden::VisibilityProfile.new(self)
|
86
|
+
end
|
87
|
+
|
88
|
+
# No-op, but for compatibility:
|
89
|
+
attr_writer :skip_warning
|
90
|
+
|
91
|
+
attr_reader :visibility_profile
|
92
|
+
|
93
|
+
def visible_field?(field_defn, _ctx = nil, owner = nil); true; end
|
94
|
+
def visible_argument?(arg_defn, _ctx = nil); true; end
|
95
|
+
def visible_type?(type_defn, _ctx = nil); true; end
|
96
|
+
def visible_enum_value?(enum_value, _ctx = nil); enum_value.visible?(Query::NullContext.instance); end
|
97
|
+
def visible_type_membership?(type_membership, _ctx = nil); true; end
|
98
|
+
def interface_type_memberships(obj_type, _ctx = nil); obj_type.interface_type_memberships; end
|
99
|
+
def get_type(type_name); @schema.get_type(type_name, Query::NullContext.instance, false); end # rubocop:disable Development/ContextIsPassedCop
|
100
|
+
def arguments(argument_owner, ctx = nil); argument_owner.all_argument_definitions; end
|
101
|
+
def enum_values(enum_defn); enum_defn.enum_values(Query::NullContext.instance); end # rubocop:disable Development/ContextIsPassedCop
|
102
|
+
def get_argument(parent_type, argument_name); parent_type.get_argument(argument_name); end # rubocop:disable Development/ContextIsPassedCop
|
103
|
+
def types; @schema.types; end # rubocop:disable Development/ContextIsPassedCop
|
104
|
+
def root_type_for_operation(op_name); @schema.root_type_for_operation(op_name); end
|
105
|
+
def directives; @schema.directives.values; end
|
106
|
+
def fields(type_defn); type_defn.all_field_definitions; end # rubocop:disable Development/ContextIsPassedCop
|
107
|
+
def get_field(parent_type, field_name); @schema.get_field(parent_type, field_name); end
|
108
|
+
def reachable_type?(type_name); true; end
|
109
|
+
def loadable?(type, _ctx); true; end
|
110
|
+
def loadable_possible_types(union_type, _ctx); union_type.possible_types; end
|
111
|
+
def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
|
112
|
+
def possible_types(type_defn); @schema.possible_types(type_defn, Query::NullContext.instance, false); end
|
113
|
+
def interfaces(obj_type); obj_type.interfaces; end
|
114
|
+
end
|
115
|
+
|
116
|
+
def visibility_profile
|
117
|
+
@visibility_profile ||= VisibilityProfile.new(self)
|
118
|
+
end
|
119
|
+
|
120
|
+
class VisibilityProfile
|
121
|
+
def initialize(warden)
|
122
|
+
@warden = warden
|
123
|
+
end
|
124
|
+
|
125
|
+
def directives
|
126
|
+
@warden.directives
|
127
|
+
end
|
128
|
+
|
129
|
+
def directive_exists?(dir_name)
|
130
|
+
@warden.directives.any? { |d| d.graphql_name == dir_name }
|
131
|
+
end
|
132
|
+
|
133
|
+
def type(name)
|
134
|
+
@warden.get_type(name)
|
135
|
+
end
|
136
|
+
|
137
|
+
def field(owner, field_name)
|
138
|
+
@warden.get_field(owner, field_name)
|
139
|
+
end
|
140
|
+
|
141
|
+
def argument(owner, arg_name)
|
142
|
+
@warden.get_argument(owner, arg_name)
|
143
|
+
end
|
144
|
+
|
145
|
+
def query_root
|
146
|
+
@warden.root_type_for_operation("query")
|
147
|
+
end
|
148
|
+
|
149
|
+
def mutation_root
|
150
|
+
@warden.root_type_for_operation("mutation")
|
151
|
+
end
|
152
|
+
|
153
|
+
def subscription_root
|
154
|
+
@warden.root_type_for_operation("subscription")
|
155
|
+
end
|
156
|
+
|
157
|
+
def arguments(owner)
|
158
|
+
@warden.arguments(owner)
|
159
|
+
end
|
160
|
+
|
161
|
+
def fields(owner)
|
162
|
+
@warden.fields(owner)
|
163
|
+
end
|
164
|
+
|
165
|
+
def possible_types(type)
|
166
|
+
@warden.possible_types(type)
|
167
|
+
end
|
168
|
+
|
169
|
+
def enum_values(enum_type)
|
170
|
+
@warden.enum_values(enum_type)
|
171
|
+
end
|
172
|
+
|
173
|
+
def all_types
|
174
|
+
@warden.reachable_types
|
175
|
+
end
|
176
|
+
|
177
|
+
def interfaces(obj_type)
|
178
|
+
@warden.interfaces(obj_type)
|
179
|
+
end
|
180
|
+
|
181
|
+
def loadable?(t, ctx) # TODO remove ctx here?
|
182
|
+
@warden.loadable?(t, ctx)
|
183
|
+
end
|
184
|
+
|
185
|
+
def loadable_possible_types(t, ctx)
|
186
|
+
@warden.loadable_possible_types(t, ctx)
|
187
|
+
end
|
188
|
+
|
189
|
+
def reachable_type?(type_name)
|
190
|
+
!!@warden.reachable_type?(type_name)
|
191
|
+
end
|
192
|
+
|
193
|
+
def visible_enum_value?(enum_value, ctx = nil)
|
194
|
+
@warden.visible_enum_value?(enum_value, ctx)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
41
198
|
# @param context [GraphQL::Query::Context]
|
42
199
|
# @param schema [GraphQL::Schema]
|
43
|
-
def initialize(
|
44
|
-
@schema = schema
|
200
|
+
def initialize(context:, schema:)
|
201
|
+
@schema = schema
|
45
202
|
# Cache these to avoid repeated hits to the inheritance chain when one isn't present
|
46
203
|
@query = @schema.query
|
47
204
|
@mutation = @schema.mutation
|
48
205
|
@subscription = @schema.subscription
|
49
206
|
@context = context
|
50
|
-
@visibility_cache = read_through { |m|
|
207
|
+
@visibility_cache = read_through { |m| check_visible(schema, m) }
|
208
|
+
# Initialize all ivars to improve object shape consistency:
|
209
|
+
@types = @visible_types = @reachable_types = @visible_parent_fields =
|
210
|
+
@visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
|
211
|
+
@visible_enum_values = @visible_interfaces = @type_visibility = @type_memberships =
|
212
|
+
@visible_and_reachable_type = @unions = @unfiltered_interfaces =
|
213
|
+
@reachable_type_set = @visibility_profile = @loadable_possible_types =
|
214
|
+
nil
|
215
|
+
@skip_warning = schema.plugins.any? { |(plugin, _opts)| plugin == GraphQL::Schema::Warden }
|
51
216
|
end
|
52
217
|
|
218
|
+
attr_writer :skip_warning
|
219
|
+
|
53
220
|
# @return [Hash<String, GraphQL::BaseType>] Visible types in the schema
|
54
221
|
def types
|
55
222
|
@types ||= begin
|
56
223
|
vis_types = {}
|
57
|
-
@schema.types.each do |n, t|
|
58
|
-
if
|
224
|
+
@schema.types(@context).each do |n, t|
|
225
|
+
if visible_and_reachable_type?(t)
|
59
226
|
vis_types[n] = t
|
60
227
|
end
|
61
228
|
end
|
@@ -63,11 +230,23 @@ module GraphQL
|
|
63
230
|
end
|
64
231
|
end
|
65
232
|
|
233
|
+
# @return [Boolean] True if this type is used for `loads:` but not in the schema otherwise and not _explicitly_ hidden.
|
234
|
+
def loadable?(type, _ctx)
|
235
|
+
!reachable_type_set.include?(type) && visible_type?(type)
|
236
|
+
end
|
237
|
+
|
238
|
+
def loadable_possible_types(union_type, _ctx)
|
239
|
+
@loadable_possible_types ||= read_through do |t|
|
240
|
+
t.possible_types # unfiltered
|
241
|
+
end
|
242
|
+
@loadable_possible_types[union_type]
|
243
|
+
end
|
244
|
+
|
66
245
|
# @return [GraphQL::BaseType, nil] The type named `type_name`, if it exists (else `nil`)
|
67
246
|
def get_type(type_name)
|
68
247
|
@visible_types ||= read_through do |name|
|
69
|
-
type_defn = @schema.get_type(name)
|
70
|
-
if type_defn &&
|
248
|
+
type_defn = @schema.get_type(name, @context, false)
|
249
|
+
if type_defn && visible_and_reachable_type?(type_defn)
|
71
250
|
type_defn
|
72
251
|
else
|
73
252
|
nil
|
@@ -84,7 +263,7 @@ module GraphQL
|
|
84
263
|
|
85
264
|
# @return Boolean True if the type is visible and reachable in the schema
|
86
265
|
def reachable_type?(type_name)
|
87
|
-
type = get_type(type_name)
|
266
|
+
type = get_type(type_name) # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
|
88
267
|
type && reachable_type_set.include?(type)
|
89
268
|
end
|
90
269
|
|
@@ -92,8 +271,8 @@ module GraphQL
|
|
92
271
|
def get_field(parent_type, field_name)
|
93
272
|
@visible_parent_fields ||= read_through do |type|
|
94
273
|
read_through do |f_name|
|
95
|
-
field_defn = @schema.get_field(type, f_name)
|
96
|
-
if field_defn && visible_field?(
|
274
|
+
field_defn = @schema.get_field(type, f_name, @context)
|
275
|
+
if field_defn && visible_field?(field_defn, nil, type)
|
97
276
|
field_defn
|
98
277
|
else
|
99
278
|
nil
|
@@ -106,15 +285,15 @@ module GraphQL
|
|
106
285
|
|
107
286
|
# @return [GraphQL::Argument, nil] The argument named `argument_name` on `parent_type`, if it exists and is visible
|
108
287
|
def get_argument(parent_type, argument_name)
|
109
|
-
argument = parent_type.get_argument(argument_name)
|
110
|
-
return argument if argument && visible_argument?(argument)
|
288
|
+
argument = parent_type.get_argument(argument_name, @context)
|
289
|
+
return argument if argument && visible_argument?(argument, @context)
|
111
290
|
end
|
112
291
|
|
113
292
|
# @return [Array<GraphQL::BaseType>] The types which may be member of `type_defn`
|
114
293
|
def possible_types(type_defn)
|
115
294
|
@visible_possible_types ||= read_through { |type_defn|
|
116
|
-
pt = @schema.possible_types(type_defn, @context)
|
117
|
-
pt.select { |t|
|
295
|
+
pt = @schema.possible_types(type_defn, @context, false)
|
296
|
+
pt.select { |t| visible_and_reachable_type?(t) }
|
118
297
|
}
|
119
298
|
@visible_possible_types[type_defn]
|
120
299
|
end
|
@@ -122,26 +301,52 @@ module GraphQL
|
|
122
301
|
# @param type_defn [GraphQL::ObjectType, GraphQL::InterfaceType]
|
123
302
|
# @return [Array<GraphQL::Field>] Fields on `type_defn`
|
124
303
|
def fields(type_defn)
|
125
|
-
@visible_fields ||= read_through { |t| @schema.get_fields(t
|
304
|
+
@visible_fields ||= read_through { |t| @schema.get_fields(t, @context).values }
|
126
305
|
@visible_fields[type_defn]
|
127
306
|
end
|
128
307
|
|
129
308
|
# @param argument_owner [GraphQL::Field, GraphQL::InputObjectType]
|
130
309
|
# @return [Array<GraphQL::Argument>] Visible arguments on `argument_owner`
|
131
|
-
def arguments(argument_owner)
|
132
|
-
@visible_arguments ||= read_through { |o|
|
310
|
+
def arguments(argument_owner, ctx = nil)
|
311
|
+
@visible_arguments ||= read_through { |o|
|
312
|
+
args = o.arguments(@context)
|
313
|
+
if !args.empty?
|
314
|
+
args = args.values
|
315
|
+
args.select! { |a| visible_argument?(a, @context) }
|
316
|
+
args
|
317
|
+
else
|
318
|
+
EmptyObjects::EMPTY_ARRAY
|
319
|
+
end
|
320
|
+
}
|
133
321
|
@visible_arguments[argument_owner]
|
134
322
|
end
|
135
323
|
|
136
324
|
# @return [Array<GraphQL::EnumType::EnumValue>] Visible members of `enum_defn`
|
137
325
|
def enum_values(enum_defn)
|
138
|
-
@
|
139
|
-
|
326
|
+
@visible_enum_arrays ||= read_through { |e|
|
327
|
+
values = e.enum_values(@context)
|
328
|
+
if values.size == 0
|
329
|
+
raise GraphQL::Schema::Enum::MissingValuesError.new(e)
|
330
|
+
end
|
331
|
+
values
|
332
|
+
}
|
333
|
+
@visible_enum_arrays[enum_defn]
|
334
|
+
end
|
335
|
+
|
336
|
+
def visible_enum_value?(enum_value, _ctx = nil)
|
337
|
+
@visible_enum_values ||= read_through { |ev| visible?(ev) }
|
338
|
+
@visible_enum_values[enum_value]
|
140
339
|
end
|
141
340
|
|
142
341
|
# @return [Array<GraphQL::InterfaceType>] Visible interfaces implemented by `obj_type`
|
143
342
|
def interfaces(obj_type)
|
144
|
-
@visible_interfaces ||= read_through { |t|
|
343
|
+
@visible_interfaces ||= read_through { |t|
|
344
|
+
ints = t.interfaces(@context)
|
345
|
+
if !ints.empty?
|
346
|
+
ints.select! { |i| visible_type?(i) }
|
347
|
+
end
|
348
|
+
ints
|
349
|
+
}
|
145
350
|
@visible_interfaces[obj_type]
|
146
351
|
end
|
147
352
|
|
@@ -158,25 +363,74 @@ module GraphQL
|
|
158
363
|
end
|
159
364
|
end
|
160
365
|
|
161
|
-
|
162
|
-
|
163
|
-
def union_memberships(obj_type)
|
164
|
-
@unions ||= read_through { |obj_type| @schema.union_memberships(obj_type).select { |u| visible?(u) } }
|
165
|
-
@unions[obj_type]
|
166
|
-
end
|
167
|
-
|
168
|
-
def visible_argument?(arg_defn)
|
169
|
-
visible?(arg_defn) && visible_type?(arg_defn.type.unwrap)
|
170
|
-
end
|
171
|
-
|
172
|
-
def visible_field?(owner_type, field_defn)
|
366
|
+
# @param owner [Class, Module] If provided, confirm that field has the given owner.
|
367
|
+
def visible_field?(field_defn, _ctx = nil, owner = field_defn.owner)
|
173
368
|
# This field is visible in its own right
|
174
369
|
visible?(field_defn) &&
|
175
370
|
# This field's return type is visible
|
176
|
-
|
371
|
+
visible_and_reachable_type?(field_defn.type.unwrap) &&
|
177
372
|
# This field is either defined on this object type,
|
178
373
|
# or the interface it's inherited from is also visible
|
179
|
-
((field_defn.respond_to?(:owner) && field_defn.owner ==
|
374
|
+
((field_defn.respond_to?(:owner) && field_defn.owner == owner) || field_on_visible_interface?(field_defn, owner))
|
375
|
+
end
|
376
|
+
|
377
|
+
def visible_argument?(arg_defn, _ctx = nil)
|
378
|
+
visible?(arg_defn) && visible_and_reachable_type?(arg_defn.type.unwrap)
|
379
|
+
end
|
380
|
+
|
381
|
+
def visible_type?(type_defn, _ctx = nil)
|
382
|
+
@type_visibility ||= read_through { |type_defn| visible?(type_defn) }
|
383
|
+
@type_visibility[type_defn]
|
384
|
+
end
|
385
|
+
|
386
|
+
def visible_type_membership?(type_membership, _ctx = nil)
|
387
|
+
visible?(type_membership)
|
388
|
+
end
|
389
|
+
|
390
|
+
def interface_type_memberships(obj_type, _ctx = nil)
|
391
|
+
@type_memberships ||= read_through do |obj_t|
|
392
|
+
obj_t.interface_type_memberships
|
393
|
+
end
|
394
|
+
@type_memberships[obj_type]
|
395
|
+
end
|
396
|
+
|
397
|
+
private
|
398
|
+
|
399
|
+
def visible_and_reachable_type?(type_defn)
|
400
|
+
@visible_and_reachable_type ||= read_through do |type_defn|
|
401
|
+
next false unless visible_type?(type_defn)
|
402
|
+
next true if root_type?(type_defn) || type_defn.introspection?
|
403
|
+
|
404
|
+
if type_defn.kind.union?
|
405
|
+
!possible_types(type_defn).empty? && (referenced?(type_defn) || orphan_type?(type_defn))
|
406
|
+
elsif type_defn.kind.interface?
|
407
|
+
if !possible_types(type_defn).empty?
|
408
|
+
true
|
409
|
+
else
|
410
|
+
if @context.respond_to?(:logger) && (logger = @context.logger)
|
411
|
+
logger.debug { "Interface `#{type_defn.graphql_name}` hidden because it has no visible implementers" }
|
412
|
+
end
|
413
|
+
false
|
414
|
+
end
|
415
|
+
else
|
416
|
+
if referenced?(type_defn)
|
417
|
+
true
|
418
|
+
elsif type_defn.kind.object?
|
419
|
+
# Show this object if it belongs to ...
|
420
|
+
interfaces(type_defn).any? { |t| referenced?(t) } || # an interface which is referenced in the schema
|
421
|
+
union_memberships(type_defn).any? { |t| referenced?(t) || orphan_type?(t) } # or a union which is referenced or added via orphan_types
|
422
|
+
else
|
423
|
+
false
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
@visible_and_reachable_type[type_defn]
|
429
|
+
end
|
430
|
+
|
431
|
+
def union_memberships(obj_type)
|
432
|
+
@unions ||= read_through { |obj_type| @schema.union_memberships(obj_type).select { |u| visible?(u) } }
|
433
|
+
@unions[obj_type]
|
180
434
|
end
|
181
435
|
|
182
436
|
# We need this to tell whether a field was inherited by an interface
|
@@ -195,10 +449,10 @@ module GraphQL
|
|
195
449
|
any_interface_has_visible_field = false
|
196
450
|
ints = unfiltered_interfaces(type_defn)
|
197
451
|
ints.each do |interface_type|
|
198
|
-
if (iface_field_defn = interface_type.get_field(field_defn.graphql_name))
|
452
|
+
if (iface_field_defn = interface_type.get_field(field_defn.graphql_name, @context))
|
199
453
|
any_interface_has_field = true
|
200
454
|
|
201
|
-
if interfaces(type_defn).include?(interface_type) && visible_field?(
|
455
|
+
if interfaces(type_defn).include?(interface_type) && visible_field?(iface_field_defn, nil, interface_type)
|
202
456
|
any_interface_has_visible_field = true
|
203
457
|
end
|
204
458
|
end
|
@@ -215,23 +469,6 @@ module GraphQL
|
|
215
469
|
end
|
216
470
|
end
|
217
471
|
|
218
|
-
def visible_type?(type_defn)
|
219
|
-
@type_visibility ||= read_through do |type_defn|
|
220
|
-
next false unless visible?(type_defn)
|
221
|
-
next true if root_type?(type_defn) || type_defn.introspection?
|
222
|
-
|
223
|
-
if type_defn.kind.union?
|
224
|
-
visible_possible_types?(type_defn) && (referenced?(type_defn) || orphan_type?(type_defn))
|
225
|
-
elsif type_defn.kind.interface?
|
226
|
-
visible_possible_types?(type_defn)
|
227
|
-
else
|
228
|
-
referenced?(type_defn) || visible_abstract_type?(type_defn)
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
@type_visibility[type_defn]
|
233
|
-
end
|
234
|
-
|
235
472
|
def root_type?(type_defn)
|
236
473
|
@query == type_defn ||
|
237
474
|
@mutation == type_defn ||
|
@@ -239,41 +476,79 @@ module GraphQL
|
|
239
476
|
end
|
240
477
|
|
241
478
|
def referenced?(type_defn)
|
242
|
-
|
243
|
-
graphql_name = type_defn.unwrap.graphql_name
|
244
|
-
members = @references_to[graphql_name] || NO_REFERENCES
|
479
|
+
members = @schema.references_to(type_defn)
|
245
480
|
members.any? { |m| visible?(m) }
|
246
481
|
end
|
247
482
|
|
248
|
-
NO_REFERENCES = [].freeze
|
249
|
-
|
250
483
|
def orphan_type?(type_defn)
|
251
484
|
@schema.orphan_types.include?(type_defn)
|
252
485
|
end
|
253
486
|
|
254
|
-
def visible_abstract_type?(type_defn)
|
255
|
-
type_defn.kind.object? && (
|
256
|
-
interfaces(type_defn).any? ||
|
257
|
-
union_memberships(type_defn).any?
|
258
|
-
)
|
259
|
-
end
|
260
|
-
|
261
|
-
def visible_possible_types?(type_defn)
|
262
|
-
possible_types(type_defn).any? { |t| visible_type?(t) }
|
263
|
-
end
|
264
|
-
|
265
487
|
def visible?(member)
|
266
488
|
@visibility_cache[member]
|
267
489
|
end
|
268
490
|
|
269
491
|
def read_through
|
270
|
-
Hash.new { |h, k| h[k] = yield(k) }
|
492
|
+
Hash.new { |h, k| h[k] = yield(k) }.compare_by_identity
|
493
|
+
end
|
494
|
+
|
495
|
+
def check_visible(schema, member)
|
496
|
+
if schema.visible?(member, @context)
|
497
|
+
true
|
498
|
+
elsif @skip_warning
|
499
|
+
false
|
500
|
+
else
|
501
|
+
member_s = member.respond_to?(:path) ? member.path : member.inspect
|
502
|
+
member_type = case member
|
503
|
+
when Module
|
504
|
+
if member.respond_to?(:kind)
|
505
|
+
member.kind.name.downcase
|
506
|
+
else
|
507
|
+
""
|
508
|
+
end
|
509
|
+
when GraphQL::Schema::Field
|
510
|
+
"field"
|
511
|
+
when GraphQL::Schema::EnumValue
|
512
|
+
"enum value"
|
513
|
+
when GraphQL::Schema::Argument
|
514
|
+
"argument"
|
515
|
+
else
|
516
|
+
""
|
517
|
+
end
|
518
|
+
|
519
|
+
schema_s = schema.name ? "#{schema.name}'s" : ""
|
520
|
+
schema_name = schema.name ? "#{schema.name}" : "your schema"
|
521
|
+
warn(ADD_WARDEN_WARNING % { schema_s: schema_s, schema_name: schema_name, member: member_s, member_type: member_type })
|
522
|
+
@skip_warning = true # only warn once per query
|
523
|
+
# If there's no schema name, add the backtrace for additional context:
|
524
|
+
if schema_s == ""
|
525
|
+
puts caller.map { |l| " #{l}"}
|
526
|
+
end
|
527
|
+
false
|
528
|
+
end
|
271
529
|
end
|
272
530
|
|
531
|
+
ADD_WARDEN_WARNING = <<~WARNING
|
532
|
+
DEPRECATION: %{schema_s} "%{member}" %{member_type} returned `false` for `.visible?` but `GraphQL::Schema::Visibility` isn't configured yet.
|
533
|
+
|
534
|
+
Address this warning by adding:
|
535
|
+
|
536
|
+
use GraphQL::Schema::Visibility
|
537
|
+
|
538
|
+
to the definition for %{schema_name}. (Future GraphQL-Ruby versions won't check `.visible?` methods by default.)
|
539
|
+
|
540
|
+
Alternatively, for legacy behavior, add:
|
541
|
+
|
542
|
+
use GraphQL::Schema::Warden # legacy visibility behavior
|
543
|
+
|
544
|
+
For more information see: https://graphql-ruby.org/authorization/visibility.html
|
545
|
+
WARNING
|
546
|
+
|
273
547
|
def reachable_type_set
|
274
|
-
return @reachable_type_set if
|
548
|
+
return @reachable_type_set if @reachable_type_set
|
275
549
|
|
276
550
|
@reachable_type_set = Set.new
|
551
|
+
rt_hash = {}
|
277
552
|
|
278
553
|
unvisited_types = []
|
279
554
|
['query', 'mutation', 'subscription'].each do |op_name|
|
@@ -283,62 +558,76 @@ module GraphQL
|
|
283
558
|
unvisited_types.concat(@schema.introspection_system.types.values)
|
284
559
|
|
285
560
|
directives.each do |dir_class|
|
286
|
-
dir_class.
|
561
|
+
arguments(dir_class).each do |arg_defn|
|
287
562
|
arg_t = arg_defn.type.unwrap
|
288
|
-
if get_type(arg_t.graphql_name)
|
563
|
+
if get_type(arg_t.graphql_name) # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
|
289
564
|
unvisited_types << arg_t
|
290
565
|
end
|
291
566
|
end
|
292
567
|
end
|
293
568
|
|
294
569
|
@schema.orphan_types.each do |orphan_type|
|
295
|
-
if get_type(orphan_type.graphql_name)
|
570
|
+
if get_type(orphan_type.graphql_name) == orphan_type # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
|
296
571
|
unvisited_types << orphan_type
|
297
572
|
end
|
298
573
|
end
|
299
574
|
|
575
|
+
included_interface_possible_types_set = Set.new
|
576
|
+
|
300
577
|
until unvisited_types.empty?
|
301
578
|
type = unvisited_types.pop
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
579
|
+
visit_type(type, unvisited_types, @reachable_type_set, rt_hash, included_interface_possible_types_set, include_interface_possible_types: false)
|
580
|
+
end
|
581
|
+
|
582
|
+
@reachable_type_set
|
583
|
+
end
|
584
|
+
|
585
|
+
def visit_type(type, unvisited_types, visited_type_set, type_by_name_hash, included_interface_possible_types_set, include_interface_possible_types:)
|
586
|
+
if visited_type_set.add?(type) || (include_interface_possible_types && type.kind.interface? && included_interface_possible_types_set.add?(type))
|
587
|
+
type_by_name = type_by_name_hash[type.graphql_name] ||= type
|
588
|
+
if type_by_name != type
|
589
|
+
name_1, name_2 = [type.inspect, type_by_name.inspect].sort
|
590
|
+
raise DuplicateNamesError.new(
|
591
|
+
duplicated_name: type.graphql_name, duplicated_definition_1: name_1, duplicated_definition_2: name_2
|
592
|
+
)
|
593
|
+
end
|
594
|
+
if type.kind.input_object?
|
595
|
+
# recurse into visible arguments
|
596
|
+
arguments(type).each do |argument|
|
597
|
+
argument_type = argument.type.unwrap
|
598
|
+
unvisited_types << argument_type
|
599
|
+
end
|
600
|
+
elsif type.kind.union?
|
601
|
+
# recurse into visible possible types
|
602
|
+
possible_types(type).each do |possible_type|
|
603
|
+
unvisited_types << possible_type
|
604
|
+
end
|
605
|
+
elsif type.kind.fields?
|
606
|
+
if type.kind.object?
|
607
|
+
# recurse into visible implemented interfaces
|
608
|
+
interfaces(type).each do |interface|
|
609
|
+
unvisited_types << interface
|
313
610
|
end
|
314
|
-
elsif
|
315
|
-
|
316
|
-
|
317
|
-
possible_types(type).each do |possible_type|
|
318
|
-
unvisited_types << possible_type
|
319
|
-
end
|
320
|
-
elsif type.kind.object?
|
321
|
-
# recurse into visible implemented interfaces
|
322
|
-
interfaces(type).each do |interface|
|
323
|
-
unvisited_types << interface
|
324
|
-
end
|
611
|
+
elsif include_interface_possible_types
|
612
|
+
possible_types(type).each do |pt|
|
613
|
+
unvisited_types << pt
|
325
614
|
end
|
615
|
+
end
|
616
|
+
# Don't visit interface possible types -- it's not enough to justify visibility
|
326
617
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
618
|
+
# recurse into visible fields
|
619
|
+
fields(type).each do |field|
|
620
|
+
field_type = field.type.unwrap
|
621
|
+
# In this case, if it's an interface, we want to include
|
622
|
+
visit_type(field_type, unvisited_types, visited_type_set, type_by_name_hash, included_interface_possible_types_set, include_interface_possible_types: true)
|
623
|
+
# recurse into visible arguments
|
624
|
+
arguments(field).each do |argument|
|
625
|
+
argument_type = argument.type.unwrap
|
626
|
+
unvisited_types << argument_type
|
336
627
|
end
|
337
628
|
end
|
338
629
|
end
|
339
630
|
end
|
340
|
-
|
341
|
-
@reachable_type_set
|
342
631
|
end
|
343
632
|
end
|
344
633
|
end
|