This is the relevant part of my ability.rb class:
def initialize(user)
can :manage, User do |u|·
user == u·
end
end
According to cancan documentation:
The block is only evaluated when an actual instance object is present.
It is not evaluated when checking permissions on the class (such as in
the index action).
However, for the UsersController index action, even though the block isn’t run, it still grants :manage permissions, listing the users.
I have confirmed this by commenting out the above code, and then the user is not authorized.
As far as I understood cancan, the block is supposed to to run (which indeed it doesn’t), and if it doesn’t run, then the block is considered to have returned false, thus not granting the permission.
Am I getting this wrong, or is this a bug?
I’m using cancan version 1.67.
I think you are misreading the documentation here:
If no instance is evaluated but rather a Class cancan will NOT execute the block as there is no instance check to be performed.
This saves you the hassle of making the block nil resilient.
Since the block is never executed there is no assumption made what it returns and cancan will only look at it’s Class rules.
If it would call the block you’d have to account for this (in a slightly more complex model):
I guess the default is buried here, but this seems like a sensible default.
If you are going to allow a user to manage his own posts anyway you should prevent him from seeing other’s posts in the index anyway. So the only threat to you is him accessing a resource he explicitly has no access to.
(Cancan will never hook up on normal ActiveRecord queries and filter them down by abilities. So User.all will always return all users – regardless of ability)
However: If you are trying to implement something like a profile, I’d suggest you just change around your UsersController logic a bit and simply make the profile a singular resource as described in the Rails Guides