简体   繁体   English

Rails-在策略中使用Pundit范围

[英]Rails - with Pundit Scopes in policy

I am trying to figure out how to use pundit policy scopes in my article policy. 我试图找出如何在我的文章政策中使用权威政策范围。

I have written an article policy, that nests a scope and then has a resolve method in it. 我写了一个文章策略,该策略嵌套一个作用域,然后在其中包含一个resolve方法。 The resolve method has alternatives based on who the current_user is. resolve方法具有根据current_user是谁的替代方法。

My article policy has: 我的文章政策有:

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

The example in the pundit docs shows how to use this for an index, but how do I use the resolve method for a show action? Pundit文档中的示例显示了如何将其用于索引,但是如何将resolve方法用于show操作? Can I write several resolve methods for the various other controller actions? 我可以为其他各种控制器操作编写几种解析方法吗?

Pundit Scopes 专家范围

I dont have much experience with pundit , however by looking at documentation and your code the code I can see 2 things. 我没有关于pundit丰富经验,但是通过查看文档和您的代码,我可以看到两件事。

1 - You shouldnt use methods like show? 1-您不应该使用show?方法show? inside your scope class. 在您的范围类中。

inside your scope class, you should use only methods that returns a scope. 在作用域类中,应仅使用返回作用域的方法。 the methods that returns boolean should be in the Policy level. 返回布尔值的方法应该在“策略”级别。 But in your code I can boolean methods inside the scope class. 但是在您的代码中,我可以在作用域类中布尔化方法。

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.

from the docs 从文档

2 - Given that Scope are POROs (Plain Old Ruby Object) you can have more than one resolve methods (of course with a different name :)), because resolve is just a method name. 2-鉴于Scope是PORO(普通的旧Ruby对象),您可以拥有多个resolve方法(当然使用不同的名称:)),因为resolve只是方法名称。

May be you can do something like 也许你可以做类似的事情

#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

in your controller 在您的控制器中

#Articles controller
class ArticlesController < ApplicationController
  ...
  def show
    authorize Article 
    ArticlePolicy::Scope.new(current_user, Article).resolve_show
  end
  ...
end

This should first authorize your show method with ArticlePolicy#show? 这首先应该使用ArticlePolicy#show?授权您的show方法ArticlePolicy#show? and the scope from ArticlePolicy::Scope#resolve_show ArticlePolicy::Scope#resolve_show

Disclaimer: Untested code, use at your own risk ;) 免责声明:未经测试的代码,使用后果自负;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM