簡體   English   中英

讓Pundit授權在Rails 5上使用命名空間

[英]Getting Pundit authorization working with Namespaces on Rails 5

關於讓Rails 5和Pundit授權使用命名空間的問題。

使用Pundit,在控制器中我想使用policy_scope([:admin, @car] ,它將使用位於以下位置的Pundit策略文件: app/policies/admin/car_policy.rb 。我在嘗試使用Pundit時遇到問題命名空間 - 沒有命名空間,它工作正常。

應用正在運行:

  • Rails 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 @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

但我想使用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問題頁面上找到了這個: https//github.com/elabs/pundit/pull/391

這修復了policy_scope的名稱空間處理,這是我想要的。

它更新了Pudit gem - > 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!執行此操作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])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM