P.Bra
P.Bra

Reputation: 264

CanCan ability on association

My question is about defining cancancan ability in this following context.

I have a common model with many to many relationship between User and Company entities

class User < ApplicationRecord
    has_many :company_users, dependent: :destroy
    has_many :companies, through: :company_users 
    enum role:[:user, :admin, :superadmin]
end

class Company < ApplicationRecord
    has_many :company_users, dependent: :destroy
    has_many :users, through: :company_users
end

class CompanyUser < ApplicationRecord
    belongs_to :company
    belongs_to :user
end

I want now to define cancan ability in order to authorized current user to manage all the users belonging to the same companies as him.

I have no problem with other many to many schemas (eg : many to many between Device and Company) like this

can :manage, Device, :companies => {:users => {:id => user.id}}

is working fine !

but

can :manage, User, :companies => {:users => {:id => user.id}}

let me see, of course, only the current user because it is on the same users table.

How can I manage easily this ability between users belonging to a same company preserving the many to many relationship ?

Thanks for your help

Upvotes: 2

Views: 2682

Answers (2)

P.Bra
P.Bra

Reputation: 264

Upon the @coorasse recommandations, I finally solve my problem by using 2 scopes as following in user.rb

scope :company_list, -> (user_id) {CompanyUser.where(:user_id => user_id).pluck(:company_id)}
scope :owned_users,  -> (user_id) {CompanyUser.where(:company_id => company_list(user_id)).pluck(:user_id).uniq}

and in the ability.rb

can :manage, User, id: User.owned_users(user.id)

This is working fine.

Upvotes: 2

coorasse
coorasse

Reputation: 5528

You can solve the issue using scopes: https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities-with-Blocks#block-conditions-with-scopes

and defining:

can :manage, User, User.joins(companies: :users).where(companies: { users: { id: user.id } })

please look at the full gist: https://gist.github.com/coorasse/f1174b618651fcee8c65525d38b36120

Upvotes: 5

Related Questions