簡體   English   中英

Rails 授權 CanCanCan

[英]Rails authorization CanCanCan

我正在嘗試使用 CanCanCan gem 實現對路由的一些授權,但對於某些路由,它不起作用,並且它要么始終授權,要么根本沒有授權。

我只希望角色 id 為 5 (admin) 的用戶訪問價格控制器的更新操作,這是我的 ability.rb 代碼:

class Ability
  include CanCan::Ability

  def initialize(user)

    user ||= User.new
    # Define abilities for the passed in user here. For example:
    if user.present?
      can :show, User

      if user.role.id == 5
        can [:index, :update, :create], User
      end

      can :update, PricesController if user.role.id == 3
    #
    # The first argument to `can` is the action you are giving the user
    # permission to do.
    # If you pass :manage it will apply to every action. Other common actions
    # here are :read, :create, :update and :destroy.
    #
    # The second argument is the resource the user can perform the action on.
    # If you pass :all it will apply to every resource. Otherwise pass a Ruby
    # class of the resource.
    #
    # The third argument is an optional hash of conditions to further filter the
    # objects.
    # For example, here the user can only update published articles.
    #
    #   can :update, Article, :published => true
    end
  end
end

索引等的第一個操作正常工作,對於第二個操作,我調試了角色 id 也正確找到。 所以故障必須在我的控制器中,這是我的代碼:

def update
    authorize! :update, current_user

    if @prices.where(description: params[:description]).update(price_params)
      respond_to do |format|
        format.html { redirect_to prices_path }
        format.json { render json: @prices }
      end
    end  
  end

如果我使用current_user來檢查授權方法,每個人都可以更改值,如果我使用@prices的實例變量,則沒有人可以執行控制器操作。

我也在處理異常:

rescue_from CanCan::AccessDenied do |e|
    respond_to do |format|
      format.html { redirect_to current_user, flash: { alert: "Sie besitzen dafür keine Berechtigung!" } }
      format.json { render json: { success: false }, status: 401 }
    end
  end

我一遍又一遍地閱讀文檔,但我無法弄清楚我的錯在哪里。

一些不同的評論:

以你的能力.rb 我會說使用

if user.role.name == 'admin'

代替

if user.role.id == 5

除非您手動設置您的 id,否則您很可能必須更改它以進行生產。

can :update, PricesController if user.role.id == 3

應該

can :update, Price if user.role.id == 3

並在您的控制器中替換

authorize! :update, current_user

authorize! :update, Price

通常在 rails 更新操作中,您將只更新一個對象,並使用以下方法對其進行授權:

authorize! :update, @price

但在你的情況下,我猜想通過模型授權是你最好的途徑。

能力定義應該是:

can :update, Price if user.role.id == 3

您授權模型 - 而不是控制器。

調用授權時,您應該傳遞正在更新的資源實例或類(如果沒有實例):

authorize! :read, @thing
authorize! :index, Thing

但是控制器本身從根本上就以與 CanCanCan 無關的方式被破壞了。 這就是一切崩潰的地方:

@prices.where(description: params[:description]).update(price_params)

where返回記錄的集合 - #update是一種在單個記錄上調用的方法。 我不知道這是否是一次非常幼稚且失敗的大規模更新嘗試,或者您是否正在嘗試執行諸如 slug 列(漂亮的 url)之類的操作。 但是您可能應該堅持使用 rails 約定,直到您知道自己在做什么:

def update
  @price = Price.find(params[:id])
  authorize!(:update, @price)
  if @price.update
    # ...
  else
    # ...
  end
end

在這種情況下,您也可以只使用load_and_authorize_resource而不是手動查找和授權。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM