Cancan授权特定型号

时间:2013-10-02 05:56:15

标签: ruby-on-rails ruby cancan

这是我想要做的:

分配了User角色admin无法更新User角色god的角色。所以这就是我提出的代码:

  if user.has_role? 'admin'
    can :manage, :all
    cannot :update, User do |resource|
      resource.has_role?('god')
    end
  end

但是,resource似乎总是返回nil

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

预期行为

为了能够使用#can#cannot的块语法,您必须首先在控制器中加载资源。 As doc says

  

当实际的实例对象是时,评估该块   当下。检查类的权限时不会对其进行评估   (例如在索引动作中)。这意味着任何条件都没有   依赖于对象的属性应该移到外面   块。

要使此实例对象存在,您需要让cancan加载它:

class UsersController < ApplicationController
  load_and_authorize_resource
end

这会使您的控制器和传递给@user的块中的#cannot可用。现在有一个问题。

...在rails-4上打破(截至2013年10月2日)

CanCan有一个rails-4的问题:它不处理StrongParameters。这会导致自动资源加载在#create#update操作中崩溃。这是a running issue,Ryan承诺为cancan-2提供解决方案(似乎放弃了cancan-1)。

无论如何,您可以使用此PR中的代码使cancan与强参数兼容。这是在a monkey patch中提取的。我更喜欢使用猴子补丁而不是将gem指向特定的提交或分叉,这样我就不会丢失任何主宝石更新。

替代资源加载

再次阅读文档,我发现了另一种避免强参数问题的方法。你可以overload loader if you use a before_filter before #load_resource

有几个含义:

  • 您必须自己实施逻辑,以便在#new#show#create等之间产生差异(可能会使用多个条件过滤器)
  • 你必须自己指定params(因此,你可以正确使用强参数)

这会破坏cancan资源加载的简单性,并且其唯一目的是让cancan知道当您想要使用#can#cannot的块时资源是什么。

我还是宁愿选择猴子补丁,这样当问题在上游修复时,你的控制器中就不会有很多无用的代码了。