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 的策略和授权错误?