cancancan authorize_resource无法按预期工作

时间:2017-07-11 15:07:12

标签: 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

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

class ServiceOrdersController < ApplicationController
  authorize_resource

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

end

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

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

authorize! :show, @service_order
像这样:

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

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

2 个答案:

答案 0 :(得分:5)

发生的事情是authorize_resource在show动作之前发生,并且因为@service_order尚未设置,它正在检查该类,并且用户有权显示{ {1}}受到限制。

  

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

     

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

from Cancancan documentations

根据widjajayd的建议,您需要做的是ServiceOrder。或者(如果您不想使用cancancan默认加载操作)执行load_and_authorize_resource,在before_filter调用之前使用自定义方法手动加载资源。

答案 1 :(得分:2)

我的建议:改为使用authorize_resource你使用load_and_authorize_resource,下面是你的控制器的示例 只需确保您的strong_parameters声明:service_order_params

  load_and_authorize_resource param_method: :service_order_params