2013-03-29 19 views
5

Tôi đang sử dụng cancan để cho phép các thao tác điều khiển của mình. Một trong những lớp mà quyền truy cập được ủy quyền bởi cancan là một cây, được triển khai với acts_as_ancestry. Tôi đang gặp sự cố khi sử dụng load_and_authorize_resource khi người dùng không được phép truy cập cấp cơ sở, nhưng thay vào đó là quyền truy cập được phép bắt đầu từ nút nội bộ.Làm cách nào để tôi có thể mặc định mối quan hệ tổ tiên với cancan đến nút nội bộ của cây?

Dưới đây là một số định nghĩa lớp relavant:

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 

Các quy tắc để quản lý bài viết là "Bạn có thể quản lý bài viết nào trong bất kỳ tổ chức dưới đây của bạn". Cancan khả năng định nghĩa của tôi là thế này:

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 

Trong bộ điều khiển, tôi có điều này (các hành động khác bỏ qua)

class PostsController < ApplicationController 
    load_and_authorize_resource :post 

    def index 
    end 

    def new 
    end 
end 

Tất cả mọi thứ hoạt động tốt khi người dùng có thẩm quyền thuộc về tổ chức gốc. Tuy nhiên, khi tôi đăng nhập với tư cách người dùng được ủy quyền tại nút nội bộ, hành động chỉ mục hoạt động tốt, nhưng khi hành động mới được gọi, tôi nhận được lỗi ủy quyền có thể.

Dưới đây là những gì tôi nhìn thấy trong nhật ký:

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

Các organization_id 1 (gốc) đến từ các lược đồ:

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

Với Cancan, hành động mới sẽ xây dựng một mới Post và gán nó cho @post. Khi thực hiện điều này, nó sẽ khởi tạo tất cả các thuộc tính với các giá trị được lấy từ định nghĩa can trong Abilities.rb. Tuy nhiên, nó sẽ không làm bất cứ điều gì nếu các thuộc tính đó là Mảng, Hashes hoặc Ranges và giá trị mặc định kết thúc đến từ lược đồ.

Làm cách nào để cho phép người dùng quản lý bài đăng trong cây con của họ, nhưng khi họ tạo bài đăng mới, hãy mặc định bài đăng đó cho tổ chức của họ?

+0

Vì vậy, tôi đã thực hiện dự án sau để kiểm tra vấn đề của bạn và nó ở đây: https://github.com/robmathews/cancan_test.git – Rob

Trả lời

3

Trong Cancan, nếu biến @post đã được khởi tạo bởi bạn, nó sẽ không gọi load_resource vào nó , chỉ làm phần ủy quyền. Xem phần tài liệu này: https://github.com/ryanb/cancan/wiki/Authorizing-controller-actions, "Ghi đè tải".

Vì vậy, giải pháp đơn giản nhất là để kiểm soát việc khởi tạo bản thân và làm cho nó những gì bạn cần, như ở đây:

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 

Bạn có thể nhìn thấy nó làm việc trong dự án thử nghiệm này mà tôi tạo ra từ bài viết của bạn: https://github.com/robmathews/cancan_test .

1

Tôi đã có một vấn đề tương tự và kết thúc bằng văn bản cho phép tổ tiên liên quan trong các khối như sau:

can :manage, Post do |post| 
    post.organization.subtree_ids.include?(user.organization_id) 
end 
Các vấn đề liên quan