From 9a91937c88009b9e3997625fe74bd87ed19a1adb Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Thu, 29 Feb 2024 13:29:01 -0500 Subject: [PATCH] fix: properly add aggregate authorization everywhere --- lib/ash/actions/read/read.ex | 71 ++++++++++++++++++++++++++++++++---- lib/ash/filter/filter.ex | 2 +- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/lib/ash/actions/read/read.ex b/lib/ash/actions/read/read.ex index 6db08e14..873a4bac 100644 --- a/lib/ash/actions/read/read.ex +++ b/lib/ash/actions/read/read.ex @@ -300,6 +300,17 @@ defmodule Ash.Actions.Read do ), query <- Map.put(query, :sort, sort), query <- add_select_if_none_exists(query), + query <- %{ + query + | filter: + add_calc_context_to_filter( + query.filter, + opts[:actor], + opts[:authorize?], + query.tenant, + opts[:tracer] + ) + }, pre_authorization_query <- query, {:ok, query} <- authorize_query(query, opts), query_before_pagination <- query, @@ -316,7 +327,7 @@ defmodule Ash.Actions.Read do pre_authorization_query, opts[:actor], query.tenant, - agg_refs(query, data_layer_calculations), + agg_refs(query, data_layer_calculations ++ [{nil, query.filter}]), opts[:authorize?] ), data_layer_calculations <- @@ -348,6 +359,14 @@ defmodule Ash.Actions.Read do filter, query.tenant ), + filter <- + add_calc_context_to_filter( + filter, + opts[:actor], + opts[:authorize?], + query.tenant, + opts[:tracer] + ), filter <- update_aggregate_filters( filter, @@ -1036,10 +1055,28 @@ defmodule Ash.Actions.Read do message: "unhandled calculation in filter statement #{inspect(ref)}" %Ash.Query.Ref{attribute: %Ash.Query.Calculation{} = calc} = ref -> - %{ - ref - | attribute: add_calc_context(calc, actor, authorize?, tenant, tracer) - } + calc = add_calc_context(calc, actor, authorize?, tenant, tracer) + + if calc.module.has_expression?() do + {:ok, expr} = + Ash.Filter.hydrate_refs( + calc.module.expression(calc.opts, calc.context), + %{ + resource: ref.resource, + public?: false + } + ) + + add_calc_context_to_filter( + expr, + actor, + authorize?, + tenant, + tracer + ) + else + %{ref | attribute: calc} + end %Ash.Query.Ref{attribute: %Ash.Query.Aggregate{} = agg} = ref -> %{ @@ -1415,7 +1452,18 @@ defmodule Ash.Actions.Read do } _ -> - aggregate + %{ + aggregate + | join_filters: + add_join_filters( + aggregate.join_filters, + aggregate.relationship_path, + ref.resource || + Ash.Resource.Info.related(resource, ref.relationship_path), + relationship_path_filters, + ref.relationship_path + ) + } end else aggregate @@ -2032,7 +2080,16 @@ defmodule Ash.Actions.Read do } :error -> - aggregate + %{ + aggregate + | join_filters: + add_join_filters( + aggregate.join_filters, + aggregate.relationship_path, + query.resource, + path_filters + ) + } end else aggregate diff --git a/lib/ash/filter/filter.ex b/lib/ash/filter/filter.ex index 6357fa6d..58dd02e4 100644 --- a/lib/ash/filter/filter.ex +++ b/lib/ash/filter/filter.ex @@ -1921,7 +1921,7 @@ defmodule Ash.Filter do include_exists?, with_references? ) do - if function_exported?(module, :expression, 2) do + if module.has_expression?() do expression = module.expression(opts, context) case hydrate_refs(expression, %{