9

我写的是关于https://github.com/elabs/pundit#scopes

我的印象是授权应该回答您是否允许访问此资源的问题?,即一个true/false答案。除了 之外的所有操作都是这种情况index,根据 Pundit 的文档,它应该根据提问者返回不同ActiveRecord::Relation的 's。例如,管理员得到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

应用程序/控制器/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

想法?

4

1 回答 1

12

我对 Pundit 中授权与范围的理解如下:

authorization: '这个用户是否允许对这个资源采取行动(创建/更新/销毁)

within scope:“这个用户应该能够看到(索引/显示)这个资源吗?”

授权(authorize @resource)以permitted_attributesinResourcePolicy为答案。

范围 ( policy_scope(Resource)) 遵循resolve.

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

正如您所描述的,您可以在控制器或视图中实现相同的行为。但是,如果您碰巧忘记在您的控制器方法之一中适当地确定范围,将代码放入 Policy 可以防止未经授权的访问。

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

于 2014-03-10T00:43:11.693 回答