【问题标题】:Getting Pundit authorization working with Namespaces on Rails 5使用 Rails 5 上的命名空间获得 Pundit 授权
【发布时间】:2017-02-25 09:46:43
【问题描述】:

关于让 Rails 5 和 Pundit 授权使用命名空间的问题。

对于 Pundit,我想在控制器中使用 policy_scope([:admin, @car],它将使用位于以下位置的 Pundit 策略文件:app/policies/admin/car_policy.rb。我在尝试 Pundit 使用此命名空间时遇到问题 - 没有命名空间,它可以正常工作。

应用程序正在运行:

  • 导轨 5
  • 身份验证设计
  • 授权专家

例如,我的命名空间是 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。我猜是因为它是一个数组。

我认为在控制器中我可以执行policy_scope(Admin::Car) 之类的操作,但这不起作用:)。

非常感谢任何助手。


更新

我在 Pundit Github 问题页面上找到了这个:https://github.com/elabs/pundit/pull/391

这修复了我想要的 policy_scope 的命名空间处理。

它更新了 Pudit gem -> lib/pundit.rb 中的 policy_scope! 方法。

发件人:

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!module Punditclass &lt;&lt; self 中。

我认为这会起作用,但它不起作用 - 假设这是因为 policy_scope!class &lt;&lt; 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

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-5 pundit


    【解决方案1】:

    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])
    

    【讨论】:

      猜你喜欢
      • 2017-03-17
      • 1970-01-01
      • 1970-01-01
      • 2017-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多