【问题标题】:Getting boolean instead of record when authorizing with Pundit使用 Pundit 授权时获取布尔值而不是记录
【发布时间】:2017-05-18 10:26:45
【问题描述】:

根据the Pundit readme authorize 应该返回记录,但是当我调用它时,我得到了true。

authorize 返回传递给它的对象,因此您可以像这样链接它 这个:

控制器:

def show
  @user = authorize User.find(params[:id])
end

宝石文件:

gem 'rails', '~> 5.1.1'
gem 'devise', '~> 4.3'
gem 'pundit', '~> 1.1'

我的控制器:

class PostsController < ApplicationController
  skip_before_action :authenticate_user!, only: [:show, :index]
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  def show
    # just for debugging purposes
    raise "Post is a #{@post.class.name}!" unless @post.is_a? Post
  end

  def set_post
    # this should return an instance of post
    @post = authorize Post.find(params[:id])
  end
end

政策:

class PostPolicy < ApplicationPolicy

  class Scope < Scope
    def resolve
      scope.all
    end
  end

  def show?
    true
  end

  # ...
end

规格:

require 'rails_helper'
RSpec.describe "Posts", type: :request do
  subject { response }

  describe "GET /posts/:id" do
    let!(:post) { create(:post) }
    before { get post_path(post) }
    it { should be_successful }
  end
end

失败信息:

  4) Posts GET /posts/:id 
     Failure/Error: raise "Post is a #{@post.class.name}!" unless @post.is_a? Post

     RuntimeError:
       Post is a TrueClass!

虽然通过以下方式解决这个问题很简单:

def set_post
  @post = Post.find(params[:id]).tap do |p|
    @post = Post.find(params[:id]).tap { |r| authorize r }
  end
end

我很好奇为什么它不像自述文件中所说的那样工作。这是一个错误还是我只是错过了什么?

【问题讨论】:

    标签: ruby-on-rails pundit


    【解决方案1】:

    返回记录显然是在 1.1 版本中未反映的 master 中的更改。

    # Retrieves the policy for the given record, initializing it with the
    # record and user and finally throwing an error if the user is not
    # authorized to perform the given action.
    #
    # @param user [Object] the user that initiated the action
    # @param record [Object] the object we're checking permissions of
    # @param record [Symbol] the query method to check on the policy (e.g. `:show?`)
    # @raise [NotAuthorizedError] if the given query method returned false
    # @return [true] Always returns true
    def authorize(user, record, query)
      policy = policy!(user, record)
    
      unless policy.public_send(query)
        raise NotAuthorizedError, query: query, record: record, policy: policy
      end
    
      true
    end
    

    解决方法是:

    def authorize(record, query = nil)
      super
      record 
    end
    

    【讨论】:

      猜你喜欢
      • 2017-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-14
      • 2017-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多