認証にはDevise、承認にはCanCanを使用しています。
目標
ユーザーとスポンサーシップの 2 つのモデルがあります。スポンサーシップは、ユーザーとしてのスポンサーとユーザーとしてのクライアントの間の has_many :through 関係を提供します。
sponsor?
特権を持つユーザーが自分のスポンサーシップを管理できるように、CanCan を構成したいと考えています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 が簡単に処理できる通常のネストされたリソースに似ています。しかし、関係には非標準の名前 (たとえば、:sponsorships ではなく :sponsor_links) がありload_and_authorize_resource
、SponsorshipsController で宣言を構成する方法がわかりません。
私が試した中でうまくいかなかった多くのことの中で;)、これはより単純なバージョンの1つです。(私の能力が適切に設定されていない可能性があることにも注意してください -- 上記を参照してください):
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
、ロールに関係なく、スポンサーシップの認証は失敗します。