0

I am trying to satisfy the following requirements using CanCan:

  1. If a deal is assigned to 1-many networks, the user can read the deal if s/he is a member of any of the assigned networks.

  2. If a deal is not assigned to any network, it can be viewed by any registered user regardless of their network memberships.

  3. If a deal is not assigned to a network, but the deal is marked member_only = true, the user can read the deal if s/he is a member of any network.

  4. If a deal is not assigned to a network and marked member_only = false, any registered user can read the deal.

  5. Guests (i.e., not a user) cannot read any deals

I think I have 2-4 covered with the following:

if current_user.persisted?
  can :read, Deal, current_user.networks.empty? ? { member_only: false } : {}
end

But, I am unsure how to further restrict deals assigned to a network. Is this possible with CanCan. If so, suggestions on how? Thanks.

Eric M.
  • 5,399
  • 6
  • 41
  • 67

2 Answers2

1

Try accessible_by. This way you just show an empty list if the user has no access to data. In other words, instead of restricting access to pages, you restrict access to data using cancan scopes.

Also see: related answer

Community
  • 1
  • 1
nurettin
  • 11,090
  • 5
  • 65
  • 85
0

Here is what I came up with. Probably not the best solution, so feedback welcomed.

if current_user.persisted?
  can :read, Deal, { id: DealAccessPolicy.accessible_deal_ids_for(current_user) }
end

class DealAccessPolicy
  def self.accessible_deal_ids_for(user)
    Deal.pluck(:id) - (Network.all - user.networks).map{|r| r.deals.map(&:id)}.flatten.uniq
  end
end
Eric M.
  • 5,399
  • 6
  • 41
  • 67