cancancan
cancancan copied to clipboard
hash_condition_match returns nil when subject is ActiveRecord Collection Proxy
When the subject is an ActiveRecord_Associations_CollectionProxy(ActiveRecord::Relation)
, the inner_foo value is true, but the outer_foo value is nil as seen below;
This is because it calls this method instead of array's any?
:
https://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-any-3F
![screen shot 2018-10-17 at 17 10 56](https://user-images.githubusercontent.com/637868/47100617-d98d1d80-d22f-11e8-8c3f-9512f2cf16f2.png)
System configuration
Rails version: 5.2.0
Ruby version: 2.5.1
CanCanCan version 2.3.0
I'm still struggling to isolate exactly why any?
is returning nil, but while debugging it, got a casual segfault from the gem which makes no sense to me so far.
Edit: Turns out using return
inside the block in ActiveRecord is causing the segfault.
Edit2: See @laurawatson 's reproduction below.
can you provide a gist to reproduce your issue? Is not clear to me, sorry.
Here is a reproduction of the issue: https://github.com/laurawatson/can_can_check.
In this reproduction, the issue occurs when you first login as an adviser user and try to access the foo show page. It will redirect you to the home page despite the adviser user having access to foo. If you then head back to the foo show page you will be allowed in (more info in the readme).
@coorasse We're currently effectively having to inline our ActiveRecord conditions to avoid this bug. We suspect it's some unusual interaction between ActiveRecord lazy loading and this gem but I have been unable to diagnose it further than that any?
method mentioned previously.
Would you be so kind as to confirm if you see the same issue as us in the example repo linked by @laurawatson above? If it is at least a confirmed bug then we may be able to put some time aside to help fix it, until then all we can do is assume it's our mistake and not use this gem.
I confirm that I see the same behaviour.
changing the rule
can :read, Foo, user_roles: { user: user } #wrong
into
can :read, Foo, user_roles: { user_id: user.id } #correct
fixes the issue.
But I still don't understand why.
And the user can also see http://cancan_error.localhost:3000/bars/1
which should be protected. By using the id
instead of the association name user
(which is not supported) fixes it
It seems like I'm not able to reproduce the issues outlined by @laurawatson.
Manually checking the Foos that the user has access to I was able to record the same behaviour for
can :read, Foo, user_roles: { user: user }
and
can :read, Foo, user_roles: { user_id: user.id }
In addition to that, by using either authorize! or load_and_authorize_resource in controllers/bars_controller.rb I'm not able to access bars/1 with neither {user : user} nor {user_id : user.id }
I guess I must have missed something ^^ Would anyone be so kind as to point me into the correct direction ?
EDIT: Was able to reproduce it ^^ seems that something went wrong during setup
@BookOfGreg Interesting thing about the line of code you referenced ^^
By changing:
attribute.any? { |element| matches_conditions_hash?(element, value) }
to:
match_results = attribute.map { |element| matches_conditions_hash?(element, value) }
match_results.any?
It works :D