5

cancanを使用してコントローラーのアクションを承認しています。cancan によってアクセスが許可されるクラスの 1 つは、acts_as_ancestryで実装されたツリーです。load_and_authorize_resourceユーザーがルート レベルへのアクセスを許可されておらず、内部ノードからのアクセスが許可されている場合、使用に問題があります。

関連するクラス定義を次に示します。

class User < ActiveRecord::Base
  belongs_to :organization, :inverse_of => :users
end

class Post < ActiveRecord::Base
  belongs_to :organization, :inverse_of => :posts
end

class Organization < ActiveRecord::Base
  has_ancestry :cache_depth => true
  has_many :users, :inverse_of => :organization
  has_many :posts, :inverse_of => :organization
end

投稿を管理するためのルールは、「自分の下の組織の投稿を管理できる」です。私のカンカン能力の定義は次のとおりです。

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new 

    # subtree_ids is added by acts_as_ancestry
    can :manage, Post, {:organization_id => user.organization.subtree_ids}
  end
end

コントローラーには、これがあります(他のアクションは省略)

class PostsController < ApplicationController
  load_and_authorize_resource :post

  def index
  end

  def new
  end
end

許可されたユーザーがルート組織に属している場合、すべてが正常に機能します。ただし、内部ノードで承認されたユーザーとしてログインすると、インデックス アクションは正常に動作しますが、新しいアクションが呼び出されると、can-can 承認エラーが発生します。

ログに表示される内容は次のとおりです。

Access denied on new #<Post id: nil, organization_id: 1>

organization_id 1ルート)はスキーマから来ています:

create_table "posts", :force => true do |t|
  t.integer  "organization_id", :default => 1
end

cancan を使用すると、新しいアクションによって新しい が作成され、Postに割り当てられ@postます。これを行うとcan、Abilities.rb の定義から取得した値ですべての属性が初期化されます。ただし、これらの属性が配列、ハッシュ、または範囲であり、デフォルト値がスキーマから取得される場合は何もしません。

サブツリー内の投稿を管理する権限をユーザーに与えるにはどうすればよいですか?ただし、ユーザーが新しい投稿を作成するときは、デフォルトで組織に設定されますか?

4

2 に答える 2

3

cancan では、@post 変数が既に初期化されている場合、load_resource は呼び出されず、承認部分のみが実行されます。ドキュメントのこの部分を参照してください: https://github.com/ryanb/cancan/wiki/Authorizing-controller-actions、「読み込みのオーバーライド」。

したがって、最も簡単な解決策は、初期化を自分で制御し、次のように必要なものにすることです。

class PostsController < ApplicationController
  before_filter :initialize_post, :only => [:new, :create]

  def initialize_post
    @post = current_user.organization.posts.build(params[:post]||{:name=>'Smashing Kittens'})
  end

  load_and_authorize_resource :post
  def index
  end

  def new
  end

  def create
  end
end

あなたの投稿から作成したこのテスト プロジェクトで動作することがわかります: https://github.com/robmathews/cancan_test

于 2013-03-29T14:47:51.270 に答える
1

同様の問題があり、祖先に関連するアクセス許可を次のようにブロックに書き込むことになりました。

can :manage, Post do |post|
  post.organization.subtree_ids.include?(user.organization_id)
end
于 2013-03-29T11:12:23.440 に答える