I'm running into a bit of difficulty using GraphQL Pro's Pundit authorization with batch-loader. We've set up a base resolver class like so:
class BaseResolver < GraphQL::Function
def batch(obj, args, model)
object_id = "#{obj.class.name.downcase}_id"
BatchLoader.for(obj.id).batch(default_value: [], key: args.to_h) do |obj_ids, loader|
scopes(model.in(object_id => obj_ids), args).each do |record|
loader.call(record[object_id]) { |memo| memo << record }
end
end
end
def self.extend_type(base_type)
base_type.define_connection do
field :totalCount do
type types.Int
resolve ->(obj, _args, _ctx) { obj.nodes.size }
end
end
end
end
and then a specific resolver might look like this:
class FindUnicorns < BaseResolver
type extend_type(Types::UnicornType)
def call(obj, args, _ctx)
batch(obj, args, Unicorn)
end
private
def scopes(query, _args)
query
end
end
and we have a policy like this:
class UnicornPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.admin?
scope.all
else
# only unicorns user rides
scope.where(rider_id: user.id)
end
end
end
end
The trouble is that GraphQL Pro will only invoke the UnicornPolicy::Scope#resolve method if the resolver returns an ActiveRecord::Relation or Mongoid::Criteria, and with batch-loader, we're actually returning a BatchLoader. If I replace our FindUnicorns resolver with this:
class FindUnicornsNoBatch < BaseResolver
type Types::UnicornType
def call(_obj, _args, ctx)
Unicorn.all
end
end
...then the Scope#resolve method is called as I desire.
My question is: is there a way I can use these two libraries together? Perhaps I should batch after applying the policy? Or maybe patch GraphQL Pro to also invoke the policy scope if the object type is BatchLoader? My goal is to achieve the efficiency of batch loading and caching Unicorn results, while also ensuring that no user receives Unicorns which they do not deserve.
I'm running into a bit of difficulty using GraphQL Pro's Pundit authorization with batch-loader. We've set up a base resolver class like so:
and then a specific resolver might look like this:
and we have a policy like this:
The trouble is that GraphQL Pro will only invoke the
UnicornPolicy::Scope#resolve
method if the resolver returns anActiveRecord::Relation
orMongoid::Criteria
, and with batch-loader, we're actually returning aBatchLoader
. If I replace our FindUnicorns resolver with this:...then the
Scope#resolve
method is called as I desire.My question is: is there a way I can use these two libraries together? Perhaps I should batch after applying the policy? Or maybe patch GraphQL Pro to also invoke the policy scope if the object type is
BatchLoader
? My goal is to achieve the efficiency of batch loading and caching Unicorn results, while also ensuring that no user receives Unicorns which they do not deserve.