Policy references

As shown in the diagram, I'm in a scenario where a container resource has a policy that permits access by either being the creator or a collaborator.
policy action(:read) do
authorize_if relates_to_actor_via(:creator)
authorize_if relates_to_actor_via(:collaborators)
end
policy action(:read) do
authorize_if relates_to_actor_via(:creator)
authorize_if relates_to_actor_via(:collaborators)
end
Is there a way to not have to repeat this logic in all the child resources, such that I could be properly authorized on Item's read action? I think it's possible to use accessing_from to allow reads of items when loading through containers, but that doesn't solve for direct access. I guess this isn't the worst solution in the world…
policy action(:read) do
authorize_if relates_to_actor_via([:container, :creator])
authorize_if relates_to_actor_via([:container, :collaborators])
end
policy action(:read) do
authorize_if relates_to_actor_via([:container, :creator])
authorize_if relates_to_actor_via([:container, :collaborators])
end
But I'd much rather have something like
policy action(:read) do
authorize_if related_resource_would_be_readable(:container)
end
policy action(:read) do
authorize_if related_resource_would_be_readable(:container)
end
So a change to the container rules wouldn't require a policy change in all child resources of the container.
No description
Solution:
My suggestion is to use calculations for this.
Jump to solution
7 Replies
barnabasj
barnabasj3mo ago
policy action(:read) do
authorize_if related_resource_would_be_readable(:container)
end
policy action(:read) do
authorize_if related_resource_would_be_readable(:container)
end
this shouldn't be hard to implement, you can just create a simple check and use Ash.can? to see if the current actor can read the other resource
RootCA
RootCAOP3mo ago
That makes sense. I'll probably end up using the relate via to get filtering though, since that simple check wouldn't interact with the DB—right?
Solution
ZachDaniel
ZachDaniel3mo ago
My suggestion is to use calculations for this.
ZachDaniel
ZachDaniel3mo ago
authorize_if expr(can_read)
..

calculate :can_read, :boolean, expr(...)
authorize_if expr(can_read)
..

calculate :can_read, :boolean, expr(...)
Then in the child resource
authorize_if expr(parent.can_read)
authorize_if expr(parent.can_read)
RootCA
RootCAOP3mo ago
🤯 that makes a lot of sense
ZachDaniel
ZachDaniel3mo ago
I'd like to implement a can_read pattern, its just a bit complex and requires "analysis" of the policies to determine if it can be done as a filter or requires running queries etc.
RootCA
RootCAOP3mo ago
I had a feeling this was more tricky because policies are so flexible that being able to read isn't universal Thanks both of you!

Did you find this page helpful?