[英]Getting Pundit authorization working with Namespaces on Rails 5
Question about getting Rails 5 and Pundit authorization working with Namespaces. 关于让Rails 5和Pundit授权使用命名空间的问题。
With Pundit, in the controller I wanted to use policy_scope([:admin, @car]
which will use the Pundit policy file located in: app/policies/admin/car_policy.rb
. I'm having issues trying to Pundit working with this namespace - without a namespace, it works fine. 使用Pundit,在控制器中我想使用policy_scope([:admin, @car]
,它将使用位于以下位置的Pundit策略文件: app/policies/admin/car_policy.rb
。我在尝试使用Pundit时遇到问题命名空间 - 没有命名空间,它工作正常。
Application is running: 应用正在运行:
My namespace is for admins
for example. 例如,我的命名空间用于admins
。
The route.rb
file looks like: route.rb
文件如下所示:
# config/routes.rb
devise_for :admins
root: 'cars#index'
resources :cars
namespace :admin do
root 'cars#index'
resources :cars
end
I've setup a Pundit ApplicationPolicy
and to get Namespaces working with Pundit's authorize
method: @record = record.is_a?(Array) ? record.last : record
我已经设置了Pundit ApplicationPolicy
并让命名空间使用Pundit的authorize
方法: @record = record.is_a?(Array) ? record.last : record
@record = record.is_a?(Array) ? record.last : record
# app/policies/application_policy.rb
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record.is_a?(Array) ? record.last : record
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope
end
end
end
In the Admin::CarsController
this works authorize [:admin, @cars]
在Admin::CarsController
这个工作authorize [:admin, @cars]
class Admin::CarsController < Admin::BaseController
def index
@cars = Car.order(created_at: :desc)
authorize [:admin, @cars]
end
def show
@car = Car.find(params[:id])
authorize [:admin, @car]
end
end
But I would like to use Policy Scope 但我想使用Policy Scope
class Admin::CarPolicy < ApplicationPolicy
class Scope < Scope
def resolve
if user?
scope.all
else
scope.where(published: true)
end
end
end
def update?
user.admin? or not post.published?
end
end
In the Admin::CarsController
在Admin::CarsController
class Admin::CarssController < Admin::BaseController
def index
# @cars = Car.order(created_at: :desc) without a policy scope
@cars = policy_scope([:admin, @cars]) # With policy scope / doesn't work because of array.
authorize [:admin, @cars]
end
def show
# @car = Car.find(params[:id]) without a policy scope
@car = policy_scope([:admin, @car]) # With policy scope / doesn't work because of array.
authorize [:admin, @car]
end
end
I'm getting an error because Pundit isn't looking for the Admin::CarPolicy
. 我收到一个错误,因为Pundit没有找到Admin::CarPolicy
。 I presume it's because it's an array. 我认为这是因为它是一个数组。
I thought in the controller I could do something like policy_scope(Admin::Car)
but that doesn't work :). 我认为在控制器中我可以做类似policy_scope(Admin::Car)
但这不起作用:)。
Any assistant is much appreciated. 非常感谢任何助理。
I found this on the Pundit Github Issues Page: https://github.com/elabs/pundit/pull/391 我在Pundit Github问题页面上找到了这个: https : //github.com/elabs/pundit/pull/391
This fixes the namespace handling for policy_scope which is what I wanted. 这修复了policy_scope的名称空间处理,这是我想要的。
It updates the Pudit gem -> policy_scope!
它更新了Pudit gem - > policy_scope!
method in lib/pundit.rb
. lib/pundit.rb
方法。
From: 从:
def policy_scope!(user, scope)
PolicyFinder.new(scope).scope!.new(user, scope).resolve
end
To: 至:
def policy_scope!(user, scope)
model = scope.is_a?(Array) ? scope.last : scope
PolicyFinder.new(scope).scope!.new(user, model).resolve
end
My question is, how do I use this in my Rails application? 我的问题是,如何在我的Rails应用程序中使用它? Is it called overloading or monkey patching? 它被称为重载或猴子修补?
I was thinking adding a pundit.rb
in the config/initializer
directory and using module_eval
but unsure how to do this as the policy_scope!
我在想在config/initializer
目录中添加一个pundit.rb
并使用module_eval
但不确定如何在policy_scope!
执行此操作policy_scope!
is inside module Pundit
and class << self
. 在module Pundit
内部和class << self
。
I thought this would work but it doesn't - presume it is because policy_scope!
我认为这会起作用,但它没有 - 假设这是因为policy_scope!
is inside class << self
. 是class << self
。
Pundit::module_eval do
def policy_scope!(user, scope)
model = scope.is_a?(Array) ? scope.last : scope
PolicyFinder.new(scope).scope!.new(user, model).resolve
end
end
Medir posted the solution on the Pundit Github Issues Page. Medir在Pundit Github问题页面上发布了该解决方案。
Just change your application_policy.rb to : 只需将application_policy.rb更改为:
class ApplicationPolicy
index? show?....
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
# @scope = scope
@scope = scope.is_a?(Array) ? scope.last : scope #This fixes the problem
end
def resolve
scope
end
end
end
You can then use : 然后你可以使用:
policy_scope([:admin, @cars])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.