分配冲突的 CanCan 角色

Assign Conflicting CanCan Roles

我正在使用 CanCan Gem 并想为用户分配两个冲突的角色。我需要一个用户有两个角色,一个是 x 角色,另一个是 y 角色。角色 x 允许用户创建帖子但不能创建文章。角色 y 允许用户创建文章但不能创建帖子。

我的 ability.rb 文件如下所示:

if user.role?(x)
  can :manage, Post
  cannot :manage, Article
end
if user.role?(y)
 cannot :manage, Post
 can :manage, Article
end

目前,如果我为用户分配两个角色,角色 Y 的权限将覆盖角色 x 的权限。我想允许管理员堆叠角色,这样如果我想将角色 x 和 y 添加到用户,该用户将能够管理帖子和文章。因此,如果角色有 can 而另一个角色有 can 权限,则 can 权限会覆盖。

不应该

if user.role?(x)
  can :manage, Post
end
if user.role?(y)
  can :manage, Article
end

够不够? cannot 只是删除之前授予的权限。但是,如果您不授予它们,则无需删除它们。

另见 https://github.com/CanCanCommunity/cancancan/wiki/Ability-Precedence

这是一个 运行 示例:

require 'cancan'

class Ability
  include CanCan::Ability
  attr_reader :user

  def initialize(user)
    @user = user

    if user.role?(:editor)
      can :edit, Post
    end

    if user.role?(:reader)
      can :read, Post
    end
  end
end

class Post
end

class User
  attr_reader :name
  def initialize(name, *roles)
    @name = name
    @roles = roles
  end

  def role?(role)
    @roles.include?(role)
  end
end

admin = User.new('admin', :reader, :editor)
user = User.new('user', :reader)
editor = User.new('editor', :editor)

admin_ability = Ability.new(admin)
user_ability = Ability.new(user)
editor_ability = Ability.new(editor)


def output(ability, permission)
  puts "#{ability.user.name} can #{permission} Post: #{ability.can?(permission, Post)}"
end

output(admin_ability, :edit)
output(user_ability, :edit)
output(editor_ability, :edit)
puts "--"
output(admin_ability, :read)
output(user_ability, :read)
output(editor_ability, :read)

默认是没有权限。因此,如果您只在 "additive" 模式下工作,如果用户具有角色则添加权限,则永远不需要删除其中一个。

:manage[:create, :edit, :update, :new, :destroy, :index, :show] 相同,只是为了方便。如果您只想添加这些权限中的 6 个,则可以添加所有 7 个,然后删除 1 个。但除此之外,我认为您的示例不需要 cannot

已接受的答案已有 5 年历史,而且此功能似乎如 OP 所预期的那样包含在 CanCanCan 中。

在 1.15 版中按预期工作,但在 3.3 版中确实有效,因此您可能需要升级您的 cancancan gem。