在我的项目中,我有相当常见的命名空间“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在命名空间中看到这些策略?
答案 0 :(得分:4)
使用新合并的commit,您可以执行此操作。
它会自动生效。
<强>更新强>
从0.3版本有效删除而无需更换功能。但是,可以在github上的名称空间分支中获取名称空间功能。
您可以在issue on github中看到有关功能的讨论。
我建议那些想要使用命名空间命名空间的人 - 请不要使用。在过滤器之前进行访问限制区域,如管理仪表板,并在权威文件中保留授权模型规则。这样你就可以在没有黑客和问题的情况下使用专家。
答案 1 :(得分:2)
简短回答:你不能让Pundit使用控制器命名空间特定的策略。
答案很长:Pundit查看资源(模型)以确定要使用的Policy类,因此每当您将User
模型的实例作为资源传递时,它都会查找{{1 }},而不是UserPolicy
您可以在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_scope
和authorize
来实现。我为类似设置做了什么:
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将很有帮助。