【发布时间】:2013-11-20 13:48:21
【问题描述】:
我正在使用 Rails 4.0.0、ruby 2.0.0p247 和 CanCan 1.6.10。
如何根据用户在联接表中的角色(has_many :through)向用户授权 CanCan?
我有 3 个模型:User、Group 和 GroupUser。
用户和组通过 GroupUser 表关联为has_many。每个 GroupUser 还有一个role 字段,可以是“编辑”或“所有者”。一个组可以有多个用户,每个用户具有不同的角色。此外,一个用户可以在多个组中拥有角色。
我设置了具有 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
【问题讨论】:
标签: ruby-on-rails permissions ruby-on-rails-4 authorization cancan