exAspArk / graphql-guard

Simple authorization gem for GraphQL :lock:
MIT License
472 stars 36 forks source link

Undefined method guard for Resolvers Class #2

Closed davidfilip closed 7 years ago

davidfilip commented 7 years ago

I am trying to use guard inside the Mutation, using Resolvers class:

class Resolvers::UpdateExample < GraphQL::Function
  argument :id, !types.ID
  argument :example, !Inputs::ExampleInput

  type Types::ExampleType

  guard ->(obj, args, ctx) { 
      true
    }

  def call(obj,args,ctx)
    puts "hello world"
  end
end

When I try to call this mutation I get error:

Failure/Error: guard ->(obj, args, ctx) { ..

 NoMethodError:
   undefined method `guard' for Resolvers::UpdateExample:Class
exAspArk commented 7 years ago

Hey, @davidfilip!

Thank you so much for reporting the issue!

To be honest, I haven't used GraphQL::Function before. Mostly lambdas, GraphQL::Relay::Mutation (with input_field, return_field, etc.) or simple resolve objects like:

field :something, Types::ExampleType do
  argument :id, !types.ID
  # ...
  resolve UpdateExample.new
end

class UpdateExample
  def call(obj, args, ctx)
    # ...
  end
end

For now, you probably have these 2 options:

field :something, function: UpdateExample.new do
  guard ->(obj, args, ctx) { true }
end
field :something, function: UpdateExample.new

class GraphqlPolicy
  RULES = {
    Types::ExampleType => {
      something: ->(obj, args, ctx) { true }
    }
  }

  def self.guard(type, field)
    RULES.dig(type, field)
  end
end

Schema = GraphQL::Schema.define do
  # ...
  use GraphQL::Guard.new(policy_object: GraphqlPolicy)
end

I'll try to investigate whether it's possible to extend GraphQL::Function in order to use inline guard without monkey patching next week 🙌

exAspArk commented 7 years ago

@davidfilip unfortunately, GraphQL:: Function doesn't support extending the interface similarly to Extending the DSL without monkey patching the class.

So, I'd suggest defining guard with a policy object or on the Type level, e.g.:

QueryType = GraphQL::ObjectType.define do
  field :something, guard: ->(obj, args, ctx) { true }, function: UpdateExample.new
end