关于使用命名空间获得 Rails 5 和 Pundit 授权的问题。
对于 Pundit,我想在 Controller 中使用 policy_scope([:admin, @car]
,它将使用位于以下位置的 Pundit 策略文件: app/policies/admin/car_policy.rb
。我在尝试 Pundit 使用此命名空间时遇到问题 - 没有命名空间,它工作正常。
应用程序正在运行:
例如,我的命名空间用于
admins
。route.rb
文件如下所示:# config/routes.rb
devise_for :admins
root: 'cars#index'
resources :cars
namespace :admin do
root 'cars#index'
resources :cars
end
我已经设置了 Pundit
ApplicationPolicy
并让命名空间与 Pundit 的 authorize
方法一起使用:@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
在
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
但我想使用策略范围
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
在
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
我收到一个错误,因为 Pundit 没有在寻找
Admin::CarPolicy
。我认为这是因为它是一个数组。我想在 Controller 中我可以做类似
policy_scope(Admin::Car)
的事情,但这不起作用:)。任何助手都非常感谢。
更新
我在 Pundit Github 问题页面上找到了这个:https://github.com/elabs/pundit/pull/391
这修复了 policy_scope 的命名空间处理,这正是我想要的。
它更新
policy_scope!
中的 Pudit gem -> lib/pundit.rb
方法。从:
def policy_scope!(user, scope)
PolicyFinder.new(scope).scope!.new(user, scope).resolve
end
至:
def policy_scope!(user, scope)
model = scope.is_a?(Array) ? scope.last : scope
PolicyFinder.new(scope).scope!.new(user, model).resolve
end
我的问题是,如何在我的 Rails 应用程序中使用它?是叫重载还是猴子补丁?
我想在
pundit.rb
目录中添加一个 config/initializer
并使用 module_eval
但不确定如何执行此操作,因为 policy_scope!
位于 module Pundit
和 class << self
内。我认为这会起作用,但它没有 - 假设这是因为
policy_scope!
位于 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 在 Pundit Github 问题页面上发布了解决方案。
只需将您的 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
然后您可以使用:
policy_scope([:admin, @cars])
关于ruby-on-rails - 在 Rails 5 上使用命名空间获得 Pundit 授权,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42454424/