当前位置 : 主页 > 编程语言 > ruby >

ruby-on-rails – cancancan authorize_resource无法按预期工作

来源:互联网 收集:自由互联 发布时间:2021-06-23
我收到一个简单的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
我收到一个简单的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应该这样做.

发生的事情是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调用之前使用您的自定义方法手动加载资源.

网友评论