Policies don't allow to load relationships
I had simple policies and two resource
if user is superadmin, then he is granted access
if user has location access and permission access, both true, then he is granted access
both resources had same policies, one has_many another
Strangely, Ash.load refused to work
I did a workaround and made a check to combine all three checks together and left only one authorize_if with combined check, that worked.
I think it is a bug
7 Replies
I had an custom admin SimpleCheck for bypass and when i made :unknown for "not admin" and had it in second resource policies, it made Ash.Load, but when i replaced policies with a combined simple check it refused to load again.
That's so uneven, and hard to catch
It sounds like you're doing something strange to me
:unknown
should only be returned when you dont know and will generally be treated as false in all cases that matter
And when you say "refused to load" what do you mean?passing :unknown will do not good things for me, because i believe it has if check do statement somewhere, where :unknown will be treated as "true". And this check with :unknown output will be bypassing like superadmin for me which is not good
but i found the issue. I pass context: %{permissions_check_context_data: data} to the first Ash.Query
but when i do Ash.load and add same context there, it doesn't add it.
the load context will have
accessing_from: %{name: :tables, source: Department},
parent_stack: [Department]
and it will not have my permissions check context data there even if I place
|> Ash.load(context:...)
or even if i try to load it manually with
Ash.load!(department, :tables, context: context)
@ZachDaniel Would be good to pass context to Ash.load(), because it is easy to manage with nested data and not to write separate queries for them 🙏
for example i run this
departments = if current_place_id do
context = %{permission_check_current_place_id: current_place_id}
# First, load departments without tables
departments = Restaurant.Department
|> Ash.Query.filter(place_id == ^current_place_id)
|> Ash.Query.set_context(context)
|> Ash.read!(actor: socket.assigns.current_user, tenant: socket.assigns.current_tenant)
# Then load tables with context using Ash.load!/3
IO.inspect("Loading tables with context", label: "DEBUG")
IO.inspect(context, label: "Context being passed")
Ash.load!(departments, :tables,
actor: socket.assigns.current_user,
tenant: socket.assigns.current_tenant,
context: context
)
and i don't get my context in the Ash.load!(),
the context of Ash.load looks this, without permission_check
Authorizer Context: %{ private: %{ tracer: [], actor: %Rover.Accounts.User{ id: "41bb9a76-b76c-45fb-9990-bc8e4f99dcb7", email: nil, first_name: "GGG", last_name: "XXX", user_type: :pin_code_login, inserted_at: ~U[2025-05-25 06:48:25.712139Z], updated_at: ~U[2025-06-20 13:37:48.738028Z], org_id: "b5f1450f-d2f1-4dee-ba7e-4e8815a3f060", archived_at: nil, roles_join_assoc: #Ash.NotLoaded<:relationship, field: :roles_join_assoc>, org: #Ash.NotLoaded<:relationship, field: :org>, roles: #Ash.NotLoaded<:relationship, field: :roles>, employee: #Ash.NotLoaded<:relationship, field: :employee>, meta: #Ecto.Schema.Metadata<:loaded, "users"> }, authorize?: true, async_limiter: nil, loading_relationships?: true, pre_flight_authorization?: false }, accessing_from: %{name: :tables, source: Rover.Restaurant.Department}, parent_stack: [Rover.Restaurant.Department] }
You can use shared context for that
https://hexdocs.pm/ash/3.5.23/actions.html#context
There should not be cases where unknown checks can authorize a policy
This may be a bug
Please create a reproduction and I will look into it
Thanks! I will check it out
Zach, thanks for your hard work, now with shared context everything works smooth!
There was no bug at all
There is no need for that, my checks were depending on context information and I wasn't expecting that being passed to context as a key they would not persist in nested loads. Now, with that information being moved to shared, all my checks gracefully work 🙂 and i don't need to output :unknown, now i output only true or false with my checks (i thought i was "inventing" a workaround with :unknown)
@Zach Daniel
I couldn't load many-to-many relationship
when it nestedly runs queries and comes to join_through resource, it loses shared context on that resource,
for example
user has one employee
employee has many-to-many places
through employee_place resource
context with %{shared: %{info: info}} will go to:
user authorizer - yes
employee authorizer - yes
employee_place authorizer - no <--- here it is lost
place authorizer - yes
so i can't set my authorizers to that resource (employee_place)
This is a bug then
Please open an issue and I'll fix
thank you! i created an issue and a reproduction repo
https://github.com/ash-project/ash/issues/2159
GitHub
many-to-many relationship doesn't preserve shared context in nested...
Versions ash 3.5.23 ash_postgres 2.6.8 ash_sql 0.2.82 Operating system Ubuntu 24 Current Behavior Policies are set with checks using shared contexts We can't fetch nested loads for resources ac...