Pundit中的管理员权限与嵌套资源以及如何处理索引操作

时间:2016-09-21 15:31:34

标签: ruby-on-rails rubygems authorization pundit

我是专家,并尝试提出处理索引操作的嵌套资源的最佳方法。我找到了similar question,但它没有处理管理员权限,我只是不确定我的解决方案是否感觉非常正确。

我们说我有两个模型,一个User可以有很多笔记,一个Note属于一个用户。用户无法查看其他用户的注释,除非他们是管理员。同时,管理员可以创建自己的笔记,因此还必须能够通过自己的索引操作检索它们的列表。

的routes.rb

resources :users, only: :show do
  resources :notes
end

notes_controller.rb

class NotesController < ApplicationController

  #would probably move to application_controller.rb
  after_action :verify_authorized
  after_action :verify_policy_scoped

  def index
    user = User.find(params[:user_id])
    @notes = policy_scope(user.notes)
    authorize user
  end

  #additional code
end

note_policy.rb

class NotePolicy < ApplicationPolicy

  class Scope < Scope
    def resolve
      if user.admin? && scope != user.notes
        scope
      else
        user.notes
      end
    end
  end

  #additional code
end

user_policy.rb

class UserPolicy < ApplicationPolicy

  def index?
    user == record || user.admin?
  end

  #additional code
end

1 个答案:

答案 0 :(得分:0)

你正在思考它:

class NotePolicy < ApplicationPolicy

  class Scope < Scope
    def resolve
      scope.where(user: user)
    end
  end

  def index?
    record == user || user.admin?
  end

  # ...
end

请注意,从policy_scope传入的范围链接是一个好主意。它允许您的控制器设置与授权无关的任何范围,例如分页。

同样在index?我们稍微作弊。我们只是传递用户而不是传递一个音符实例。

class NotesController < ApplicationController

  before_action :set_user!, only: [:index] # ...
  before_action :set_note!, only: [:show, :edit, :update, :destroy]

  def index
    @notes = policy_scope(Note.all)
    authorize(@user)
  end

  # ...

  private
    def set_user!
      @user = User.find(params[:user_id])
    end 

    def set_note!
      @note = authorize( Note.find(params[:id]) )
    end
end

以这种方式使用before_action是一个非常好的模式,因为它设置了所有“成员”操作以进行授权。