Reputation: 634
I am using cancan
for authorisation, and I would like to make some restrictions based on a many to many relationship.
Entities
User - has_many project_assignments
User - has_many projects, through: :project_assignments
User - has_many roles, through: :project_assignments
ProjectAssignment: user_id, project_id, role_id
I want to give the user the ability to do a full CRUD
on Project and Toy
models, only if the project was created by the user. Toy is nested under Project
Toy has many Projects
and Project has many Toy
through ProjectToy
if user.role? :moderator
can :crud, [Project, Toy]
end
I think I only need to restrict the project
, because toy
is depending on the project_id, can I do this?
Upvotes: 1
Views: 160
Reputation: 634
I found a solution:
In my Project controller I have added:
load_and_authorize_resource through: :current_user
In my Toy controller I added:
load_and_authorize_resource project, through: :current_user
load_and_authorize_resource :toy, through: :project
In my Ability file:
if user.role? :moderator
can :crud, :all or [Project, Toy]
end
And everything is working fine, I`ve assigned a user to multiple projects, and it has access to each project.
Upvotes: 1
Reputation: 824
I would try to use some kind of if statement for the second many to many:
can :crud, Project do |project|
ProjectAssignment.where(user_id: user.id, project_id: project.id).any?
end
can :crud, ProjectToy do |project_toy|
ProjectAssignment.where(user_id: user.id, project_id: project_toy.project.id).any?
if can? :crud, ProjectToy
can :crud, Toy do |toy|
ProjectToy.where(toy_id: toy.id).any?
end
end
end
PS - You may need to be careful with :crud and replace this with [:edit, :update, :destroy, :delete] then give a separate can to :create because if the user is creating a project/toy for the first time then the system won't find any toys or projects associated with him/her and not provide access.
Upvotes: 2