codevise / activeadmin-searchable_select

Searchable select boxes for forms and filters
Other
96 stars 33 forks source link

Support for authorizing AJAX requests #16

Open denisahearn opened 4 years ago

denisahearn commented 4 years ago

We are using ActiveAdmin's PunditAdapter to provide authorization of the ActiveAdmin controller actions. After we integrated activeadmin-searchable_select with AJAX, we ran into an issue with the *_options controller actions. They would execute without first authorizing the request, and as a result would fail due to a Pundit::AuthorizationNotPerformedError error.

We have worked around the problem by overriding the ActiveAdmin::SearchableSelect::ResourceDSLExtension:: searchable_select_options method in an initializer, by calling an authorize method (in our ApplicationController class) prior to calling render within the collection_action block:

module ActiveAdmin
  module SearchableSelect
    module ResourceDSLExtension
      def searchable_select_options(name: :all, **options)
        option_collection = OptionCollection.new(name, options)
        config.searchable_select_option_collections[name] = option_collection

        collection_action(option_collection.collection_action_name) do
          #--------------------------------------------------
          # Customization
          authorize :application
          #--------------------------------------------------
          render(json: option_collection.as_json(self, params))
        end
      end
    end
  end
end

While this works, we would prefer not to override/replace code in the gem. Would it be possible to enhance the gem to use ActiveAdmin's built-in authorization to authorize the *_options requests?

Thanks, Denis

tf commented 4 years ago

In my use cases so far, authorization could be handled by limiting the scope to things the current user is allowed to see. So basically everyone was allowed to call all option endpoints, but might get an empty response.

I understand, though, that this does not play well with Pundit's verify_authorized feature. If you pass a proc to the scope option, it is evaluated in the context of the collection action. So, technically, you should be able to call authorize there, before returning the scope. That looks rather ugly, though.

I agree, that it would be nice to automatically authorize the requests against the configured authorization adapter. I'm not sure, though, what action should be authorized by default. Also the change needs to be made in a way that preserves backwards compatibility for current users of the Pundit adapter.

So maybe a middle ground could be introducing a new authorize option which takes the name of the method to call on the resource's policy?

ActiveAdmin.register Category do
  searchable_select_options(scope: Category.all,
                            authorize: :get_options, # Makes collection action call CategoryPolicy.get_options?
                            text_attribute: :name)
  end
end

Happy to accept a PR.