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
kurmetaubanov
kurmetaubanovOP4mo ago
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
ZachDaniel
ZachDaniel4mo ago
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?
kurmetaubanov
kurmetaubanovOP4mo ago
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] }
ZachDaniel
ZachDaniel4mo ago
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
kurmetaubanov
kurmetaubanovOP4mo ago
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)
ZachDaniel
ZachDaniel4mo ago
This is a bug then Please open an issue and I'll fix
kurmetaubanov
kurmetaubanovOP4mo ago
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&#39;t fetch nested loads for resources ac...

Did you find this page helpful?