我收到一个简单的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
应该这样做。
答案 0 :(得分:5)
发生的事情是authorize_resource
在show动作之前发生,并且因为@service_order
尚未设置,它正在检查该类,并且用户有权显示{ {1}}受到限制。
添加authorize_resource将安装一个调用authorize!的before_action回调,并传递资源实例变量(如果存在)。如果未设置实例变量(例如在索引操作中),则它将传入类名。例如,如果我们有一个ProductsController,它将在每个动作之前执行此操作。
授权!(参数[:action] .to_sym,@ product || Product)
根据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