schrockwell / bodyguard

Simple authorization conventions for Phoenix apps

Home Page:https://hexdocs.pm/bodyguard/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How do you handle cases when role is defined in another model?

abitdodgy opened this issue · comments

For example, in scenarios where you have a many-to-many association between, say, companies and users, where the role column is defined in the memberships schema.

In this scenario, the current user is not enough. We also need the membership record.

Easy enough, I suppose:

  def can?(%User{id: user_id}, action, %Organisation{id: org_id})
  when action in [:edit, :update] do
    case Repo.get_by(Membership, user_id: user_id, organisation_id: org_id, role: :admin) do
      nil -> false
      _ -> true
    end
  end

Can you preload the user.memberships association prior to authorization? If so, then in your policy you can do everything in-memory:

def can?(%User{memberships: memberships}, action, %Organisation{id: org_id})
when action in [:edit, :update] do
  Enum.any?(memberships, &match?(%Membership{organisation_id: ^org_id, role: :admin}, &1))
end

@schrockwell great suggestion as well. Thanks.