Francesco Meli
Francesco Meli

Reputation: 2700

ActiveAdmin checking create authorization

To me it seems that ActiveAdmin should check the create authorization mainly in 2 cases:

That's it! So why would ActiveAdmin check the following right before showing the generated "create form" for the user?

user.can?(:create, Ticket.new({author_id: nil, some: nil, other: nil, values: nil}))

What if the current user has only permission to create tickets where author_id = own_user_id?

The authorization would fail even before seeing the form.

Upvotes: 1

Views: 370

Answers (2)

Francesco Meli
Francesco Meli

Reputation: 2700

I did override the Data Access class as follows, in order to have it working.

I am:

  • disabling authorization that i feel is done in the wrong time
  • forced validation before the authorization before saving a resource

    ActiveAdmin::ResourceController::DataAccess.module_eval do
      def build_resource
        get_resource_ivar || begin
          resource = build_new_resource
            resource = apply_decorations(resource)
          run_build_callbacks resource
    
          # this authorization check is the one we don't need anymore
          # authorize_resource! resource
    
          set_resource_ivar resource
        end
      end
    end
    
    ActiveAdmin::ResourceController::DataAccess.module_eval do
      def save_resource(object)
        run_save_callbacks object do
          return false unless object.validate # added it
          authorize_resource! resource        # added it
          object.save(validate: false)        # disabled validation since i do it 2 lines up
        end
      end
    end
    

Upvotes: 1

Tom Aranda
Tom Aranda

Reputation: 6036

I can't explain why ActiveAdmin was written that way, but I can show you how I've solved a similar problem.

First, you will need to grant your user the ability to create the desired record under all conditions:

# app/models/ability.rb
...
  can :create, Ticket
...

This will get your past ActiveAdmin's can? check and allow the user to see the form. But we need to make sure the author_id belongs to the current user. To do this, you can use the before_create callback to set the proper author_id before saving:

# app/admin/ticket.rb
ActiveAdmin.register Ticket do
...
  before_create do |ticket|
    ticket.author_id = own_user_id
  end
...
end

The above assumes you have a helper method or a variable called own_user_id that is available to the ActiveAdmin module and returns the proper user id. If you were using Devise, you might substitute current_user.id for own_user_id.

I'll admit, this is a not the cleanest solution, but it works. I have implemented something similar in my own projects.

Upvotes: 1

Related Questions