Pundit::NotAuthorizedError — наследование политики приложений не работает

#ruby-on-rails #ruby #inheritance #controller #pundit

#ruby-on-rails #ruby #наследование #контроллер #эксперт

Вопрос:

Я устанавливаю pundit в свое приложение. Мой файл RestaurantPolicy наследуется от файла ApplicationPolicy (который по умолчанию не предоставляет доступ ни к одному из методов). При изменении методов в RestaurantPolicy (с false на true) это, похоже, не имеет никакого эффекта, поскольку у меня по-прежнему нет доступа ни к одному из методов. НО при замене ложных значений на истинные в файле ApplicationPolicy…У меня есть доступы! Есть идеи, почему методы в файле RestaurantPolicy не переопределяют методы ApplicationPolicy? Спасибо, ууу!!

application_controller.rb

 class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :authenticate_user!
  include Pundit

  # Pundit: white-list approach.
  after_action :verify_authorized, except: :index, unless: :skip_pundit?
  after_action :verify_policy_scoped, only: :index, unless: :skip_pundit?

  private

  def skip_pundit?
    devise_controller? || params[:controller] =~ /(^(rails_)?admin)|(^pages$)/
  end
end
  

restaurants_controller.rb

 class RestaurantsController < ApplicationController
  before_action :set_restaurant, only: [:show, :edit, :update, :destroy]

  def index
    @restaurants = Restaurant.all
    authorize @restaurants
  end

  def show
  end

  def new
    @restaurant = Restaurant.new
    authorize @restaurant
  end


  def edit
  end


  def create
    @restaurant = Restaurant.new(restaurant_params)
    @restaurant.user = current_user
# OU :     @restaurant = current_user.restaurants.build(restaurant_params)


    respond_to do |format|
      if @restaurant.save
        format.html { redirect_to @restaurant, notice: 'Restaurant was successfully created.' }
        format.json { render :show, status: :created, location: @restaurant }
      else
        format.html { render :new }
        format.json { render json: @restaurant.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @restaurant.update(restaurant_params)
        format.html { redirect_to @restaurant, notice: 'Restaurant was successfully updated.' }
        format.json { render :show, status: :ok, location: @restaurant }
      else
        format.html { render :edit }
        format.json { render json: @restaurant.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @restaurant.destroy
    respond_to do |format|
      format.html { redirect_to restaurants_url, notice: 'Restaurant was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

    def set_restaurant
      @restaurant = Restaurant.find(params[:id])
    end

    def restaurant_params
      params.require(:restaurant).permit(:name)
    end
end
  

restaurant.rb

 class Restaurant < ApplicationRecord
  belongs_to :user
end
  

user.rb

 class User < ApplicationRecord
  

разработайте :database_authenticatable, :registerable,
:восстанавливаемый, : запоминаемый, : проверяемый
has_many :рестораны
завершение

application_policy.rb

 class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  end

  def index?
    false
  end

  def show?
    scope.where(:id => record.id).exists?
  end

  def create?
    false
  end

  def new?
    create?
  end

  def update?
    false
  end

  def edit?
    update?
  end

  def destroy?
    false
  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
  

restaurant_policy.rb

 class RestaurantPolicy < ApplicationPolicy
  class Scope < Scope
    def index?
      true
    end

    def show?
      scope.where(:id => record.id).exists?
    end

    def create?
      true
    end

    def new?
      create?
    end

    def update?
      true
    end

    def edit?
      update?
    end

    def destroy?
      true
    end
  end
end
  

Ответ №1:

Вы должны определить методы своей политики вне RestaurantPolicy::Scope, вот так:

 class RestaurantPolicy < ApplicationPolicy
  class Scope < Scope
    def index?
      true
    end
  end

  # Notice we have closed the definition of Scope class.
  def show?
    scope.where(:id => record.id).exists?
  end

  def create?
    true
  end

  def new?
    create?
  end

  def update?
    true
  end

  def edit?
    update?
  end

  def destroy?
    true
  end
end