将Pundit与命名空间一起使用

时间:2014-01-21 10:09:30

标签: ruby-on-rails pundit

在我的项目中,我有相当常见的命名空间“admin”。

namespace :admin do
    resources :users, except: :show
end

我使用Pundit gem来设置适当的授权,但我发现很难在命名空间中使用控制器。我的政策安排如下

-policies
    -admin
        user_policy.rb
    application_policy.rb
    admin_policy.rb
    awesome_policy.rb

与控制器非常相似。

然而,当我在控制器内部使用“authorize”方法时,我只得到一个错误,通知该应用程序“无法找到UserPolicy”。我的UserPolicy看起来像这样:

class Admin::UserPolicy < AdminPolicy
end

那么问题是什么,我应该怎样做才能使Pundit在命名空间中看到这些策略?

4 个答案:

答案 0 :(得分:4)

使用新合并的commit,您可以执行此操作。

它会自动生效。

<强>更新

从0.3版本有效删除而无需更换功能。但是,可以在github上的名称空间分支中获取名称空间功能。

您可以在issue on github中看到有关功能的讨论。

我建议那些想要使用命名空间命名空间的人 - 请不要使用。在过滤器之前进行访问限制区域,如管理仪表板,并在权威文件中保留授权模型规则。这样你就可以在没有黑客和问题的情况下使用专家。

答案 1 :(得分:2)

简短回答:你不能让Pundit使用控制器命名空间特定的策略。

答案很长:Pundit查看资源(模型)以确定要使用的Policy类,因此每当您将User模型的实例作为资源传递时,它都会查找{{1 }},而不是UserPolicy

请参阅hereherehere

可以Admin::UserPolicy模型上指定policy class,但这并不能真正解决您的命名空间控制器问题,因为Pundit将从中派生出策略类模型,无论你在哪里授权。

答案 2 :(得分:2)

虽然onemanstartup提到现在应该自动工作,但是我无法使命名空间策略起作用,但是我发现这是可以接受的。

在您的情况下,在AdminPolicy中,我添加了自定义操作名称,例如

def new_user?
  some code
end

然后在我的Admin :: UserController#new action

def new
  authorize @user, :new_user?
end

答案 3 :(得分:1)

只是因为同样的问题来到这里。使用pundit v2.1.0,可以通过在控制器中覆盖policy_scopeauthorize来实现。我为类似设置做了什么:

module Admin
  class ModuleController < ModuleController
    private

    def policy_scope(scope)
      super([:admin, scope])
    end

    def authorize(record, query = nil)
      super([:admin, record], query)
    end
  end
end

然后仅使用在控制器中使用策略的常规方法,这将从Admin命名空间获取策略。

自述文件的https://github.com/varvet/pundit#policy-namespacing

中也对此进行了描述。

如果您需要除当前用户和记录以外的更多上下文,Pundit policies with two input parameters将很有帮助。