简体   繁体   中英

Cancancan passing an object through ability check

I'm setting up an admin ability using Cancancan. I have an association where a room

has_one:group, through: :property

I'm aware that one can't pass an object through using cancancan, but we can check abilities by using a hash.

#ability.rb

if user.has_role?(:admin)    
  can :manage, Room, :group => { :id => user.group_id }  
end

The above ability check works when I'm loading my index, show, update, edit and destroy methods, but doesn't work when I'm loading the new or create methods. I know that Cancancan passes any conditions as a hash, like this , but I don't think it's passing my hash because groups are set up as an association instead of a column on each room object.

#rooms_controller.rb

class RoomsController < ApplicationController 
  load_and_authorize_resource
    def new
      @room = Room.new
    end
end

My question is, how can I check this ability on new and create methods, preferably without adding new columns to my objects.

Any help is appreciated

Thanks

If you are using load_and_authorize_resource , you shouldn't be doing @room = Room.new in the new method. The load_and_authorize_resource method does that for you. So my assumption is you're overwriting the one it's initializing.

The same would apply to all of the other methods in RoomsController , unless you want to override how the image is loaded (eager loading, etc.) or searched for.

Try doing the following.

To check against a rule with custom attributes the new object you create must have those attributes. ie a Room with the current user's group_id

#rooms_controller.rb

class RoomsController < ApplicationController 
  def new
    @room = Room.new(group_id: current_user.group_id)
    authorize! @room
  end
end

Alternatively I think you can specify custom params for an action via https://github.com/CanCanCommunity/cancancan/blob/develop/docs/changing_defaults.md#strong-parameters

So that might (I haven't tested) look like:

#rooms_controller.rb

class RoomsController < ApplicationController 
  load_and_authorize_resource

  def new
    puts @room
  end

  def room_params
    @room_params = params.require(:room).permit(:group_id)
    @room_params[:room].merge(group_id: current_user.group_id) # ??
    @room_params
  end
end

That said, you might not even want to restrict the new action, since the resource doesn't create anything, it might not matter who gets here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM