mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 13:33:20 +12:00
improvement: include actor in all calculation context
This commit is contained in:
parent
86d2297018
commit
f060a2bdc4
2 changed files with 97 additions and 0 deletions
|
@ -281,6 +281,8 @@ defmodule Ash.Actions.Read do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
query = add_calculation_context(query, actor, authorize?, tenant, tracer)
|
||||||
|
|
||||||
query = %{
|
query = %{
|
||||||
query
|
query
|
||||||
| api: api,
|
| api: api,
|
||||||
|
@ -424,6 +426,77 @@ defmodule Ash.Actions.Read do
|
||||||
[fetch, process]
|
[fetch, process]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp add_calculation_context(query, actor, authorize?, tenant, tracer) do
|
||||||
|
query =
|
||||||
|
if query.calculations do
|
||||||
|
%{
|
||||||
|
query
|
||||||
|
| calculations:
|
||||||
|
Map.new(query.calculations, fn {name, calc} ->
|
||||||
|
{name,
|
||||||
|
%{
|
||||||
|
calc
|
||||||
|
| context:
|
||||||
|
Map.merge(
|
||||||
|
%{actor: actor, authorize?: authorize?, tenant: tenant, tracer: tracer},
|
||||||
|
calc.context
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
end)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
if query.filter do
|
||||||
|
%{
|
||||||
|
query
|
||||||
|
| filter: add_calc_context_to_filter(query.filter, actor, authorize?, tenant, tracer)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
query
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp add_calc_context_to_filter(filter, actor, authorize?, tenant, tracer) do
|
||||||
|
Ash.Filter.map(filter, fn
|
||||||
|
%Ash.Query.Parent{} = parent ->
|
||||||
|
%{
|
||||||
|
parent
|
||||||
|
| expr: add_calc_context_to_filter(parent.expr, actor, authorize?, tenant, tracer)
|
||||||
|
}
|
||||||
|
|
||||||
|
%Ash.Query.Exists{} = exists ->
|
||||||
|
%{
|
||||||
|
exists
|
||||||
|
| expr: add_calc_context_to_filter(exists.expr, actor, authorize?, tenant, tracer)
|
||||||
|
}
|
||||||
|
|
||||||
|
%Ash.Query.Ref{attribute: %Ash.Resource.Calculation{}} = ref ->
|
||||||
|
raise Ash.Error.Framework.AssumptionFailed,
|
||||||
|
message: "Unhandled calculation in filter statement #{inspect(ref)}"
|
||||||
|
|
||||||
|
%Ash.Query.Ref{attribute: %Ash.Query.Calculation{} = calc} = ref ->
|
||||||
|
%{
|
||||||
|
ref
|
||||||
|
| attribute: %{
|
||||||
|
calc
|
||||||
|
| context:
|
||||||
|
Map.merge(
|
||||||
|
%{
|
||||||
|
actor: actor,
|
||||||
|
authorize?: authorize?,
|
||||||
|
tenant: tenant,
|
||||||
|
tracer: tracer
|
||||||
|
},
|
||||||
|
calc.context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
other ->
|
||||||
|
other
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
defp unwrap_for_get({:ok, [value | _]}, true, _, _resource), do: {:ok, value}
|
defp unwrap_for_get({:ok, [value | _]}, true, _, _resource), do: {:ok, value}
|
||||||
|
|
||||||
defp unwrap_for_get({:ok, []}, true, true, resource),
|
defp unwrap_for_get({:ok, []}, true, true, resource),
|
||||||
|
|
|
@ -25,6 +25,21 @@ defmodule Ash.Test.CalculationTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defmodule NameWithUsersName do
|
||||||
|
# Don't do this kind of thing in real life
|
||||||
|
use Ash.Calculation
|
||||||
|
|
||||||
|
def load(_, _, _) do
|
||||||
|
[:full_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def calculate(records, _opts, %{actor: actor}) do
|
||||||
|
Enum.map(records, fn record ->
|
||||||
|
record.full_name <> " " <> actor.first_name <> " " <> actor.last_name
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defmodule ConcatWithLoad do
|
defmodule ConcatWithLoad do
|
||||||
# An example concatenation calculation, that accepts the delimiter as an argument
|
# An example concatenation calculation, that accepts the delimiter as an argument
|
||||||
use Ash.Calculation
|
use Ash.Calculation
|
||||||
|
@ -160,6 +175,7 @@ defmodule Ash.Test.CalculationTest do
|
||||||
calculate :best_friends_name, :string, BestFriendsName
|
calculate :best_friends_name, :string, BestFriendsName
|
||||||
|
|
||||||
calculate :names_of_best_friends_of_me, :string, NamesOfBestFriendsOfMe
|
calculate :names_of_best_friends_of_me, :string, NamesOfBestFriendsOfMe
|
||||||
|
calculate :name_with_users_name, :string, NameWithUsersName
|
||||||
|
|
||||||
calculate :conditional_full_name,
|
calculate :conditional_full_name,
|
||||||
:string,
|
:string,
|
||||||
|
@ -258,6 +274,14 @@ defmodule Ash.Test.CalculationTest do
|
||||||
assert %{slug: "zach daniel123"} = Api.load!(user, [:slug])
|
assert %{slug: "zach daniel123"} = Api.load!(user, [:slug])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "calculations can access the actor", %{user1: user1, user2: user2} do
|
||||||
|
assert %{
|
||||||
|
name_with_users_name: "zach daniel brian cranston"
|
||||||
|
} =
|
||||||
|
user1
|
||||||
|
|> Api.load!(:name_with_users_name, actor: user2)
|
||||||
|
end
|
||||||
|
|
||||||
test "it loads anything specified by the load callback" do
|
test "it loads anything specified by the load callback" do
|
||||||
full_names =
|
full_names =
|
||||||
User
|
User
|
||||||
|
|
Loading…
Reference in a new issue