Rails 6 - Pundit“策略包装器”

Posted

技术标签:

【中文标题】Rails 6 - Pundit“策略包装器”【英文标题】:Rails 6 - Pundit "policy wrapper" 【发布时间】:2020-07-24 09:34:49 【问题描述】:

我有点迷恋 Pundit:感觉解决方案应该很简单 - 但我不明白。实际上我有一堆模型都依赖于一个主要模型。我的主要模型是脚本。该脚本有许多角色、许多场景、许多服装等。此外,它还具有一些连接的连接,例如 scene.roles。我只是想授权创建脚本的用户做所有事情(添加角色、删除场景,只是在她自己的脚本范围内的所有事情),而其他人什么都不做(和看)。我需要为每个模型创建一个策略,还是我可以(重新)以某种方式使用一个“脚本策略”?

授权在依赖控制器中的外观如何(即角色中的“索引”或场景中的“新”)?

身份验证由设备处理。用户必须登录才能查看或执行任何操作。 这是我关于堆栈溢出的第一篇文章,很高兴加入社区:-)

【问题讨论】:

欢迎来到 SO,PixAff! Pundit 策略只是 PORO,因此您可以简单地创建一个共享类并为每个模型继承它。如果您需要对给定模型的不同权限,您可以覆盖继承的方法。 【参考方案1】:

在你的控制器中调用authorize方法时,可以指定策略类:

authorize @model, policy_class: ScriptPolicy

我发现这个解决方案生成的样板文件更少。

授权范围:

scenes = policy_scope(Scene, policy_scope_class: ScriptPolicy::Scope)

顺便说一句,这一切都在权威人士的自述文件中介绍:https://github.com/varvet/pundit

【讨论】:

谢谢@cesartalves!我可以用索引方法做同样的事情吗?像这样:@scene = policy_scope(Script)? 添加到答案中【参考方案2】:

Pundit 策略是 PORO(普通的旧 ruby​​ 对象)。因此,您可以轻松地为主模型创建策略:

class ScriptPolicy
  attr_reader :user, :script

  def initialize(user, script)
    @user = user
    @script = script
  end

  def update?
      user.actor?
  end

  def delete?
      user.admin?
  end
end

然后对于您拥有的每个模型,只需创建一个继承自 ScriptPolicy 的空类定义

class ScenePolicy < ScriptPolicy
end

另一种方法是覆盖 Pundit 在子模型中直接引用的策略名称。所以假设你有一个模型Scene,它应该使用与Script相同的策略,你可以添加一个方法:

class Scene < ActiveRecord::Base
  def self.policy_class
     ScriptPolicy
  end
end

在后者中,您不需要为每个模型创建空策略类,但是您可以用它来换取在为模型定义特定权限时降低的灵活性。

【讨论】:

感谢您采用这种(经典)方法! (两个版本)在控制器中的外观如何?我会在场景控制器中authorize @scene 吗?我将如何授权 scene#index 方法?

以上是关于Rails 6 - Pundit“策略包装器”的主要内容,如果未能解决你的问题,请参考以下文章

Ruby - Rails 4 - Pundit - 路由#index_fr 的策略和授权错误?

Rails 5,具有命名空间资源的Pundit

Rails 4 with Pundit & Statesman gem - 对象处于状态时的策略

Authorization With Pundit

具有两个输入参数的 Pundit 策略

如何为 Rails 中枚举中列出的角色添加模型?