我使用 Devise 进行身份验证,使用 CanCan 进行授权。
目标
我有两个模型:User 和 Sponsorship,其中 Sponsorship 提供了 has_many :through user-as-sponsor 和 user-as-client 之间的关系。
我想配置 CanCan 以便具有sponsor?
特权的用户可以管理他或她自己的赞助,也就是说,只有Sponsorship#client_id == user.id
. 用户还可以拥有admin?
特权,在这种情况下,他或她可以管理任何赞助。
模型
class User < ActiveRecord::Base
has_many :sponsor_links, :class_name => 'Sponsorship', :foreign_key => 'client_id'
has_many :sponsors, :through => :sponsor_links, :class_name => 'User'
has_many :client_links, :class_name => 'Sponsorship', :foreign_key => 'sponsor_id'
has_many :clients, :through => :client_links, :class_name => 'User'
def has_role?(role)
... return true if this user has <role> privileges
end
end
class Sponsorship
belongs_to :sponsor, :class_name => 'User'
belongs_to :client, :class_name => 'User'
end
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # handle guest user (not logged in)
if user.has_role?(:admin)
can :manage, :all
elsif user.has_role?(:sponsor)
# not sure if the third argument is correct...
can :manage, Sponsorship, :sponsor => {:user_id => user.id}
end
end
end
路线
我设置了嵌套路由来反映赞助用户拥有他或她的客户的事实:
resource :users, :only => [:index]
resource :sponsorships
end
问题
在我的 SponsorshipsController 中加载和授权用户和赞助资源的正确方法是什么?
我试过的
这类似于 CanCan 轻松处理的普通嵌套资源。但是这些关系具有非标准名称(例如:sponsor_links 而不是:sponsorships),而且我还没有弄清楚如何load_and_authorize_resource
在我的 SponsorshipsController 中配置声明。
在我尝试过的许多不起作用的事情中;),这是更简单的版本之一。(另请注意,我的能力可能没有正确设置——见上文):
class SponsorshipsController < ApplicationController
load_and_authorize_resource :sponsor_links, :class_name => "User"
load_and_authorize_resource :sponsorships, :through => :sponsor_links
respond_to :json
# GET /users/:user_id/sponsorships.json
def index
respond_to @sponsorships
end
# GET /users/:user_id/sponsorships/:id.json
def show
respond_to @sponsorship
end
end
通过抢救 CanCan::AccessDenied 错误,我知道:
- 在
index
使用:sponsor
用户时,用户的身份验证失败。 - 在
index
使用:admin
用户时,赞助的身份验证失败。 - 在
show
中,无论角色如何,发起人的身份验证都会失败。