【问题标题】:Rails 4 - Pundit with Rolify - permitting a group of rolesRails 4 - Pundit with Rolify - 允许一组角色
【发布时间】:2016-06-02 14:24:00
【问题描述】:

我正在尝试使用 Rails 4 制作应用程序。

我已经用 Rolify gem 定义了一系列角色。

现在,我想使用 pundit 允许具有角色的用户执行某些操作。在不止一种类型的角色可以做某事的情况下,我定义了一组角色。

在我的 application_policy 中,我定义了私有方法,这些方法设置了我想在权威权限中使用的角色组。

我的应用程序策略实例化用户和记录。然后我将记录定义为相关模型的名称(与该模型的策略名称相同)。

我有:

class ApplicationPolicy
  attr_reader :user, :record

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

  def index?
    false
  end

  def show?
    scope.where(:id => record.id).exists?
  end

  def create?
    false
  end

  def new?
    create?
  end

  def update?
    false
  end

  def edit?
    update?
  end

  def destroy?
    false
  end

  def scope
    Pundit.policy_scope!(user, record.class)
  end

  class Scope
    attr_reader :user, :scope

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

    def resolve
      scope
    end
  end

  private


    def cf_legal
      [ :Admin, :CF_Legal, :CF_Policy_Manager ]
    end

    def cf_content
      [ :Admin, :CF_Author, :CF_Editor ]
    end


end

然后在我的内容政策中,我想说:

def record
   content
end

def create
    user.has_role? :cf_content
end

当我保存并尝试时,我看不到我应该看到的内容(作为具有作者角色的用户。

任何人都可以看到如何做到这一点?

【问题讨论】:

    标签: ruby-on-rails permissions roles pundit rolify


    【解决方案1】:

    tl;dr:在 Policy 类上使用查询方法。

    首先,模型应该有它自己的 Policy 类,它(可选地)扩展您的 ApplicationPolicy 类。假设您的模型名为Post。然后你可以这样做:

    class PostPolicy < ApplicationPolicy
    
       attr_reader :user, :post
    
       def initialize(user,post)
         @user = user
         @post = post
       end
    
       def create?
         cf_content.all? { |role| user.has_role?(role) }
       end
    
       private
    
       def cf_content
        [ :Admin, :Author, :Editor ]
       end
    end
    
    
    class PostsController
      def create
        @post = Post.new(params[:post])
        authorize @post, :create?
        # @post.save and redirect, etc.
      end
    end
    

    并且授权调用将调用create?查询方法并检查用户是否具有cf_content中的角色。

    您甚至可能不需要添加第二个参数 create?,正如专家 documentation 所说:

    authorize 方法自动推断 Post 将有一个 匹配 PostPolicy 类,并实例化该类,上交 当前用户和给定的记录。然后它从动作中推断 名称,它应该调用更新?在这个政策实例上。

    或者在你的情况下,create? 而不是 update?

    【讨论】:

    • 嗨乔希,我不明白你写的任何内容。我将编辑我的帖子以澄清我的问题。
    【解决方案2】:

    我认为你需要使用

    has_any_role?
    

    这需要两个或多个参数作为符号传递。但是您的 cf_content 方法正在返回一个数组。如果用户需要您在cf_create 中定义的 3 个角色,您需要做更多类似的事情

    def create
      cf_content.all? { |role| user.has_role?(role) }
    end
    

    更新:

    如果你只需要一个角色而不是简单的改变:

    def create
        cf_content.any? { |role| user.has_role?(role) }
    end
    

    另外,我不确定这些代表什么,但如果它们是您角色的名称,我建议使用小写。所以不是

    [ :Admin, :CF_Author, :CF_Editor ]
    

    你可能会使用:

    [:admin, :cf_author, :cf_editor]

    更新 2:

    has_role?不接受数组。所以如果你想检查has_role?在需要迭代 has_role 的数组上?在数组中的每个项目上。既然 :cf_content 方法返回和角色数组,那么从:

    def create
        user.has_role? :cf_content
    end
    

    收件人:

    def create
       :cf_content.any? { |role| user.has_role?(role) }
    end
    

    但你没有解释你试图把你的“内容政策”放在哪里。

    【讨论】:

    • 用户不需要三个角色,可以是数组中的任意一个角色。这些角色在标题大小写的应用程序的其他部分中起作用,因此除非有权威人士特定的理由将所有内容重命名为小写,否则我将保持原样。不确定显示方法,它工作正常,因为我有它。我的问题是如果用户具有数组中的任何角色,如何让一组角色作为 true 传递给权威人士。
    • 查看我的更新答案。至于角色名称,我建议使用 ruby​​ / rails 命名约定。通常只有类或模块名称使用大写,所以我被它们弄糊涂了,甚至堆栈溢出语法突出显示 :Admin 就好像它是一个类名一样。见github.com/bbatsov/ruby-style-guide#naming
    • 嗨 - 你的回答对我来说仍然没有意义(对不起,如果我没有抓住重点)。我的表演动作很好——这不是我要寻求帮助的。我想知道如何定义一个角色数组,以便如果当前用户具有该数组中的任何角色 - 那么权威人士的行动将被允许。你知道如何修复我的代码以实现这一目标吗?
    【解决方案3】:

    您可以像这样检查多个角色:

    user.admin?还是 user.author?

    如果你想从一个数组中检查角色,你也可以检查:cf_content.include?(user.role) OR cf_content.include?(user.role.title) 哪个适合场景。

    您还可以使用 -> user.applied_roles 检查实例绑定角色,并查看它返回的角色是否包含您预期的角色。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多