mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +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
|
||||
|
||||
query = add_calculation_context(query, actor, authorize?, tenant, tracer)
|
||||
|
||||
query = %{
|
||||
query
|
||||
| api: api,
|
||||
|
@ -424,6 +426,77 @@ defmodule Ash.Actions.Read do
|
|||
[fetch, process]
|
||||
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, []}, true, true, resource),
|
||||
|
|
|
@ -25,6 +25,21 @@ defmodule Ash.Test.CalculationTest do
|
|||
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
|
||||
# An example concatenation calculation, that accepts the delimiter as an argument
|
||||
use Ash.Calculation
|
||||
|
@ -160,6 +175,7 @@ defmodule Ash.Test.CalculationTest do
|
|||
calculate :best_friends_name, :string, BestFriendsName
|
||||
|
||||
calculate :names_of_best_friends_of_me, :string, NamesOfBestFriendsOfMe
|
||||
calculate :name_with_users_name, :string, NameWithUsersName
|
||||
|
||||
calculate :conditional_full_name,
|
||||
:string,
|
||||
|
@ -258,6 +274,14 @@ defmodule Ash.Test.CalculationTest do
|
|||
assert %{slug: "zach daniel123"} = Api.load!(user, [:slug])
|
||||
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
|
||||
full_names =
|
||||
User
|
||||
|
|
Loading…
Reference in a new issue