3

I'm using Rails 5.2, Pundit 1.1, and rails_admin 1.2

I have the following in my application_controller.rb:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  include Pundit

  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  private

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

I have the following in my application.policy.rb:

class ApplicationPolicy
.
.
.
  def rails_admin?(action)
    case action
      when :dashboard
        user.admin?
      when :index
        user.admin?
      when :show
        user.admin?
      when :new
        user.admin?
      when :edit
        user.admin?
      when :destroy
        user.admin?
      when :export
        user.admin?
      when :history
        user.admin?
      when :show_in_app
        user.admin?
      else
        raise ::Pundit::NotDefinedError, "unable to find policy #{action} for #{record}."
    end
  end
end

In my config/initializers/rails_admin.rb I have the following:

    RailsAdmin.config do |config|
      ### Popular gems integration

      ## == Devise ==
      config.authenticate_with do
        warden.authenticate! scope: :user
      end
      config.current_user_method(&:current_user)

      ## == Pundit ==
      config.authorize_with :pundit

    end

module RailsAdmin
  module Extensions
    module Pundit
      class AuthorizationAdapter
        def authorize(action, abstract_model = nil, model_object = nil)
          record = model_object || abstract_model && abstract_model.model
          if action && !policy(record).send(*action_for_pundit(action))
            raise ::Pundit::NotAuthorizedError.new("not allowed to #{action} this #{record}")
          end
          @controller.instance_variable_set(:@_pundit_policy_authorized, true)
        end

        def authorized?(action, abstract_model = nil, model_object = nil)
          record = model_object || abstract_model && abstract_model.model
          policy(record).send(*action_for_pundit(action)) if action
        end

        def action_for_pundit(action)
          [:rails_admin?, action]
        end
      end
    end
  end
end

If a user is an admin then they can access the admin dashboard. However, if a user isn't an admin then they should be redirected to the home page with a flash message.

When I try to access the Rails Admin dashboard for a non-admin user I get the following: enter image description here Why is ApplicationController not rescuing the Pundit::NotAuthorizedError?

I have created a sample app that reproduces this error: https://github.com/helphop/sampleapp

chell
  • 7,646
  • 16
  • 74
  • 140
  • does putting this config method in your `RailsAdmin.config` block help? Make sure you restart your server after adding it. `config.parent_controller = '::ApplicationController'` - my guess is that RailsAdmin isn't inheriting from your `ApplicationController`. – Josh Brody Jan 20 '18 at 00:22
  • I just tried adding config.parent_controller = '::ApplicationController' and I get the same error – chell Jan 20 '18 at 00:24

2 Answers2

2

Edit: Update —

The error you are actually having involves path helpers — such as root_url or root_path — inside RailsAdmin. When rescue_from encounters an error, it escapes itself.

With that being said, changing the redirect_to "/" should solve the problem.

Josh Brody
  • 5,153
  • 1
  • 14
  • 25
0

You should add config.parent_controller = 'ApplicationController' before config.authorize_with :pundit. It will say Rails Admin that RailsAdmin::ApplicationController inherited from your ApplicationController and rescue will work. Hope this help.

  • Thanks Ivan for your suggestion. I actually had added config.parent_controller = ::ApplicationController before the config.authorize_with :pundit. I have changed it to match your suggestion and it still works. Not sure if there is a difference. – chell Dec 14 '18 at 08:07