2013-03-29 5 views
5

Używam cancan do autoryzacji działań kontrolera. Jedną z klas, w których dostęp jest autoryzowany przez cancan, jest drzewo, realizowane za pomocą acts_as_ancestry. Mam problemy z korzystaniem z load_and_authorize_resource, gdy użytkownik nie ma dostępu do poziomu głównego, ale ma prawo dostępu rozpoczynającego się w węźle wewnętrznym.Jak mogę domyślnie powiązać przodka z kankanem z wewnętrznym węzłem drzewa?

Oto kilka obowiązujących, odnośnych definicje klas:

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 

Zasady zarządzania posty są „można zarządzać posty w każdej organizacji poniżej Yours”. Moja cancan zdolności definicja jest taka:

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 

w sterowniku, mam to (inne działania pominięte)

class PostsController < ApplicationController 
    load_and_authorize_resource :post 

    def index 
    end 

    def new 
    end 
end 

Wszystko działa poprawnie, gdy uprawniony użytkownik należący do organizacji korzeniowego. Jednak po zalogowaniu się jako użytkownik autoryzowany w węźle wewnętrznym akcja indeksu działa poprawnie, ale po wywołaniu nowej akcji otrzymuję błąd autoryzacji Can-can.

Oto, co widzę w dzienniku:

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

organization_id 1 (korzeń) jest pochodzące ze schematu:

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

Z kankana, nowa akcja zbuduje nowy Post i przypisz go do @post. Gdy to zrobi, zainicjuje wszystkie atrybuty wartościami podanymi w definicji can w Abilities.rb. Jednak nie zrobi nic, jeśli te atrybuty są tablicami, hashe lub zakresami, a domyślna wartość pochodzi ze schematu.

W jaki sposób mogę upoważnić użytkowników do zarządzania wpisami w ich poddrzewach, ale kiedy tworzą nowy wpis, domyślnie go do swojej organizacji?

+0

Zrobiłem następujący projekt, aby przetestować twój problem i to tutaj: https://github.com/robmathews/cancan_test.git – Rob

Odpowiedz

3

W kankana, jeśli zmienna @post jest już zainicjowany przez ciebie, to nie będzie na niej zadzwonić load_resource , wykonaj tylko część autoryzacji. Zobacz tę część dokumentu: https://github.com/ryanb/cancan/wiki/Authorizing-controller-actions, "Zastąp ładowanie".

więc najprostszym rozwiązaniem jest przejęcie kontroli nad inicjalizacji siebie i zrobić to, co trzeba, tak jak tutaj:

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 

Widać to działa w ramach tego projektu badawczego, który został utworzony z Twojego postu: https://github.com/robmathews/cancan_test .

1

miałem podobny problem i skończyło się na piśmie uprawnienia związane z przodków w blokach tak:

can :manage, Post do |post| 
    post.organization.subtree_ids.include?(user.organization_id) 
end 
Powiązane problemy