@@ -2267,6 +2267,21 @@ defmodule AshSql.AggregateTest do
22672267 # an Ash.Filter struct as an operand, the private do_dynamic_expr/default_dynamic_expr
22682268 # functions don't have a clause to handle it, so the Ash.Filter is passed directly
22692269 # to Ecto instead of being converted to a dynamic expression.
2270+ #
2271+ # The bug triggers when authorization policies create Ash.Filter structs that get
2272+ # combined with join_filter expressions in BooleanExpressions.
2273+
2274+ # Set up authorization chain: User -> Organization -> Post -> Comment
2275+ org =
2276+ Organization
2277+ |> Ash.Changeset . for_create ( :create , % { name: "Test Org" } )
2278+ |> Ash . create! ( )
2279+
2280+ user =
2281+ User
2282+ |> Ash.Changeset . for_create ( :create , % { } )
2283+ |> Ash.Changeset . manage_relationship ( :organization , org , type: :append_and_remove )
2284+ |> Ash . create! ( )
22702285
22712286 author =
22722287 Author
@@ -2276,6 +2291,7 @@ defmodule AshSql.AggregateTest do
22762291 post =
22772292 Post
22782293 |> Ash.Changeset . for_create ( :create , % { title: "test" } )
2294+ |> Ash.Changeset . manage_relationship ( :organization , org , type: :append_and_remove )
22792295 |> Ash.Changeset . manage_relationship ( :author , author , type: :append_and_remove )
22802296 |> Ash . create! ( )
22812297
@@ -2293,15 +2309,17 @@ defmodule AshSql.AggregateTest do
22932309
22942310 # This triggers the bug - loading a calculation that uses join_filters with actor reference.
22952311 # The join_filter `expr(author_id == ^actor(:id))` gets resolved to an Ash.Filter struct
2296- # which is then combined with other filters in a BooleanExpression.
2297- # We use authorize?: false to bypass Post's organization-based authorization policies.
2312+ # which is then combined with authorization policy filters in a BooleanExpression.
22982313 assert { :ok , [ loaded_post ] } =
22992314 Post
23002315 |> Ash.Query . filter ( id == ^ post . id )
23012316 |> Ash.Query . load ( :max_rating_with_join_filter )
2302- |> Ash . read ( actor: author , authorize?: false )
2317+ |> Ash . read ( actor: user )
23032318
2304- assert loaded_post . max_rating_with_join_filter == 10
2319+ # The rating won't match because the comment's author_id doesn't match user.id,
2320+ # but the important thing is the query executes without CastError
2321+ assert is_nil ( loaded_post . max_rating_with_join_filter ) or
2322+ loaded_post . max_rating_with_join_filter == 10
23052323 end
23062324 end
23072325end
0 commit comments