cancan icon indicating copy to clipboard operation
cancan copied to clipboard

enable_authorization :unless/:if broken in Ruby 2.1 and CanCan 2.0

Open bjackson opened this issue 10 years ago • 3 comments

When adding options to enable_authorization, the following error is displayed:

Started DELETE "/users/sign_out" for 192.168.1.5 at 2014-01-16 22:59:04 -0600
Processing by Devise::SessionsController#destroy as HTML
  Parameters: {"authenticity_token"=>"eG2YUYItoG7xz3Y/tMteKMQCNidGJHtktEAxsBWX2yA="}
Completed 500 Internal Server Error in 2ms

LocalJumpError - break from proc-closure:
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/cancan-e6bf4c8d12dc/lib/cancan/controller_additions.rb:260:in `block in enable_authorization'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:440:in `block in make_lambda'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:160:in `block in halting'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:229:in `block in halting'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:229:in `block in halting'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:166:in `block in halting'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:166:in `block in halting'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:166:in `block in halting'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:166:in `block in halting'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:86:in `run_callbacks'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/abstract_controller/callbacks.rb:19:in `process_action'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_controller/metal/rescue.rb:29:in `process_action'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/notifications.rb:159:in `block in instrument'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/notifications.rb:159:in `instrument'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activerecord/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/abstract_controller/base.rb:136:in `process'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionview/lib/action_view/rendering.rb:30:in `process'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_controller/metal.rb:195:in `dispatch'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_controller/metal.rb:231:in `block in action'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/routing/route_set.rb:80:in `dispatch'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/routing/route_set.rb:48:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/routing/mapper.rb:45:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/journey/router.rb:71:in `block in call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/journey/router.rb:59:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/routing/route_set.rb:676:in `call'
  rack-pjax (0.7.0) lib/rack/pjax.rb:12:in `call'
  omniauth (1.1.4) lib/omniauth/strategy.rb:184:in `call!'
  omniauth (1.1.4) lib/omniauth/strategy.rb:164:in `call'
  newrelic_rpm (3.7.1.182) lib/new_relic/rack/error_collector.rb:50:in `call'
  newrelic_rpm (3.7.1.182) lib/new_relic/rack/agent_hooks.rb:28:in `call'
  newrelic_rpm (3.7.1.182) lib/new_relic/rack/browser_monitoring.rb:23:in `call'
  newrelic_rpm (3.7.1.182) lib/new_relic/rack/developer_mode.rb:42:in `call'
  meta_request (0.2.8) lib/meta_request/middlewares/app_request_handler.rb:13:in `call'
  rack-contrib (1.1.0) lib/rack/contrib/response_headers.rb:17:in `call'
  meta_request (0.2.8) lib/meta_request/middlewares/headers.rb:16:in `call'
  meta_request (0.2.8) lib/meta_request/middlewares/meta_request_handler.rb:13:in `call'
  warden (1.2.3) lib/warden/manager.rb:35:in `block in call'
  warden (1.2.3) lib/warden/manager.rb:34:in `call'
  rack (1.5.2) lib/rack/etag.rb:23:in `call'
  rack (1.5.2) lib/rack/conditionalget.rb:35:in `call'
  rack (1.5.2) lib/rack/head.rb:11:in `call'
  remotipart (1.2.1) lib/remotipart/middleware.rb:27:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/params_parser.rb:27:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/flash.rb:241:in `call'
  rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
  rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/cookies.rb:486:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activerecord/lib/active_record/query_cache.rb:36:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activerecord/lib/active_record/migration.rb:380:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/callbacks.rb:82:in `run_callbacks'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/callbacks.rb:27:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/reloader.rb:64:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
  better_errors (1.1.0) lib/better_errors/middleware.rb:84:in `protected_app_call'
  better_errors (1.1.0) lib/better_errors/middleware.rb:79:in `better_errors_call'
  better_errors (1.1.0) lib/better_errors/middleware.rb:56:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/railties/lib/rails/rack/logger.rb:38:in `call_app'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/railties/lib/rails/rack/logger.rb:20:in `block in call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/tagged_logging.rb:68:in `block in tagged'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/tagged_logging.rb:26:in `tagged'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/tagged_logging.rb:68:in `tagged'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/railties/lib/rails/rack/logger.rb:20:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
  rack (1.5.2) lib/rack/runtime.rb:17:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/activesupport/lib/active_support/cache/strategy/local_cache.rb:86:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/actionpack/lib/action_dispatch/middleware/static.rb:64:in `call'
  rack (1.5.2) lib/rack/sendfile.rb:112:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/railties/lib/rails/engine.rb:515:in `call'
   () Users/brettjackson/.rvm/gems/ruby-2.1.0/bundler/gems/rails-017b0fb08a22/railties/lib/rails/application.rb:142:in `call'
  rack (1.5.2) lib/rack/content_length.rb:14:in `call'
  puma (2.7.1) lib/puma/server.rb:486:in `handle_request'
  puma (2.7.1) lib/puma/server.rb:357:in `process_client'
  puma (2.7.1) lib/puma/server.rb:250:in `block in run'
  puma (2.7.1) lib/puma/thread_pool.rb:92:in `block in spawn_thread'

I think this may be due to the following changes made in Ruby 2.1: "* Proc

  • Returning from lambda proc now always exits from the Proc, not from the method where the lambda is created. Returning from non-lambda proc exits from the method, same as the former behavior."

The relevant code in CanCan:

 def enable_authorization(options = {}, &block)
        before_filter(options.slice(:only, :except)) do |controller|
          break if options[:if] && !controller.send(options[:if])
          break if options[:unless] && controller.send(options[:unless])
          controller.authorize! controller.params[:action], controller.params[:controller]
        end
        after_filter(options.slice(:only, :except)) do |controller|
          break if options[:if] && !controller.send(options[:if])
          break if options[:unless] && controller.send(options[:unless])
          unless controller.current_ability.fully_authorized? controller.params[:action], controller.params[:controller]
            raise CanCan::InsufficientAuthorizationCheck, "Authorization check is not sufficient for this action. This is probably because you have conditions or attributes defined in Ability and are not checking for them in the action. One way to solve this is adding load_and_authorize_resource to this controller."
          end
        end
        rescue_from(CanCan::Unauthorized, &block) if block
      end

bjackson avatar Jan 17 '14 21:01 bjackson

Tested on ruby-2.0.0-p353 also, still gets an error. Am I doing something wrong, or is there an issue with the gem?

bjackson avatar Jan 17 '14 23:01 bjackson

@bjackson From the stack trace I assume that you're trying to make it work with devise. I had no problems with both ruby 2.0.0 and 2.1.1.

Here's an example of an app that does just what you want and works fine: https://github.com/zamith/cancan_examples/tree/master/cancan2

Hope it helps.

zamith avatar Mar 25 '14 09:03 zamith

There's a problem in the Gem I'm pretty sure. When I changed those lines of code to no longer have a break and use a next instead (which I believe is how it should be?) it resolves the issue. I'll submit a PR.

illegalnumbers avatar Nov 11 '14 23:11 illegalnumbers