stffn / declarative_authorization

An unmaintained authorization plugin for Rails. Please fork to support current versions of Rails
MIT License
1.24k stars 233 forks source link

Rails 5 : Syntax fix recursive loop where prepend-ed modules exist #224

Open simon-smartdata opened 7 years ago

simon-smartdata commented 7 years ago

HI in_controller.rb line 600 ish
ancestors[1..-1] is the issue.

protected
      def filter_access_permissions # :nodoc:
         unless filter_access_permissions?
          ancestors[1..-1].reverse.each do |mod|
            mod.filter_access_permissions if mod.respond_to?(:filter_access_permissions, true)
          end
        end
        class_variable_set(:@@declarative_authorization_permissions, {}) unless filter_access_permissions?
        class_variable_get(:@@declarative_authorization_permissions)[self.name] ||= []
      end

This is a recursive method and ancestors[1..-1] appears to be designed to remove the current object's class from the iterator, with the assumption that the current object is its own first ancestor. eg if ancestors returns [ ActionController::Base, ActiveRecord::Railties::ControllerRuntime, ....... ] [1..-1] removes the first element which is assumed to be the current object, in this case ActionController::Base.

However this fails if other gem modules (eg wicked_pdf) are designed to prepend to the front of the ancestors chain.

See Nice Module#prepend explanation here

For example: prepend excerpt from the wicked_pdf gem:

class WickedPdf
  if defined?(Rails)
    if Rails::VERSION::MAJOR >= 5
      class WickedRailtie < Rails::Railtie
        initializer 'wicked_pdf.register' do |_app|
          ActionController::Base.send :prepend, PdfHelper
          ActionView::Base.send :include, WickedPdfHelper::Assets
        end
      end

ancestors returns [WickedPdf::PdfHelper, ActionController::Base, ActiveRecord::Railties::ControllerRuntime, ....... [1..-1] removes the first element, in this case the prepend-ed WickedPdf::PdfHelper, leaving the current object ( ActionController::Base) in the iterator which causes the infinite loop.

FIX: Replace

ancestors[1..-1].reverse.each do |mod|

WITH

(ancestors - [self] ).reverse.each do |mod|

Thanks Simon

rbishop commented 7 years ago

I experienced this as well and fixed it similarly. I didn't get down to what was causing it so good find on prepending being the issue. We use WickedPdf as well. :+1: