cancan没有评估实例级别的能力检查

时间:2013-03-29 13:56:14

标签: ruby-on-rails ruby-on-rails-3 cancan

我正在尝试将cancan合并到我的第一个Ruby on Rails应用程序中。

我在开始时遇到了问题......这肯定是基本的。

我的应用程序有一个项目列表,用户可能有也可能没有权限查看任何项目。

我将此添加到我的ProjectsController:

class ProjectsController < ApplicationController
  load_and_authorize_resource

我的初始化方法如下所示:

  def initialize(user)
    user ||= User.new # guest user
    puts "********  Evaluating cancan permissions for: " + user.inspect
    can :read, Project do |project|
      puts "********  Evaluating project permissions for: " + project.inspect
      # project.try(project_users).any?{|project_user| project_user.user == user} 
      1 == 1  #POC test!
    end
  end

当我这样时,会出现项目索引页面,但不会列出任何项目。

我在这里有两个问题:

  1. 不应该显示所有项目,因为所有项目都返回true 项目?
  2. 第二个puts语句未写入rails 服务器控制台,但第一个是。为什么??? ???
  3. 如果我将initialize方法更改为:

      def initialize(user)
        user ||= User.new # guest user
        puts "********  Evaluating cancan permissions for: " + user.inspect
        can :read, Project
      end
    

    ......我看到了所有项目,我期待

    如果我删除了can:read,项目行,我得到一个安全异常试图点击项目索引页面....也是我期望的。

1 个答案:

答案 0 :(得分:0)

只有在项目实例可用时才会评估传递给:read能力的块(@project)。因为您正在讨论索引操作,所以只有集合可用(@projects)。这就解释了为什么你的第二个看跌声明永远不会出现。为了限制索引操作,您需要将条件的哈希值传递给can方法,或者使用范围(除了块)。所有这些信息都在Github上的CanCan wiki中清楚地列出。

因此puts问题可以解释。没有意义的是没有项目如何展示。在评估索引操作时,CanCan实际上会默认完全忽略该块。这意味着您的能力无论如何都是can :read, Project(即使在第一个示例中),也可用于索引操作。

我有兴趣让你尝试添加一个简单的范围,只是为了看看它是否有效。尝试:

can :read, Project, Project.scoped do |project|
  true
end

然后看看索引操作会发生什么。

编辑:

鉴于您现在可以在索引中看到项目,您似乎需要将范围传递给能力和块。请阅读this Github issue,其中Ryan解释了为什么不对索引操作评估块。

  

块仅用于基于a定义能力   对象的属性。 [...]这是块应该的唯一情况   因为块仅在对象出现时执行   可用。所有其他条件应在块外定义。

请记住,如果您的能力对于条件哈希来说不是太复杂,那么您应该使用它。条件的哈希在this CanCan wiki page on Github.上解释如果确实需要范围,则需要传入范围和块。让我们说你有上面显示的能力。

  1. 在索引操作上,CanCan将忽略该块,因为Project对象(@project)不可用。它将返回在给定范围内的项目,在本例中为Project.scoped(这将只是所有项目)。
  2. 在show动作中,@project可用,因此如果块的计算结果为true,CanCan将评估该块并允许该动作。
  3. 因此,您需要传递两者的原因是CanCan可以处理索引和显示操作。在大多数情况下,您的块将定义与作用域相同的内容,只有块将用Ruby编写,而您的作用域将编写Rails的ActiveRecord语法。您可以在此处了解更多相关信息:Defining Abilities with Blocks