Does Rails come with a not authorized exception?
Rails doesn't seem to map an exception to :unauthorized
.
The default mappings are defined in activerecord/lib/active_record/railtie.rb:
config.action_dispatch.rescue_responses.merge!(
'ActiveRecord::RecordNotFound' => :not_found,
'ActiveRecord::StaleObjectError' => :conflict,
'ActiveRecord::RecordInvalid' => :unprocessable_entity,
'ActiveRecord::RecordNotSaved' => :unprocessable_entity
)
and actionpack/lib/action_dispatch/middleware/exception_wrapper.rb:
@@rescue_responses.merge!(
'ActionController::RoutingError' => :not_found,
'AbstractController::ActionNotFound' => :not_found,
'ActionController::MethodNotAllowed' => :method_not_allowed,
'ActionController::UnknownHttpMethod' => :method_not_allowed,
'ActionController::NotImplemented' => :not_implemented,
'ActionController::UnknownFormat' => :not_acceptable,
'ActionController::InvalidAuthenticityToken' => :unprocessable_entity,
'ActionDispatch::ParamsParser::ParseError' => :bad_request,
'ActionController::BadRequest' => :bad_request,
'ActionController::ParameterMissing' => :bad_request
)
You could add a custom exception from within your application's configuration (or a custom Railtie):
Your::Application.configure do
config.action_dispatch.rescue_responses.merge!(
'AuthorizationException' => :unauthorized
)
# ...
end
Or simply use rescue_from
.
ApplicationController not rescuing Pundit Not Authorized Error
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.
Pundit: how to handle multiple error codes for one unauthorized action?
Unfortunately Pundit
cannot handle different error types out of the box. And it is built to always expect the policy's methods to return true
or false false
. Therefore raising another custom error and rescuing from that in the controller will not work, because it would break view methods too.
I suggest a workaround to introduce different error types. Something like this might work:
# in the policy
class ItemPolicy < ApplicationPolicy
def show?
return true if record.public?
return false unless record.band.members.include?(user)
if user.premium?
true
else
Current.specific_response_error_code = :payment_required
false
end
end
end
# in the controller
class Api::V1::BaseController < ActionController::API
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
def user_not_authorized(_exception)
case Current.specific_response_error_code
when :payment_required
render json: { error: { message: "Premium required" } }, status: :payment_required
else
render json: { error: { message: "Access denied" } }, status: :forbidden
end
end
end
I would not consider using the global CurrentAttributes
a good practice but they are part of Rails and in this case, using this global data store avoids overriding pundit internals.
You might want to read the API docs about CurrentAttributes
.
How do I create a spec which verifies Pundit rejects users that are not logged in?
RSpec cannot catch the error in the background unless you use the raise_error
matcher with the block form of expect
:
RSpec.describe PostPolicy do
it "should raise an exception when users aren't logged in" do
expect do
AccountFolderPolicy.new(nil, record)
end.to raise_error(Pundit::NotAuthorizedError)
end
end
Alternatively
RSpec.describe PostPolicy do
it "should raise an exception when users aren't logged in" do
expect { AccountFolderPolicy.new(nil, record) }.to raise_error(Pundit::NotAuthorizedError)
end
end
Related Topics
How to Sort a Ruby Hash Alphabetically by Keys
Provide Value for Self When Using Proc#Call
Rspec Any_Instance Deprecation: How to Fix It
Running Phantomjs from a Ruby on Rails Application
Safe Navigation Equivalent to Rails Try for Hashes
What Rails Plugins Are Good, Stable and *Really* Enhance Your Code
How to Write a JSON Schema for Array of Objects
What Is the Point of Object#Presence in Rails
Problem When Installing Ruby 2.2.9 on MAC Big Sur M1
Why Is "❨╯°□°❩╯︵┻━┻" with Such an Encoding Used for a Method Name
Rails: Update Model Attribute Without Invoking Callbacks
How to Elegantly Symbolize_Keys for a 'Nested' Hash
Add_Foreign_Key VS Add_Reference in Rails
Checking If a String Is Valid JSON Before Trying to Parse It
Trying to Understand Use of Self.Method_Name VS. Classname.Method_Name in Ruby