为什么“范围”导向的行为(特别是“索引”行动)在Pundit中有不同的处理方式?
我写的是关于https://github.com/elabs/pundit#scopes
我的印象是授权应该回答问题您是否允许访问此资源? ,即一个true
/ false
答案。 除了index
之外的所有操作都是如此,根据Pundit的文档,这应该根据谁的要求返回不同的ActiveRecord::Relation
。 例如, admin获取scope.all
,而普通用户获取scope.where(:published => true)
。
应用程序/政策/ post_policy.rb
class Scope true) end end end
应用程序/控制器/ posts_controller.rb
def index @posts = policy_scope(Post) end
我的保留意见是这是一个很滑的斜坡,很快我就会在范围中添加演示文稿(例如scope.all.order('created_at ASC')
) – 而且在授权策略中这样做很奇怪。
当然我可以把它移到控制器……
def index @post = policy_scope(post) if user.admin? @post = @post.order( 'created_at ASC' ) end end
……但这是控制器的工作吗? 我不认为向视图添加这样的调用是正确的。 那么也许它应该是一种模型方法?
你会说什么是做以下事情的利弊?
应用程序/控制器/ 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
)延迟到ResourcePolicy
中的authorize @resource
以获得答案。
范围( policy_scope(Resource)
)推迟resolve
。
我相信Pundit范围背后的原因是代码中应该只有一个位置,您可以定义谁应该可以访问哪些资源。
正如您所描述的,您可以在控制器或视图中实现相同的行为。 但是,如果您在某个控制器方法中忘记了适当的范围,那么将代码放入策略中以防止未经授权的访问。
我认为policy_scope()
是限制可见性的方法,而其他结果改进(例如排序)可以在控制器级别进行。 然而,毫无疑问,在游戏中有很多个人偏好。