我在写有关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/