Does Rails come with a "not authorized" exception?

Rick picture Rick · Sep 17, 2014 · Viewed 24.1k times · Source

I am writing an application that uses plain old Ruby objects (POROs) to abstract authorization logic out of controllers.

Currently, I have a custom exception class called NotAuthorized that I rescue_from at the controller level, but I was curious to know: Does Rails 4 already come with an exception to indicate that an action was not authorized? Am I reinventing the wheel by implementing this exception?

Clarification: The raise AuthorizationException is not happening anywhere inside of a controller, it is happening inside of a completely decoupled PORO outside of the controller. The object has no knowledge of HTTP, routes or controllers.

Answer

Stefan picture Stefan · Sep 17, 2014

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.