我收到一个简单的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 u
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应该这样做.
发生的事情是authorize_resource在show动作之前发生,并且由于@service_order尚未设置,它正在检查类,并且用户确实有权在约束下显示ServiceOrder.Adding authorize_resource will install a before_action callback that calls authorize!, passing the resource instance variable if it exists. If the instance variable isn’t set (such as in the index action) it will pass in the class name. For example, if we have a ProductsController it will do this before each action.
authorize!(params[:action].to_sym, @product || Product)
from Cancancan documentations
你需要做的是按照widjajayd的建议加载load_and_authorize_resource.或者(如果您不想使用cancancan默认加载操作)执行before_filter,在authorize_resource调用之前使用您的自定义方法手动加载资源.