关于让Rails 5和Pundit授权使用命名空间的问题.
使用Pundit,在控制器中我想使用policy_scope([:admin,@ car],它将使用位于以下位置的Pundit策略文件:app / policies / admin / car_policy.rb.我在尝试使用Pundit时遇到问题命名空间 – 没有命名空间,它工作正常.
应用正在运行:
> Rails 5
>设计身份验证
> Pundit授权
例如,我的命名空间用于管理员.
>标准用户> http://garage.me/cars
>管理员用户> http://garage.me/admin/cars
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的授权方法:@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中,这个工作授权[: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
但我想使用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
在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.我认为这是因为它是一个数组.
我认为在控制器中我可以做类似policy_scope(Admin :: Car)的东西,但这不起作用:).
非常感谢任何助理.
更新
我在Pundit Github Issue页面上找到了这个:https://github.com/elabs/pundit/pull/391
这修复了policy_scope的名称空间处理,这是我想要的.
它更新了Pudit宝石 – > policy_scope! 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应用程序中使用它?它被称为重载或猴子修补?
我在想在config / initializer目录中添加一个pundit.rb并使用module_eval但不确定如何在policy_scope中执行此操作!在模块Pundit内部和类<
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])