我正在使用Rails 4.0.0,ruby 2.0.0p247和CanCan 1.6.10。
基于联接表(has_many:through),如何使用CanCan根据用户的角色授权?
我有三个模型:User、Group和GroupUser。
用户和组通过GroupUser表关联为has_many。每个GroupUser还有一个role字段,可以是“editor”或“owner”。一个组可以有多个用户,每个用户具有不同的角色。此外,一个用户可以在多个组中担任角色。
我已经设置了CanCan能力,但它不仅限制对具有正确角色的用户的访问,而且授权所有人。
模型设置如下。还要注意Group有一个返回其所有者列表的方法。
基于联接表(has_many:through),如何使用CanCan根据用户的角色授权?
我有三个模型:User、Group和GroupUser。
用户和组通过GroupUser表关联为has_many。每个GroupUser还有一个role字段,可以是“editor”或“owner”。一个组可以有多个用户,每个用户具有不同的角色。此外,一个用户可以在多个组中担任角色。
我已经设置了CanCan能力,但它不仅限制对具有正确角色的用户的访问,而且授权所有人。
模型设置如下。还要注意Group有一个返回其所有者列表的方法。
class User < ActiveRecord::Base
has_many :group_users
has_many :groups, through: :group_users
end
class Group < ActiveRecord::Base
has_many :group_users
has_many :users, through: :group_users
def owners
User.find(self.group_users.where(role: 'owner').map(&:user_id))
end
end
class GroupUser < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
CanCan权限管理。请注意,它使用了Group上的owners
方法。class Ability
include CanCan::Ability
def initialize(user)
can :update, Group do |group|
group.owners.include?(user)
end
end
end
视图如下。在这里,不应该看到该链接的用户仍然可以看到它。
<ul class="groups">
<% @groups.each do |group| %>
<li>
<p><%= group.name %></p>
<% if can? :update, Group %>
<%= link_to "Edit", edit_group_path(group) %>
<% end %>
</li>
<% end %>
</ul>
最后,视图的控制器操作如下:
def index
@groups = current_user.groups
end
. . . 一个有趣的事情是,即使在实际使用中它不起作用,以下单元测试也将通过:
test 'user can only update groups they own' do
ability_one = Ability.new(users(:one)) # Owner
ability_two = Ability.new(users(:two)) # Not-owner
assert ability_one.can?(:update, groups(:one))
assert ability_two.cannot?(:update, groups(:two))
end