ruby-on-rails - 为什么在Pundit中对待面向 `scope`的 Action (尤其是 `index` Action )有不同的对待?

标签 ruby-on-rails authorization pundit

我在写有关https://github.com/elabs/pundit#scopes的文章

我的印象是授权应回答您是否允许访问此资源的问题,即true/false答案。除index之外的所有操作都是这种情况,根据Pundit的文档,根据谁在询问,该操作应返回不同的ActiveRecord::Relation。例如,管理员获取scope.all,而普通用户获取scope.where(:published => true)

应用程序/策略/post_policy.rb

class Scope < Struct.new(:user, :scope)
  def resolve
    if user.admin?
      scope.all
    else
      scope.where(:published => true)
    end
  end
end

应用程序/ Controller /posts_controller.rb
def index
  @posts = policy_scope(Post)
end

我的保留意见是这是一个滑坡,不久我将在范围内添加演示文稿(例如scope.all.order('created_at ASC'))-在授权策略中这样做听起来很奇怪。

我当然可以将其移到 Controller 上。
def index
    @post = policy_scope(post)
    if user.admin?
        @post = @post.order( 'created_at ASC' )
    end
end

...但是那是管制员的工作吗?而且我认为在 View 中添加这样的调用是不正确的。所以也许应该是一种模型方法?

您说做以下事情的利弊是什么?

应用程序/ Controller /posts_controller.rb

这使index像其他方法一样保持不变,只调用一次authorize,一次调用模型方法。
def index
  authorize(Post)
  @posts = Post.index(current_user)
end

应用程序/策略/post_policy.rb

这只是给出了对/错的答案。您被授权了吗?是还是不是。
def index?
    user.admin? || user.regular_user?
end

应用程序/模型/post.rb

在模型中,我们可以根据自己的喜好进行选择。
def self.index(user)
  if user.admin?
    Post.all.order('created_at ASC')
  else
    Post.where(user_id: user.id)
  end
end

有什么想法吗?

最佳答案

我对Pundit中授权与作用域的理解如下:
authorization:“是否允许此用户对(创建/更新/销毁)该资源采取行动?”
within scope:“此用户应该能够看到(索引/显示)此资源吗?”

授权(authorize @resource)遵循permitted_attributes中的ResourcePolicy来获取答案。

范围(policy_scope(Resource))取决于resolve

我相信Pundit范围的背后原因是,您的代码中应该只有一个位置,您可以在其中定义谁有权访问哪些资源。

如前所述,您可以在 Controller 或 View 中实现相同的行为。但是,将代码放入策略中可以防止未经授权的访问,以防您忘记在一种 Controller 方法中适当调整范围。

我认为policy_scope()是限制可见性的方法,而其他结果优化(例如排序)可以在 Controller 级别进行。但是,毫无疑问,有很多个人喜好在起作用。

关于ruby-on-rails - 为什么在Pundit中对待面向 `scope`的 Action (尤其是 `index` Action )有不同的对待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21172620/

相关文章:

html - 在 Rails 翻译文件中使用 HTML

ruby-on-rails - 分布式系统的认证和授权

c# - 在ASP.Net核心中应用粒度权限限制

Java web应用认证-账户设计

ruby-on-rails - 如何覆盖 View 中的策略类

ruby-on-rails-5 - 如何将 Pundit 与 Actioncable 结合使用(Rails 5)

ruby-on-rails - 样式表的条件加载

mysql - 为多个查询获取 rails ActiveRecord 而不是对象数组

c# - 自定义 ASP.NET MVC 表单例份验证

ruby-on-rails - Rails 5 - 如何使用 Pundit