# frozen_string_literal: true require 'pundit' module GraphQL module Pundit module Instrumenters # Instrumenter that supplies `scope` class Scope attr_reader :current_user def initialize(current_user = :current_user) @current_user = current_user end # rubocop:disable Metrics/MethodLength, Metrics/AbcSize def instrument(_type, field) # rubocop:enable Metrics/MethodLength, Metrics/AbcSize scope = field.metadata[:scope] return field unless scope unless valid_value?(scope) raise ArgumentError, 'Invalid value passed to `scope`' end old_resolve = field.resolve_proc scope_proc = lambda do |obj, _args, ctx| ::Pundit.policy_scope!(ctx[current_user], obj) end scope_proc = scope if proc?(scope) field.redefine do resolve(lambda do |obj, args, ctx| new_scope = scope_proc.call(obj, args, ctx) old_resolve.call(new_scope, args, ctx) end) end end private def valid_value?(value) inferred?(value) || proc?(value) end def proc?(value) value.respond_to?(:call) end def inferred?(value) value == :infer_scope end end end end end