Search code examples
ruby-on-railsrubydevisecancan

Rails: Make model to read and edit only own data by CanCanCan


I have Admin and Partner models. Partner has_many Services. I am using Devise and CanCanCan. I have set my defaults in my application_controller:

# This is for changing defaults for CanCanCan
 def current_ability
   if admin_signed_in?
     @current_ability ||= Ability.new(current_admin)
   elsif partner_signed_in?
     @current_ability ||= Ability.new(current_partner)
 end
end

Now inside my Abilities class:

case model
  # if model is Admin
  when Admin
    can :manage, :all

  # if model is Partner
  when Partner
    can :read, Partner, id: model.id

    can :manage, Service, partner_id: model.id, partner: {active: true}
    can :create, Service

    can :update, Partner, id: model.id, active: true


  else
    cannot :read, :all
end

model is an parameter i made instead of old user. I have placed a lot of if can? conditions inside my views.

Now here is the question: depending on who logged in, how I can restrict access to pages and controllers combining Devise and CanCanCan?

I thought I will add somethinglike this for every controller:

before_action :check_logged_in

def check_logged_in
    if partner_signed_in?
       # do something
    elsif admin_signed_in?
       # do something
    end
end

But this makes CanCanCan useless and will be hard to maintain if I have too many controllers.

I thought I should use load_and_authorize_resource for my controllers, but I have only Admin and Partner models that has Devise authorization and there are a lot of controllers of models that does not need any authorization or even without models.


Solution

  • Well I don't know how to do it on all models, but you can make rules on each model like this

    when Partner
      can :manage, Service, user_id: user.id
    

    This will only allow the partner to manage services where(user_id: current_user.id)