I’m just getting my head around basic AshAuthorization and still struggle with some of the relationship DSL… and I’ve no idea how to tackle this one.
I have two resources, Teams
and Users
(the later being defined by AshAuthentication). They are related via a many_to_many
named :team_members
:
# Team policies do bypass actor_attribute_equals(:role, :admin) do authorize_if always() end policy action_type(:update) do authorize_if actor_attribute_equals(:role, :team_lead) && expr(exists(team_memberships, user_id == ^actor(:id))) end end relationships do has_many :team_memberships, WasteWalk.Teams.Members has_many :sprints, WasteWalk.Sprints.Sprint many_to_many :team_members, WasteWalk.Accounts.User do join_relationship :team_memberships source_attribute_on_join_resource :team_id destination_attribute_on_join_resource :user_id end end
As you can see, to update a team, you need to be a team lead for that team.
User
s are just users, as defined by Ash. I’ve added a many_to_many
relationship to the User
resource:
# User relationships do has_many :team_memberships, WasteWalk.Teams.Members many_to_many :teams, WasteWalk.Teams.Team do join_relationship :team_memberships source_attribute_on_join_resource :user_id destination_attribute_on_join_resource :team_id end end
Keeping in mind that only someone with a :team_leads
role can actually modify their own Team
, I want to extend that to team membership. In other words, only a :team_lead
can modify (create, destroy) the members of a team.
As it is now (see below) a team lead could modify another team’s membership. (The code API doesn’t really support it, but there’s nothing keeping someone from updating the Members
resource directly).
So I’m struggling with the DSL to prevent team leads from modifying relationships unless they are a :team_lead
(role) for the specific :team_id
they are updating. I’ve no idea how to do that with the policy DSL… (see comment, below – vague idea, but lacking practical knowledge).
# Members policies do bypass actor_attribute_equals(:role, :admin) do authorize_if always() end policy action_type(:create) do authorize_if actor_attribute_equals(:role, :admin) # TODO restrict to only :team_lead's own teams: # e.g. kind of like... && expr(exists(team_memberships, user_id == ^actor(:id))) authorize_if actor_attribute_equals(:role, :team_lead) # &&...?? end policy action_type(:read) do authorize_if always() end end actions do defaults [:read] create :create do primary? true accept [:user_id, :team_id] end end relationships do belongs_to :user, WasteWalk.Accounts.User, primary_key?: true, allow_nil?: false belongs_to :team, WasteWalk.Teams.Team, primary_key?: true, allow_nil?: false actions do defaults [:read, :destroy, update: :*] end end