Policies: authorize if user is an admin of the requested resource's organization
I have a group resource with these relationships:
And an organization resource with these:
And a user resource with this:
And this read action:
I'm trying to write a policy that applies to read actions like the above that only shows groups that:
a) the educator is the owner of
b) the educator is an admin inside the group that the organization belongs to
I got the first one working, but the second bit I don't know how to go about. Basically a policy that checks the group's organization_id and then checks the actor's organization_memberships, finds that org with that id and checks to see if the
role
attribute on it is admin
.
19 Replies
It depends a bit on your data model, but how about something like:
I tried this:
But I get some weird error:
Do I need to "preload" something?
Actually, looks like I was a bit off in my description. There's a
current_organization
that the actor is viewing the page as. The policy needs to check if the actor is an admin on that organization.
So should I be passing that organization's ID into the read actions?Interesting. Are you sure thats how you want to do it?
Think about it this way, if the current organization on the page somehow passes an id down for some other organizations thing, if you do it the way you described, they'd be allowed to read it
So I could read anything just by passing down a
current_organization_id
that I'm an admin of
What you'd want to do is use current_organization_id
to filter the data for the user, and then use criteria independent of that to determine what they can see.
So, the best thing to do is describe, for some given group, when a user should be allowed to see that group (not factoring in the other action inputs)
is probably from one of those relationships not existing
i.e organization.organization_members
means "group -> organization -> organization_members"So the actual requirement is: the user should be able to see the group, if the user is an admin on the organization the group belongs to, OR one of the organizations higher in the org hierarchy.
How does your organization hierarchy work?
In other words, I want to get a list of groups while looking at the page from the perspective of a current organization
is it just like organizations have a
parent_id
type thing?Org hierarchy is that each org can have a parent and also multiple child organizations
yeah
Gotcha. So, that is typically quite difficult to model TBH. It can be done, but its not fun, especially when you consider rules like this one
it technically requires recursively walking the tree all the way up
There are other ways to model hierarchies, or assistive things that you can do that will make your life much easier
for example, if you add an column of type
ltree
representing the position in the tree of each organization
and you can manage that as organizations are created and/or updated
but I imagine you aren't just going to refactor all that stuff right now 😆The modeling is outside my purview. We're translating existing code (which uses Ecto) to Ash
Gotcha. So in that case, yes you can use an argument like
current_organization_id
argument to do this manually
There are two waysRight, I have access to that in the liveview
Just promise me you will test the case where the user passes in a
current_organization_id
that they are the admin of, and attempts to read data from a different organization
you will have to ensure the action logic appropriately filters based on current_organization_id
Actually, I think you can do it all w/ one thing
So doing it with a custom filter check
So
get_parents
is the recursive function that compiles the parent orgs. What is filter_where_admin_of
?That does something to ensure that its only organizations that the user is an admin of
whatever that looks like
OK, I was just wondering if it's an Ash thing
Cool
I'll bang on this for a bit and see how far I can get
So I just do
authorize_if AdminOfOrganizationInHierarchy
inside policies
right?yep!
OK. I might come back here with my tail tucked between my legs. We'll see
Thanks Zach
My pleasure 🙇♂️