我试图弄清楚如何在我的文章政策中使用权威政策范围。
我写了一篇文章策略,它嵌套了一个范围,然后在其中有一个解决方法。解决方法具有基于current_user
是谁的替代方案。
我的文章政策有:
class ArticlePolicy < ApplicationPolicy
class Scope < Scope
attr_reader :user, :scope
# I now think I don't need these actions because I have changed the action in the articles controller to look for policy scope.
# def index?
# article.state_machine.in_state?(:publish)
# end
def show?
article.state_machine.in_state?(:publish) ||
user == article.user ||
article.state_machine.in_state?(:review) && user.org_approver ||
false
end
end
def create?
article.user.has_role?(:author)
end
def update?
# user && user.article.exists?(article.id) #&& user.article.created_at < 15.minutes.ago
user.present? && user == article.user
# add current state is not published or approved
end
def destroy?
user.present? && user == article.user
# user.admin?
# user.present?
# user && user.article.exists?(article.id)
end
end
private
def article
record
end
def resolve
if user == article.user
scope.where(user_id: user_id)
elsif approval_required?
scope.where(article.state_machine.in_state?(:review)).(user.has_role?(:org_approver))
else
article.state_machine.in_state?(:publish)
end
end
def approval_required?
true if article.user.has_role?(:author)
# elsif article.user.profile.organisation.onboarding.article_approval == true
# if onboarding (currently in another branch) requires org approval
end
def org_approver
if article.user.has_role? :author
user.has_role? :editor
# if onboarding (currently in another branch) requires org approval, then the approval manager for that org
elsif article.user.has_role? :blogger
user.has_role? :editor if user.profile.organisation.id == article.user.profile.organisation.id
end
end
end
专家文档中的示例显示了如何将其用于索引,但如何将resolve方法用于show动作?我可以为各种其他控制器操作编写几种解决方法吗?
答案 0 :(得分:1)
我对pundit
没有多少经验,但是通过查看文档和代码,我可以看到两件代码。
1 - 您不应在范围类中使用show?
之类的方法。
Instances of this class respond to the method resolve, which should return some kind of result which can be iterated over. For ActiveRecord classes, this would usually be an ActiveRecord::Relation.
2 - 鉴于Scope是PORO(Plain Old Ruby Object),你可以拥有多个解析方法(当然使用不同的名称:)),因为resolve只是一个方法名称。
可能你可以做点什么
#policy
class ArticlePolicy < ApplicationPolicy
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
class Scope < Scope
def resolve
# some scope
end
def resolve_show
#scope for show action
# E.g scope.all
end
end
def show?
article.state_machine.in_state?(:publish) ||
user == article.user ||
article.state_machine.in_state?(:review) && user.org_approver || false
end
end
控制器中的
#Articles controller
class ArticlesController < ApplicationController
...
def show
authorize Article
ArticlePolicy::Scope.new(current_user, Article).resolve_show
end
...
end
首先应使用ArticlePolicy#show?
和ArticlePolicy::Scope#resolve_show
免责声明:未经测试的代码,使用风险自负;)