Skip to content

authorized_as_type? Fails if Application Object has Method .key? #3604

@sergio-opslevel

Description

@sergio-opslevel

Describe the bug

Mutation fails to execute when application object contains method .key? but does not accept a symbol as the only argument.
I believe this code assumes any object with .key? method is a hash an InputObject, which is not true in my case.

Proposed fix:
Changing value.respond_to?(:key?) to value.is_a?(InputObject).

Versions

I was upgrading from graphql 1.9.x to 1.12.x when I discovered this issue.

Other versions: rails=5.2.5 and graphql-batch=0.4.3

GraphQL schema

  • Using interpreter
  • No custom instumentation
module Types
  class TagType < GraphQL::Schema::Object

    description "<removed>"
    public_field :id, ID, null: false, description: "<removed>"
    public_field :key, String, null: false, description: "<removed>"
    public_field :value, String, null: false, description: "<removed>"
    public_field :owner, Types::TagOwnerType, null: false, description: "<removed>"
    field :locked, Boolean, null: false, description: "<removed>"

    def locked
      object.locked?
    end
  end
end

The Active Record model matches this schema. Active Record will see field .key and automatically create method .key? that takes no args.

GraphQL query

    mutation ($id: ID!) {
      tagDelete (input: {
        id: $id
      }) {
        deletedTagId
        errors {
          message
          path
        }
      }
    }

Steps to reproduce

Run a query on an object which implements .key? with no arguments.

Expected behavior

The query completes successfully

Actual behavior

The query explodes

A debugger at the site of incidence:
image

Full Backtrace

Click to view exception backtrace
["/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/activerecord-5.2.5/lib/active_record/attribute_methods/query.rb:37:in `attribute?'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/activemodel-5.2.5/lib/active_model/attribute_methods.rb:382:in `key?'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/argument.rb:155:in `block in authorized_as_type?'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/argument.rb:150:in `each'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/argument.rb:150:in `authorized_as_type?'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/argument.rb:131:in `authorized?'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/resolver.rb:152:in `block in authorized?'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/resolver.rb:149:in `each_value'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/resolver.rb:149:in `authorized?'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/resolver.rb:92:in `block (2 levels) in resolve_with_support'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema.rb:116:in `after_lazy'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/resolver.rb:87:in `block in resolve_with_support'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema.rb:116:in `after_lazy'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/resolver.rb:76:in `resolve_with_support'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:714:in `public_send'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:714:in `block in public_send_field'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:757:in `block in with_extensions'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:787:in `block (2 levels) in run_extensions_before_resolve'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:790:in `run_extensions_before_resolve'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:787:in `block in run_extensions_before_resolve'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-batch-0.4.3/lib/graphql/batch/mutation_field_extension.rb:6:in `resolve'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:780:in `run_extensions_before_resolve'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:756:in `with_extensions'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:696:in `public_send_field'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:609:in `block in resolve'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema.rb:116:in `after_lazy'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/field.rb:607:in `resolve'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:495:in `block (4 levels) in evaluate_selection_with_args'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/tracing.rb:66:in `trace'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:494:in `block (3 levels) in evaluate_selection_with_args'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/query.rb:362:in `block in with_error_handling'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/errors.rb:107:in `with_error_handling'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/query.rb:361:in `with_error_handling'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:493:in `block (2 levels) in evaluate_selection_with_args'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:779:in `resolve_with_directives'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:490:in `block in evaluate_selection_with_args'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:878:in `after_lazy'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:426:in `evaluate_selection_with_args'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:418:in `block in evaluate_selection'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/member/has_arguments.rb:132:in `block (2 levels) in coerce_arguments'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/dataloader/null_dataloader.rb:17:in `append_job'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/member/has_arguments.rb:111:in `block in coerce_arguments'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/member/has_arguments.rb:110:in `each'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema/member/has_arguments.rb:110:in `coerce_arguments'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/arguments_cache.rb:50:in `dataload_for'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:417:in `evaluate_selection'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:348:in `block (2 levels) in evaluate_selections'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/dataloader/null_dataloader.rb:17:in `append_job'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:347:in `block in evaluate_selections'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:346:in `each'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:346:in `evaluate_selections'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:221:in `block (4 levels) in run_eager'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:779:in `resolve_with_directives'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:220:in `block (3 levels) in run_eager'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/dataloader/null_dataloader.rb:17:in `append_job'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:218:in `block (2 levels) in run_eager'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:180:in `tap_or_each'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:209:in `block in run_eager'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:779:in `resolve_with_directives'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter/runtime.rb:200:in `run_eager'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter.rb:73:in `block in evaluate'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/tracing.rb:66:in `trace'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter.rb:72:in `evaluate'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/interpreter.rb:48:in `begin_query'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:85:in `begin_query'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:104:in `block (2 levels) in run_as_multiplex'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/dataloader/null_dataloader.rb:17:in `append_job'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:104:in `block in run_as_multiplex'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:103:in `each'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:103:in `each_with_index'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:103:in `run_as_multiplex'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:63:in `block (2 levels) in run_queries'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:208:in `block in instrument_and_analyze'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:29:in `block (2 levels) in apply_instrumenters'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:46:in `block (2 levels) in each_query_call_hooks'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:41:in `each_query_call_hooks'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:45:in `block in each_query_call_hooks'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:72:in `call_hooks'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:44:in `each_query_call_hooks'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:27:in `block in apply_instrumenters'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:72:in `call_hooks'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/instrumentation.rb:26:in `apply_instrumenters'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:187:in `instrument_and_analyze'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:62:in `block in run_queries'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/tracing.rb:66:in `trace'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:60:in `run_queries'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/execution/multiplex.rb:50:in `run_all'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema.rb:1688:in `multiplex'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/graphql-1.12.15/lib/graphql/schema.rb:1659:in `execute'",
 "/Users/sergio/dev/OpsLevel/test/test_helper.rb:363:in `exec_query'",
 "/Users/sergio/dev/OpsLevel/test/graphql/mutations/tag_delete_test.rb:60:in `block in <class:TagDeleteTest>'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest/test.rb:98:in `block (3 levels) in run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest/test.rb:195:in `capture_exceptions'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest/test.rb:95:in `block (2 levels) in run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:272:in `time_it'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest/test.rb:94:in `block in run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:367:in `on_signal'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest/test.rb:211:in `with_info_handler'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest/test.rb:93:in `run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:1029:in `run_one_method'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:341:in `run_one_method'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:328:in `block (2 levels) in run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:327:in `each'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:327:in `block in run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:367:in `on_signal'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:354:in `with_info_handler'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:326:in `run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/railties-5.2.5/lib/rails/test_unit/line_filtering.rb:10:in `run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:164:in `block in __run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:164:in `map'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:164:in `__run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:141:in `run'",
 "/Users/sergio/dev/OpsLevel/vendor/ruby/2.6.0/gems/minitest-5.14.4/lib/minitest.rb:68:in `block in autorun'"]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions