如何使用 Pundit 限制对用户资源索引操作的授权?我不认为答案是范围
How do I restrict authorization to a user's resource index action using Pundit? I don't think the answer is scope
我在使用 Pundit 时遇到嵌套资源的索引操作授权问题。 Pundit 非常精巧,而且可能很简单,我不想把它扔到一边,因为我无法弄清楚这一点。我想一旦我理解了这部分,其他所有内容都会内嵌。我已经阅读了很多人的帖子,他们提出的问题与我所问的问题非常相似,而且似乎最接近我所问问题的帖子从未得到解决。所以,我还在寻找答案。
class User < ApplicationRecord
enum role: [:user, :admin]
after_initialization :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
has_many :galleries, dependent: :destroy
end
class Gallery < ApplicationRecord
belongs_to :user
validates :user_id, presence: true
validates :title,, presence: true
end
我让用户使用 UserPolicy 设置我想要的方式。它不是从 ApplicationPolicy 继承的,因为我正在看的教程说我不需要它。
我的路线是这样的:
devise_for :users, path: 'accounts
resources :users, shallow: true do
resources :galleries
end
基本上我不希望一个用户看到另一个用户的东西,即索引、显示...操作。我相信这被称为封闭系统。我查看用户图库(我的嵌套资源)索引的路径如下所示:
localhost:/users/20/galleries
我不想让用户 19 看到用户 20 在他们的画廊索引中有什么。我该怎么做?
这是我的 GalleryController 的样子:
before_action :authenticate_user! #I'm using devise
def index
@galleries = current_user.galleries.all
#authorize ????? <<part of what I don't understand
end
private
def gallery_params
params.require(:gallery).permit(:title)
end
我真的不知道我应该在 GalleryPolicy 中为索引做什么。我已经制定了 show 操作,因为它只是根据用户 ID 的实例检查图库的实例。这是 GalleryPolicy
attr_reader :user, :model
def initialize(user, model)
@user = user
@gallery = gallery
end
def show?
@gallery.user_id == user.id
end
def index?
# I can't figure it out
end
def new?
#actually this is confusing too
end
首先,我一直编写继承自 ApplicationPolicy 的 Pundit 策略,所以让我们从那里开始。 ApplicationPolicy 使用用户和记录进行初始化。该记录将是您希望用户有权查看的模型。在这种情况下,画廊。
其次,每个策略都应该包含一个范围。这也在 ApplicationPolicy 内部初始化,但您的工作是根据需要限制范围。
class GalleryPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.where(:user_id => user.id)
end
end
# no need for an index? method here. we will see this in the controller
# essentially here we are checking that the user associated to the record
# is the same as the current user
def show?
record.user == user
end
# this is actually already the case in ApplicationPolicy but I added
# it here for clarity
def new?
create?
end
# who do we want to be able to create a gallery? anyone!
# so this simple returns true
def create?
true
end
end
然后在您的 GalleryController 中,您将每次授权模型。只有索引操作有点不同,我们现在将看到:
# controllers/gallery_controller.rb
def index
@galleries = policy_scope(Gallery)
# as we specified the scope in GalleryPolicy to only include galleries which belong
# to the current user this is all we need here!
end
# your other actions will look something like this:
def show
@gallery = Gallery.find(params[:gallery_id]
authorize @gallery
end
def new
@gallery = Gallery.new # or @gallery = current_user.galleries.build
authorize @gallery
end
[...]
希望对您有所帮助!一旦您掌握了 Pundit,它就是一个非常棒的工具。
我在使用 Pundit 时遇到嵌套资源的索引操作授权问题。 Pundit 非常精巧,而且可能很简单,我不想把它扔到一边,因为我无法弄清楚这一点。我想一旦我理解了这部分,其他所有内容都会内嵌。我已经阅读了很多人的帖子,他们提出的问题与我所问的问题非常相似,而且似乎最接近我所问问题的帖子从未得到解决。所以,我还在寻找答案。
class User < ApplicationRecord
enum role: [:user, :admin]
after_initialization :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
has_many :galleries, dependent: :destroy
end
class Gallery < ApplicationRecord
belongs_to :user
validates :user_id, presence: true
validates :title,, presence: true
end
我让用户使用 UserPolicy 设置我想要的方式。它不是从 ApplicationPolicy 继承的,因为我正在看的教程说我不需要它。
我的路线是这样的:
devise_for :users, path: 'accounts
resources :users, shallow: true do
resources :galleries
end
基本上我不希望一个用户看到另一个用户的东西,即索引、显示...操作。我相信这被称为封闭系统。我查看用户图库(我的嵌套资源)索引的路径如下所示:
localhost:/users/20/galleries
我不想让用户 19 看到用户 20 在他们的画廊索引中有什么。我该怎么做?
这是我的 GalleryController 的样子:
before_action :authenticate_user! #I'm using devise
def index
@galleries = current_user.galleries.all
#authorize ????? <<part of what I don't understand
end
private
def gallery_params
params.require(:gallery).permit(:title)
end
我真的不知道我应该在 GalleryPolicy 中为索引做什么。我已经制定了 show 操作,因为它只是根据用户 ID 的实例检查图库的实例。这是 GalleryPolicy
attr_reader :user, :model
def initialize(user, model)
@user = user
@gallery = gallery
end
def show?
@gallery.user_id == user.id
end
def index?
# I can't figure it out
end
def new?
#actually this is confusing too
end
首先,我一直编写继承自 ApplicationPolicy 的 Pundit 策略,所以让我们从那里开始。 ApplicationPolicy 使用用户和记录进行初始化。该记录将是您希望用户有权查看的模型。在这种情况下,画廊。
其次,每个策略都应该包含一个范围。这也在 ApplicationPolicy 内部初始化,但您的工作是根据需要限制范围。
class GalleryPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.where(:user_id => user.id)
end
end
# no need for an index? method here. we will see this in the controller
# essentially here we are checking that the user associated to the record
# is the same as the current user
def show?
record.user == user
end
# this is actually already the case in ApplicationPolicy but I added
# it here for clarity
def new?
create?
end
# who do we want to be able to create a gallery? anyone!
# so this simple returns true
def create?
true
end
end
然后在您的 GalleryController 中,您将每次授权模型。只有索引操作有点不同,我们现在将看到:
# controllers/gallery_controller.rb
def index
@galleries = policy_scope(Gallery)
# as we specified the scope in GalleryPolicy to only include galleries which belong
# to the current user this is all we need here!
end
# your other actions will look something like this:
def show
@gallery = Gallery.find(params[:gallery_id]
authorize @gallery
end
def new
@gallery = Gallery.new # or @gallery = current_user.galleries.build
authorize @gallery
end
[...]
希望对您有所帮助!一旦您掌握了 Pundit,它就是一个非常棒的工具。