我是专家,并尝试提出处理索引操作的嵌套资源的最佳方法。我找到了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
答案 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
是一个非常好的模式,因为它设置了所有“成员”操作以进行授权。