graphql-guard icon indicating copy to clipboard operation
graphql-guard copied to clipboard

Deprecation warnings with graphql-1.13.1

Open IngusSkaistkalns opened this issue 3 years ago • 16 comments

Hello,

Deprecation warnings starting graphql-1.13.1:

Legacy `.to_graphql` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Remove `.to_graphql` to use a class-based definition instead.

Called on #<GraphQL::Schema::Field Query.posts(...): [Post!]!> from:

graphql-guard/lib/graphql/guard/testing.rb:29:in `field_with_guard'
.....

From changelog

.to_graphql and .graphql_definition are deprecated and will be removed in GraphQL-Ruby 2.0. 
All features using those legacy definitions are already removed
and all behaviors should have been ported to class-based definitions. 
So, you should be able to remove those calls entirely.
Please open an issue if you have trouble with it! #3750 #3765

Also I noticed, that inline guards return Array wrapped guard Proc and not just proc right away. Is this intended outcome in graphql or some undesired behaviour - I don't know, should investigate more.

IngusSkaistkalns avatar Dec 15 '21 12:12 IngusSkaistkalns

:+1: up

pierry01 avatar Jan 11 '22 21:01 pierry01

Hmm, I'm getting this error now on the latest graphql-ruby (1.13.4)

undefined method `graphql_definition' for #<GraphQL::Schema::TypeMembership
Did you mean?  graphql_name
/bundle/ruby/3.0.0/bundler/gems/graphql-guard-ca368a8dbdac/lib/graphql/guard.rb:17:in `block in <class:Guard>'

Not quite sure what's happening as I didn't think they removed the .graphql_definition yet? In the PR, it seems deprecated, not removed. Not quite following what's going on.

Downgrading to graphql 1.12.23 addresses the issue, and I no longer get the error.

asgeo1 avatar Jan 14 '22 04:01 asgeo1

Is there any news on this? I get the same warnings when updating to graphql-ruby 1.13.8

23tux avatar Feb 08 '22 15:02 23tux

I just tried to find a fix for this, but I'm not sure how to get the metadata from schema_member without using graphql_definition in those lines:

https://github.com/exAspArk/graphql-guard/blob/fb42e72112c51cde2380c0a62d31fb3d63515d45/lib/graphql/guard.rb#L16-L19

In sum there are 3 places where #graphql_definition is still used.

As mentioned here https://github.com/rmosolgo/graphql-ruby/blob/master/CHANGELOG.md#deprecations-3

All features using those legacy definitions are already removed and all behaviors should have been ported to class-based definitions. So, you should be able to remove those calls entirely.

But of course, we can't just remove the call itself, somehow it has to load the masks.

Maybe @rmosolgo can help?

23tux avatar Feb 23 '22 18:02 23tux

I just discovered, that it's not only a deprecation warning, but an error:

NoMethodError:
 undefined method `graphql_definition' for #<GraphQL::Schema::TypeMembership:0x0000557f69381178>
 Did you mean?  graphql_name
# /usr/local/bundle/gems/graphql-guard-2.0.0/lib/graphql/guard.rb:17:in `block in <class:Guard>'

23tux avatar Feb 23 '22 18:02 23tux

metadata is part of the legacy type definition system, you're right that there's no way to access it apart from .graphql_definition. Instead of .metadata, you should store custom values in instance variables on your definitions. For example:

module MaskFilter 
  attr_accessor :mask 
end 

class Types::BaseObject < GraphQL::Schema::Object
  extend MaskFilter 
end 

# ^^ do the same for other base classes 

MASKING_FILTER = ->(schema_member, ctx) do 
 mask =  schema_member.respond_to?(:mask) && schema_member.mask
 mask ? mask.call(ctx) : true 
end 

Hope that helps!

rmosolgo avatar Feb 25 '22 16:02 rmosolgo

@rmosolgo thanks for the quick answer!

It seems, that the changes require more work than I first anticipated to get masking to work. So I wondered, if you can give some advice how to implement it?

The current implementation is this: https://github.com/exAspArk/graphql-guard/blob/fb42e72112c51cde2380c0a62d31fb3d63515d45/lib/graphql/guard.rb#L57-L63

I see some room for improvement here:

  • I don't like using class_eval to monkey patch the .default_filter method
  • I noticed that GraphQL::Filter is marked private in the docs (see https://graphql-ruby.org/api-doc/2.0.0/GraphQL/Filter)

What would be a more future proof way of providing a masking feature? I found the visiblity stuff in your docs (see https://graphql-ruby.org/schema/dynamic_types.html#using-visiblecontext-1), but it seems that it's intended to dynamically switch the implementation of a type, right?

Regarding "metadata is part of the legacy type definition system": Does this imply, that using .accept_definitions is the wrong way now? See: https://github.com/exAspArk/graphql-guard/blob/fb42e72112c51cde2380c0a62d31fb3d63515d45/lib/graphql/guard.rb#L95-L100

Before you could write something like this

field :title, String, null: true, guard: ->(obj, args, ctx) { ctx[:current_user].admin? }

I'm not sure how I would achieve something like this using your approach with attr_accessor :mask. Could you elaborate?

23tux avatar Mar 02 '22 13:03 23tux

future proof way of providing a masking feature?

Yes, def self.visible?(ctx) is the way. Here are some docs on that: https://graphql-ruby.org/authorization/visibility.html

Besides swapping implementations at runtime, you can also hide implementations at runtime -- and if a type, field, argument, etc is hidden, then it doesn't exist for the current query.

using .accept_definitions

Yes, it was a way to bridge the gap from legacy definition to class-based definition, but it's removed in graphql-ruby 2.0.

Honestly, for class-based definitions, I would recommend a method-based approach instead of a proc-based approach. Something like this:

module GraphQL::Guard::Integration 
  def masked?(context)
    # library users should implement this method to hide things
    false
  end 
  
  def visible?(context)
    (!masked?(context)) && super 
  end 

  def guarded?(*args) # for objects, `[obj, ctx]`, but for fields and arguments, `[obj, args, ctx]`
    # library users should implement this method to flag things as not authorized
    false 
  end 
  
  def authorized?(*args)
    (!guarded?(*args)) && super 
  end
end 

class Types::BaseObject < GraphQL::Schema::Object 
  extend GraphQL::Guard::Integration 
  
  def self.guarded?(obj, ctx)
    ctx[:current_user].admin?
  end 
end 

# or: 

class Types::BaseField < GraphQL::Schema::Field 
  include GraphQL::Guard::Integration 
  
  def guarded?(obj, args, ctx)
    ctx[:current_user].admin?
  end 
end 

More details about graphql-ruby's .authorized? method here: https://graphql-ruby.org/authorization/authorization.html

Hope that helps!

rmosolgo avatar Mar 02 '22 15:03 rmosolgo

Hello @exAspArk, are there any plans for this library to support GraphQL Ruby 1.13 or 2.0? Are you open to PRs to address this issue?

grxy avatar Mar 14 '22 16:03 grxy

@rmosolgo thank you, this helps a lot. We are going to need something similar in https://github.com/graphql-devise/graphql_devise and I think it might help for this gem too.

It looks like our only way to implement this, will be to provide a custom field class in the gem, and that one should be able to handle what you described in https://github.com/exAspArk/graphql-guard/issues/53#issuecomment-1057079969. Is there a way to assign a default field_class for all types of fields? From the docs it'd seem like we will have to call field_class in every base type like enum or object. But from a gem's perspective it would be amazing if we could assign a field class for ALL in a single call. Of course, I see how that might not be possible and we might have to document this so users do this in their projects for every base type.

mcelicalderon avatar Mar 28 '22 01:03 mcelicalderon

Yeah, there's not a way to install a field class for every base type in one line of code -- the base Object, Interface, and Mutation classes all need that configuration. I definitely agree that would be nice, but I haven't been able to figure out how it'd work...

rmosolgo avatar Mar 28 '22 12:03 rmosolgo

That's fine, thank you!

mcelicalderon avatar Mar 28 '22 15:03 mcelicalderon

Any updates? I started having this problem after updating some old libs 😞

KauanCS avatar Oct 30 '23 20:10 KauanCS

Is still repo still active?

tienle avatar Apr 12 '24 11:04 tienle

Sorry, I don't have the bandwidth to address it. But if anyone is willing to submit a PR, I'd be happy to review it!

exAspArk avatar Apr 13 '24 23:04 exAspArk