Pundit:授权命名空间控制器内的操作

Pundit: authorize actions within namespaced controllers

我有一个具有不同状态的 Blog 模型。为了保持瘦控制器并遵循每个控制器仅具有 CRUD 操作的惯例,我遵循 DHH's namespacing controllers pattern 并命名空间 Blog 控制器。

现在我有一个 Blogs::NewDraft 控制器、一个 Blogs::AwaitingApproval 控制器和一个 Blogs::Active 控制器。

问题在于编写我的策略来授权这些命名空间控制器中的操作。所有命名空间控制器中的所有操作都授权相同的 Blog 模型对象。问题是我需要每个命名空间控制器在匹配的命名空间策略中授权(而不是在同一个 blog_policy.rb 文件中授权所有命名空间控制器。)

基本示例:对于具有未命名空间的 restful 控制器的 restful 资源,您可以这样做:

#app/controllers/blogs_controller.rb
class BlogsController < ApplicationController
  def index
    authorize :blog
    @blogs = Blog.all
  end

  def show
    @blog = Blog.find(1)
    authorize @blog
  end
end

现在匹配政策

#app/policies/blogs_policy.rb
class BlogPolicy < ApplicationPolicy
  def index?
    user.admin?
  end

  def show?
    record.author == current_user
  end
end

当你没有命名空间时,你就是这样做的。


尝试让命名空间与 Pundit 一起工作的当前代码:我正在命名空间。我仍在授权一个 Blog 对象,但我需要在命名空间策略中授权每个命名空间控制器内的操作:

#app/controllers/blogs/new_drafts.rb
class Blogs::NewDraftsController < ApplicationController
  def index
    # doesn't work
    authorize Blog::NewDrafts
    @blogs = Blog.new_drafts
  end
  def show
    @blog = Blog.find(1)
    #doesn't work either
    authorize @blog, Blog::NewDraft
  end
end

所以我希望命名空间控制器不路由到 app/policies/blog_policy.rb,而是路由到 app/policies/blogs/new_draft_policy.rb

#app/policies/blogs/new_draft_policy.rb
class Blogs::NewDraftPolicy < ApplicationPolicy
  def index?
    user.admin?
  end

  def show?
    # the record is a blog from the Blog Model
    record.author == current_user
  end
end

Pundit Documentation and Usage

不知道如何路由到命名空间策略并传入 Blog 记录。但是:以下是当您的命名空间策略只能根据当前用户的 permissions/roles:

进行授权时的操作方法
#app/controllers/blogs/new_drafts.rb
class Blogs::NewDraftsController < ApplicationController
  def index
    authorize [:blogs, :new_draft]
    @blogs = Blog.new_drafts
  end
end

#app/policies/blogs/new_draft_policy.rb
class Blogs::NewDraftPolicy < ApplicationPolicy
  def index?
    user.admin?
  end
end