accessible_by permanently modifies a rule's conditions via normalize_conditions, causing can? to fail
The ConditionNormalizer in accessible_by permanently modifies a rule's conditions when you call accessible_by, meaning that a call to the can? method that worked before calling accessible_by may not work afterwards.
For example, say I have the models Client, Project, and Activity, where an activity belongs to a project and a project belongs to a client. In Ability, I can create a rule to say that a user can read any project or activity belonging to client with id 10:
can :read, [ Project, Activity ], client: { id: 10 }
This creates a rule with conditions: { client: { id: 10 } }.
Then if I run this code in the controller:
@project = Project.first
can? :read, @project
@activities = Activity.accessible_by current_ability
can? :read, @project
then the first call to can? runs without error. The call to Activity.accessible_by current_ability permanently changes the rule's conditions to { project: { client: { id: 10 } } } via a call to normalize_conditions, and the second identical call to can? then raises a NoMethodError saying "undefined method `project' for an instance of Project" because the new conditions make cancancan call @project.project.client instead of @project.client.
Is the rule illegal, ie should you only ever create a rule with an array of models that all have through reflections to the condition OR all have belongs_to reflections to the condition? Or should accessible_by not permanently change the conditions for the rule?
I'm using cancancan 3.6.1 and Rails 8.0.1.