5

我正在使用cancan来授权我的控制器操作。cancan 授权访问的类之一是树,用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. 当它这样做时,它将使用从canAbilities.rb 中的定义中获取的值初始化所有属性。但是,如果这些属性是 Arrays、Hashes 或 Ranges 并且默认值最终来自模式,则它不会做任何事情。

如何授权用户管理其子树中的帖子,但是当他们创建新帖子时,将其默认为他们的组织?

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 回答