【问题标题】:Is it possible to use pundit authorization with graphql是否可以将权威授权与 graphql 一起使用
【发布时间】:2017-09-15 12:47:10
【问题描述】:

我想做这样的事情:

authorize record, :some_action

在解析graphql字段或突变(例如突变)

module Mutations::CreateLink
  CreateLink = GraphQL::Relay::Mutation.define do
    name "CreateLink"

    input_field :name, types.String
    input_field :url, types.String
    input_field :description, types.String

    return_field :link, Types::LinkType

    resolve -> (object, inputs, ctx) {
      Rails::logger.ap ctx[:current_user]
      Rails::logger.ap inputs[:name]
      ctx[:current_user]
      @link = Link.new(name: inputs[:name], url: inputs[:url], description: inputs[:description])
      authorize @link, :create?
      response = {
          link: @link
      }
    }
  end
end

运行上述程序时会显示此错误: NoMethodError - GraphQL::Relay::Mutation 无法定义“授权”

通常你会写

include Pundit

在您的控制器中,但将其添加到 GraphqlController 没有任何区别。

如何让 graphql 了解 pundit 及其方法?

【问题讨论】:

    标签: ruby-on-rails graphql pundit


    【解决方案1】:

    include Pundit 不起作用的原因是当你包含一个模块时,include 被添加到类中,而 authorize 方法无论如何都不起作用,因为它意味着被包含在控制器中并基于此做出假设。

    但是手动初始化策略真的很容易:

    class ApplicationPolicy
      attr_reader :user, :record
    
      def initialize(user, record)
        @user = user
        @record = record
      end
    end
    

    您可以通过在策略上调用适当的方法来授权:

    unless LinkPolicy.new(ctx[:current_user], @link).create?
      raise Pundit::NotAuthorizedError, "not allowed to create? this #{@link.inspect}"
    end
    

    【讨论】:

      【解决方案2】:

      我在这篇博文Graphql ruby and authorization with pundit 中找到了一个巧妙的解决方案

      建议您在 graphqlcontroller 中添加 include Pundit,然后将控制器添加为上下文,如下所示:

      context = {
        current_user: current_user,
        pundit: self
      }
      

      然后在解析字段和突变时,授权方法是这样暴露的:

      ctx[:pundit].authorize @link, :create?
      

      Pundit 知道用户是上下文中的 current_user 并引发相应的错误。

      【讨论】:

        【解决方案3】:

        使用更高版本的 graphql-ruby(我在撰写本文时使用的是 1.9.17),您可以在突变中定义 authorized? 方法并包含以下内容...

        Pundit.authorize context[:current_user], @link, :create?
        

        有关 Pundit authorize 类方法的详细信息,请参阅 https://github.com/varvet/pundit/blob/df96d2ae6bcf28991c1501d5ff0bde4c42aa4acd/lib/pundit.rb#L60-L76

        有关 graphql-ruby 的 authorized? 方法的详细信息,请参阅 https://graphql-ruby.org/mutations/mutation_authorization.html#can-this-user-perform-this-action

        【讨论】:

          【解决方案4】:

          graphql-rubypaid versionpundit integration

          但您也可以通过调用手动使用Pundit

          Pundit.authorize(context[:current_user], record, :some_action)
          
          Pundit.policy_scope(context[:current_user], RecordClass)
          

          但是,这不能满足verify_authorizedverify_policy_scoped。为此,您需要在控制器上调用authorizepolicy_scope,类似于@TamRock 的回答:

          graphql_controller.rb

          class GraphqlController < ApplicationController
            include Pundit::Authorization
            after_action :verify_authorized
            after_action :verify_policy_scoped
          
            public :policy_scope
            public :authorize
          
            # ...
          
            def execute
              # ...
          
              context = {
                controller: self
              }
          
              # ...
            end
          end
          

          然后在解析器中:

          context[:controller].policy_scope(RecordClass)
          context[:controller].authorize(record, :some_action)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-28
            • 1970-01-01
            • 2018-11-05
            • 2020-11-26
            • 1970-01-01
            相关资源
            最近更新 更多