Rails 4 - 与Rolify合作 - 允许一组角色

时间:2016-02-21 03:33:52

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

我正在尝试使用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

当我保存并尝试时,我无法看到我应该看到的东西(作为具有角色作者的用户。

有人能看到怎么做吗?

3 个答案:

答案 0 :(得分:2)

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所说:

  

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

或者在您的情况下,create?代替update?

答案 1 :(得分:1)

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

  

user.admin?或user.author?

如果您想从阵列中检查角色,您还可以查看:cf_content.include?(user.role)或cf_content.include?(user.role.title),无论哪种情况适合于场景。

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

答案 2 :(得分:0)

我认为你需要使用

has_any_role?

将两个或多个args作为符号传递。但是你的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

但是你还没有解释你在试图制定你的内容政策的地方&#34;。