diff --git a/lib/ash/query/query.ex b/lib/ash/query/query.ex index 997ed471..e19ebe5d 100644 --- a/lib/ash/query/query.ex +++ b/lib/ash/query/query.ex @@ -904,12 +904,36 @@ defmodule Ash.Query do load_relationship(query, [{field, nested_query}]) resource_calculation = Ash.Resource.Info.calculation(query.resource, field) -> + {name, load} = + cond do + Keyword.keyword?(rest) -> + case Keyword.fetch(rest, :as) do + {:ok, value} -> + {value, nil} + + :error -> + {resource_calculation.name, resource_calculation.name} + end + + is_map(rest) -> + case Map.fetch(rest, :as) do + {:ok, value} -> + {value, nil} + + :error -> + {resource_calculation.name, resource_calculation.name} + end + + true -> + {resource_calculation.name, resource_calculation.name} + end + {module, opts} = resource_calculation.calculation with {:ok, args} <- validate_calculation_arguments(resource_calculation, rest), {:ok, calculation} <- Calculation.new( - resource_calculation.name, + name, module, opts, {resource_calculation.type, resource_calculation.constraints}, @@ -918,9 +942,9 @@ defmodule Ash.Query do resource_calculation.load ) do calculation = - select_and_load_calc(resource_calculation, %{calculation | load: field}, query) + select_and_load_calc(resource_calculation, %{calculation | load: load}, query) - Map.update!(query, :calculations, &Map.put(&1, field, calculation)) + Map.update!(query, :calculations, &Map.put(&1, name, calculation)) else {:error, error} -> Ash.Query.add_error(query, :load, error) diff --git a/lib/ash/resource/dsl.ex b/lib/ash/resource/dsl.ex index 78a78fc6..f1a26b56 100644 --- a/lib/ash/resource/dsl.ex +++ b/lib/ash/resource/dsl.ex @@ -1331,7 +1331,8 @@ defmodule Ash.Resource.Dsl do ] @verifiers [ - Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch + Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch, + Ash.Resource.Verifiers.VerifyReservedCalculationArguments ] @moduledoc """ diff --git a/lib/ash/resource/verifiers/verify_reserved_calculation_arguments.ex b/lib/ash/resource/verifiers/verify_reserved_calculation_arguments.ex new file mode 100644 index 00000000..ebcad948 --- /dev/null +++ b/lib/ash/resource/verifiers/verify_reserved_calculation_arguments.ex @@ -0,0 +1,22 @@ +defmodule Ash.Resource.Verifiers.VerifyReservedCalculationArguments do + @moduledoc "Verifies that standard context keys are not used as calculation arguments" + use Spark.Dsl.Verifier + + @reserved_calculation_argument_names ~w(actor tenant authorize? tracer as)a + + def verify(dsl) do + dsl + |> Ash.Resource.Info.calculations() + |> Enum.each(fn calculation -> + Enum.each(calculation.arguments, fn argument -> + if argument.name in @reserved_calculation_argument_names do + raise Spark.Error.DslError, + module: Spark.Dsl.Verifier.get_persisted(dsl, :module), + message: + "Argument #{argument.name} is reserved and cannot be used in a calculation argument.", + path: [:calculations, calculation.name, :argument, argument.name] + end + end) + end) + end +end