I noticed users could access an action they shouldn't be able to access.
I debugged in the rails console with something like
user = User.first
physician = Physician.first
ability = Ability.new(user)
ability.can?(:send_message, physician)
# => false
The above says that user can't access the send_message action for that physician, which is the desired behaviour, yet I know they can in the app!
I think this narrows down the cause to a problem with cancancan loading the wrong model instance for some reason. And that's hinted to in the cancan docs too:
Note: this assumes that the model instance is being loaded properly.
But the problem is I'm not sure how to diagnose the problem from here, since the console says it should be working. I don't know how to view the model instance that cancancan has set, and I don't know what else to try.
Any ideas?
Update
I did manage to work around this by using authorize! :send_message, physician
in the controller, but since I only stumbled upon this behaviour by chance, I think it's much more important to figure out why the wrong model instance was being loaded (especially so I can see if that was happening elsewhere too).
I figured out why it was probably happening (but I still don't know how to disagnose it)
I think this was happening because I had many custom actions, and some had @physician = Physician.find(current_user.physician.id)
(i.e they're the current user), whereas others were more like @physician = Physician.find_by_id(physician_params[:id])
. I'm not sure how cancan sets the instance model, but I do know it's not psychic, so it wouldn't know whether to set it to the current user's physician instance, or the physician instance for the physician id passed in.
What remains?
How does cancancan set the model instance for custom methods (I presume it tries something, and if that doesn't work, tries something else, etc etc)?
Small notes that help:
load_and_authorize_resource
does attempt to load the model instance for non RESTful actions- Some useful info in the docs
- This may have something to do with what I experienced:
When I returned slug it breaks this behaviour and I can edit all pokemons.