fix: temporarily disable field policy deselection optimization

also added a test for related field calc dependencies,
commented out until I fix it later
This commit is contained in:
Zach Daniel 2024-05-07 16:08:56 -04:00
parent d2bfaff377
commit ce559bc018
3 changed files with 72 additions and 16 deletions

View file

@ -326,7 +326,7 @@ defmodule Ash.Actions.Read do
end
end
defp do_read(%{action: action} = query, calculations_at_runtime, calculations_in_query, opts) do
defp do_read(%{action: action} = query, _calculations_at_runtime, calculations_in_query, opts) do
maybe_in_transaction(query, opts, fn ->
with {:ok, %{valid?: true} = query} <- handle_multitenancy(query),
{:ok, sort} <-
@ -353,11 +353,11 @@ defmodule Ash.Actions.Read do
pre_authorization_query <- query,
{:ok, query} <- authorize_query(query, opts),
query_before_pagination <- query,
query <-
Ash.Actions.Read.Calculations.deselect_known_forbidden_fields(
query,
calculations_at_runtime ++ calculations_in_query
),
# query <-
# Ash.Actions.Read.Calculations.deselect_known_forbidden_fields(
# query,
# calculations_at_runtime ++ calculations_in_query
# ),
{:ok, data_layer_calculations} <- hydrate_calculations(query, calculations_in_query),
{:ok, relationship_path_filters} <-
Ash.Filter.relationship_filters(
@ -635,18 +635,18 @@ defmodule Ash.Actions.Read do
defp load(
initial_data,
query,
calculations_at_runtime,
_calculations_at_runtime,
calculations_in_query,
missing_pkeys?,
opts
) do
must_be_reselected = List.wrap(query.select) -- Ash.Resource.Info.primary_key(query.resource)
query =
Ash.Actions.Read.Calculations.deselect_known_forbidden_fields(
query,
calculations_at_runtime ++ calculations_in_query
)
# query =
# Ash.Actions.Read.Calculations.deselect_known_forbidden_fields(
# query,
# calculations_at_runtime ++ calculations_in_query
# )
if missing_pkeys? ||
(Enum.empty?(must_be_reselected) && Enum.empty?(query.aggregates) &&

View file

@ -295,6 +295,9 @@ defmodule Ash.Type do
calc_name: term(),
calc_load: term(),
calc_path: list(atom),
reuse_values?: boolean,
strict_loads?: boolean,
initial_data: term(),
relationship_path: list(atom)
}

View file

@ -4,12 +4,13 @@ defmodule Ash.Test.Resource.CalculationsTest do
alias Ash.Test.Domain, as: Domain
defmodule Calculation do
defmodule Name do
use Ash.Resource.Calculation
@impl true
def load(_, _, _), do: [:first_name, :last_name, :show_last_name]
@impl true
def calculate(records, _, _) do
{:ok,
records
@ -23,7 +24,38 @@ defmodule Ash.Test.Resource.CalculationsTest do
%{
first_name: first_name,
show_last_name: false,
show_last_name: false
} ->
first_name
end)}
end
end
defmodule SelfName do
use Ash.Resource.Calculation
@impl true
def load(_, _, _), do: [self: [:first_name, :last_name, :show_last_name]]
@impl true
def calculate(records, _, _) do
{:ok,
records
|> Enum.map(fn
%{
self: %{
first_name: first_name,
show_last_name: true,
last_name: last_name
}
} ->
"#{first_name} #{last_name}"
%{
self: %{
first_name: first_name,
show_last_name: false
}
} ->
first_name
end)}
@ -53,7 +85,8 @@ defmodule Ash.Test.Resource.CalculationsTest do
end
calculations do
calculate :name, :string, Calculation, public?: true
calculate :name, :string, Name, public?: true
calculate :self_name, :string, SelfName, public?: true
end
policies do
@ -70,16 +103,36 @@ defmodule Ash.Test.Resource.CalculationsTest do
field_policy :name do
authorize_if always()
end
field_policy :self_name do
authorize_if always()
end
end
actions do
defaults [:read, create: [:first_name, :last_name, :show_last_name]]
end
relationships do
has_one :self, __MODULE__ do
source_attribute :id
destination_attribute :id
end
end
end
test "can calculate even if calculate depends on forbidden field" do
Resource.create!(%{first_name: "Homer", last_name: "Simpson", show_last_name: false})
[%{name: "Homer"}] = Resource.read!(%{}, load: [:name])
[%{name: "Homer", show_last_name: %Ash.ForbiddenField{}}] =
Resource.read!(%{}, load: [:name, :show_last_name], authorize?: true)
end
# TODO
# test "can calculate even if calculate depends on forbidden field from a relationship" do
# Resource.create!(%{first_name: "Homer", last_name: "Simpson", show_last_name: false})
# [%{name: "Homer", self: %{show_last_name: %Ash.ForbiddenField{}}}] =
# Resource.read!(%{}, load: [:self_name, self: [:show_last_name]], authorize?: true)
# end
end