Pundit::AuthorizationNotPerformedError 使用 Devise 控制器

Pundit::AuthorizationNotPerformedError with Devise controller

我对使用此 Pundit gem 还很陌生,但似乎无法理解政策系统。我添加了检查是否已调用 Pundit 进行授权 (verify_authorized) 和范围界定 (verfify_policy_scoped)。但是,当我访问 Devise 会话控制器时,这会导致错误。

应用程序控制器

class ApplicationController < ActionController::Base
  include Pundit
  protect_from_forgery
  before_filter :authenticate_person!

  # Verify that controller actions are authorized. Optional, but good.
  after_filter :verify_authorized,  except: :index
  after_filter :verify_policy_scoped, only: :index


  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  private

  def pundit_user
    Person.find_by_id(current_person)
  end

  def user_not_authorized
    flash[:alert] = "You are not authorized to perform this action."
    # redirect_to(request.referrer || root_path)
  end
end

申请政策

class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    raise Pundit::NotAuthorizedError, "must be logged in" unless user
    @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

错误信息

Pundit::AuthorizationNotPerformedError in
  Devise::SessionsController#new

Pundit::PolicyScopingNotPerformedError in
  ...

您可能需要查看 Pundit 自述文件中的 this section

它基本上是说,当在 after_action 中使用 verify_authorized 时,它会检查是否实际调用了 authorized

Pundit adds a method called verify_authorized to your controllers. This method will raise an exception if authorize has not yet been called. You should run this method in an after_action to ensure that you haven't forgotten to authorize the action.

verify_policy_scoped也是如此,但是policy_scope

Likewise, Pundit also adds verify_policy_scoped to your controller. This will raise an exception in the vein of verify_authorized. However, it tracks if policy_scope is used instead of authorize. This is mostly useful for controller actions like index which find collections with a scope and don't authorize individual instances.

在你的情况下,异常是由于你没有在 Devise::SessionsController#new 操作中调用授权。

我认为,最好的处理方法是从 ApplicationController 中删除 after_action 检查并将它们移至子类。

答案是检查它是否是 devise 控制器。

after_action :verify_authorized, :except => :index, unless: :devise_controller?

发件人:https://github.com/elabs/pundit/issues/113 and https://gorails.com/forum/using-pundit-with-activeadmin