cancancan authorize_resource无法按预期工作

Aug*_*tos 4 ruby-on-rails cancan cancancan

我收到一个简单的cancancan授权的意外行为.

ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    # Define abilities for the passed in user here. For example:
    #
    user ||= User.new # guest user (not logged in)
    if user.is_admin?
        can :manage, :all
    elsif user.is_standard?
        can :manage, ServiceOrder, {user_id: user.id}
        can :manage, ServiceOrderDetail, :service_order => { :user_id => user.id }
    end
Run Code Online (Sandbox Code Playgroud)

service_order.rb控制器(部分显示)

class ServiceOrdersController < ApplicationController
  authorize_resource

  def show
    @service_order = ServiceOrder.includes(:service_order_details).find(params[:id])
  end

end
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为它让控制器显示任何service_order记录,而不仅仅是current_user拥有的记录.

这种方法的唯一方法是,如果我手动授权控制器添加:

authorize! :show, @service_order
Run Code Online (Sandbox Code Playgroud)

像这样:

  def show
    @service_order = ServiceOrder.includes(:service_order_details).find(params[:id])
    authorize! :show, @service_order
  end
Run Code Online (Sandbox Code Playgroud)

这是没有意义的,因为authorize_resource应该这样做.

Mic*_*man 7

发生的事情是在authorize_resourceshow动作之前发生的事情,并且由于@service_order尚未设置,它正在检查类,并且用户确实有权显示ServiceOrder刚刚受限制.

添加authorize_resource将安装一个调用authorize!的before_action回调,传递资源实例变量(如果存在).如果未设置实例变量(例如在索引操作中),则它将传入类名.例如,如果我们有一个ProductsController,它将在每个动作之前执行此操作.

授权!(params [:action] .to_sym,@ product || Product)

来自Cancancan文件

你需要做的是load_and_authorize_resource按照widjajayd的建议.或者(如果您不想使用cancancan默认加载操作)请before_filterauthorize_resource调用之前使用自定义方法手动加载资源.