Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I know if a user has access to all or just some resources with Cancan?

I have a Rails 3 application that uses Cancan for authorization. I have the following logic in my application: An admin has access to manage all other users, and has can :manage, User set in the ability file. A company owner has access to manage all users under his company, and has can :manage, User, company_id: user.company_id set in the ability file.

In my UserController#index, i need to call one method if the user has access to manage all the other users, and another method if the user only can access users from his company. Is there any way to do this with CanCan?

like image 967
karianneberg Avatar asked Oct 25 '25 05:10

karianneberg


2 Answers

As discussed in the question comments, this sounds like a case of roles vs abilities.

If there already is a role system in place, and the logic for choosing between methods maps directly to these roles, then going through CanCan abilities is unnecessarily complex. CanCan is good at checking for abilities on specific model objects, classes and collections but not at going back to the original logic behind why those abilities were awarded in the first place.

In this specific case, there would need to be a way to refer to the case "can manage all Users in Company X but NOT all Users". It might be possible to accomplish with some if-else structure, but I don't think it is what you actually want. Especially if your ability logic changes over time it may not make sense anymore. One example is the corner case where all users belong to the same company, would it be desirable that the "all Users" method is called even for non-admin company owners?

My suggestion therefore is to check the roles directly, much like you already do in your Abilities class. But I feel your pain. ;)

like image 90
lime Avatar answered Oct 26 '25 20:10

lime


I know this an old question but I also ran into this situation. I was also looking to do all role checking in ability.rb file in one place.

What I ended up doing was far from ideal, but just noting it down if anyone wants to go that road. I defined a new ability like this in the ability.rb:

can :manage, :all_users if user.admin?

Please note that :all_users is just a random name that I chose and not some magic method in cancan.

After defining this ability, I was able to do like this in the controller:

if can? :manage, :all_users
  call_method_which_can_access_all_users
else
  call_method_which_can_access_only_some_users
end

But, it would have been great if Cancan gave us something like can? :manage, User, :all depending on whether there is a hash for filtering users after the User parameter.

like image 42
rubyprince Avatar answered Oct 26 '25 20:10

rubyprince



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!