0

devise と cancan でネストされたリソースを正しく承認するにはどうすればよいですか? ドキュメントから提案された手順を実装しましたが、成功しませんでした。

この問題には、 deviseおよび cancan gem を使用してネストされたリソースの第 3 層からユーザー ID を取得しない機能モデルが含まれます。ただし、セカンダリレイヤーからユーザー ID を取得することはできます。どんな助けでも大歓迎です!

次のようなネストされたリソースがあります。

  resources :users do
    resources :clients do
      resources :positions
    end
  end

  resources :clients do
    resources :positions
  end

  resources :users do
    resources :positions
  end

  resources :users
  resources :clients
  resources :positions 

以下を使用するpositionモデルコントローラーを使用します。

class PositionsController < ApplicationController
  before_filter :grab_client_from_client_id
  load_and_authorize_resource :user
  load_and_authorize_resource :client, through: :user, shallow: true
  load_and_authorize_resource :position, through: :client, except: [:index], shallow: true
  ...
end

アビリティ.rb ファイル:

class Ability
  include CanCan::Ability

  def initialize(user)

    user ||= User.new # guest user (not logged in)

    if user.has_role? :admin
      can :manage, :all
    elsif user.has_role? :management
      can [:create, :read, :update], :all
    else
      can :read, :all, user_id: user.id
    end

  end
end

これにより、管理者以外/管理者以外のユーザーに次のエラーが表示されます。

undefined method 'user_id' for #<User:0x5227d40>

明らかに何かが正しく設定されていません。各 gem のドキュメントを何度も確認し、解決策を探してあらゆる場所を検索しました。

また、モデルの関係を以下に示します。


class User < ActiveRecord::Base
  has_many :clients
  has_many :positions, through: :clients
  resourcify
  ...
end


class Client < ActiveRecord::Base
  resourcify
  has_many :checklogs
  has_many :positions
  belongs_to :user
end


class Position < ActiveRecord::Base
  resourcify
  belongs_to :client
  delegate :user, to: :client, allow_nil: true
end
4

1 に答える 1

4

問題は次の行にあります。

can :read, :all, user_id: user.id

ユーザーが何かを読むことができるかどうかを確認するときは、何を読もうとしているかを確認します。

コントローラーに次の行があるため:

load_and_authorize_resource :user

承認しようとしているリソースはユーザーです。

あなたの能力は に匹敵user.user_idcurrent_user.idます。ユーザーには がないuser_idため、エラーの原因はそこにあります。

あなたのコードに基づいて、ユーザーがマネージャーまたは管理者でない限り、ユーザーが自分のものだけを読むことができるようにしたいと思います。

これは、次の方法で実現できます。

if user.has_role? :admin
  can :manage, :all
elsif user.has_role? :management
  can [:create, :read, :update], :all
else
  can :read, User, id: user.id
  can :read, Client, user_id: client.id
  can :read, Position, client: { user_id: user.id }
end

このようにして、ユーザーは関係のあるモデルにのみアクセスできます。

于 2013-04-23T14:45:08.723 に答える