mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
263 lines
5.8 KiB
Elixir
263 lines
5.8 KiB
Elixir
defmodule Ash do
|
|
@moduledoc """
|
|
General purpose tools for working with Ash and Ash resources.
|
|
"""
|
|
|
|
for {function, arity} <- Ash.Api.Functions.functions() do
|
|
args = Macro.generate_arguments(arity, __MODULE__)
|
|
|
|
defdelegate unquote(function)(unquote_splicing(args)), to: Ash.Api.GlobalInterface
|
|
|
|
unless function in Ash.Api.Functions.no_opts_functions() do
|
|
args = Macro.generate_arguments(arity + 1, __MODULE__)
|
|
|
|
defdelegate unquote(function)(unquote_splicing(args)), to: Ash.Api.GlobalInterface
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Converts a context map to opts to be passed into an action.
|
|
"""
|
|
def context_to_opts(map, add_to \\ []) when is_map(map) do
|
|
add_to
|
|
|> add_if_present(map, :actor)
|
|
|> add_if_present(map, :authorize?)
|
|
|> add_if_present(map, :tracer)
|
|
end
|
|
|
|
defp add_if_present(opts, map, key) do
|
|
case Map.fetch(map, key) do
|
|
{:ok, value} -> Keyword.put(opts, key, value)
|
|
:error -> opts
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Gets all of the ash context so it can be set into a new process.
|
|
|
|
Use `transfer_context/1` in the new process to set the context.
|
|
"""
|
|
@spec get_context_for_transfer(opts :: Keyword.t()) :: term
|
|
def get_context_for_transfer(opts \\ []) do
|
|
context = Ash.get_context()
|
|
actor = Process.get(:ash_actor)
|
|
authorize? = Process.get(:ash_authorize?)
|
|
tenant = Process.get(:ash_tenant)
|
|
tracer = Process.get(:ash_tracer)
|
|
|
|
tracer_context =
|
|
opts[:tracer]
|
|
|> List.wrap()
|
|
|> Enum.concat(List.wrap(tracer))
|
|
|> Map.new(fn tracer ->
|
|
{tracer, Ash.Tracer.get_span_context(tracer)}
|
|
end)
|
|
|
|
%{
|
|
context: context,
|
|
actor: actor,
|
|
tenant: tenant,
|
|
authorize?: authorize?,
|
|
tracer: tracer,
|
|
tracer_context: tracer_context
|
|
}
|
|
end
|
|
|
|
@spec transfer_context(term, opts :: Keyword.t()) :: :ok
|
|
def transfer_context(
|
|
%{
|
|
context: context,
|
|
actor: actor,
|
|
tenant: tenant,
|
|
authorize?: authorize?,
|
|
tracer: tracer,
|
|
tracer_context: tracer_context
|
|
},
|
|
_opts \\ []
|
|
) do
|
|
case actor do
|
|
{:actor, actor} ->
|
|
Ash.set_actor(actor)
|
|
|
|
_ ->
|
|
:ok
|
|
end
|
|
|
|
case tenant do
|
|
{:tenant, tenant} ->
|
|
Ash.set_tenant(tenant)
|
|
|
|
_ ->
|
|
:ok
|
|
end
|
|
|
|
case authorize? do
|
|
{:authorize?, authorize?} ->
|
|
Ash.set_authorize?(authorize?)
|
|
|
|
_ ->
|
|
:ok
|
|
end
|
|
|
|
Ash.set_tracer(tracer)
|
|
|
|
Enum.each(tracer_context || %{}, fn {tracer, tracer_context} ->
|
|
Ash.Tracer.set_span_context(tracer, tracer_context)
|
|
end)
|
|
|
|
Ash.set_context(context)
|
|
end
|
|
|
|
@doc """
|
|
Sets context into the process dictionary that is used for all changesets and queries.
|
|
|
|
In Ash 3.0, this will be updated to deep merge
|
|
"""
|
|
@spec set_context(map) :: :ok
|
|
def set_context(map) do
|
|
Process.put(:ash_context, map)
|
|
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Deep merges context into the process dictionary that is used for all changesets and queries.
|
|
"""
|
|
@spec merge_context(map) :: :ok
|
|
def merge_context(map) do
|
|
update_context(&Ash.Helpers.deep_merge_maps(&1, map))
|
|
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Updates the context into the process dictionary that is used for all changesets and queries.
|
|
"""
|
|
@spec update_context((map -> map)) :: :ok
|
|
def update_context(fun) do
|
|
context = Process.get(:ash_context, %{})
|
|
set_context(fun.(context))
|
|
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sets actor into the process dictionary that is used for all changesets and queries.
|
|
"""
|
|
@spec set_actor(map) :: :ok
|
|
def set_actor(map) do
|
|
Process.put(:ash_actor, {:actor, map})
|
|
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sets authorize? into the process dictionary that is used for all changesets and queries.
|
|
"""
|
|
@spec set_authorize?(map) :: :ok
|
|
def set_authorize?(map) do
|
|
Process.put(:ash_authorize?, {:authorize?, map})
|
|
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sets the tracer into the process dictionary that will be used to trace requests
|
|
"""
|
|
@spec set_tracer(module | list(module)) :: :ok
|
|
def set_tracer(module) do
|
|
case Process.get(:ash_tracer, module) do
|
|
nil -> Process.put(:ash_tracer, module)
|
|
tracer -> Process.put(:ash_tracer, Enum.uniq(List.wrap(tracer) ++ List.wrap(module)))
|
|
end
|
|
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Removes a tracer from the process dictionary.
|
|
"""
|
|
@spec remove_tracer(module | list(module)) :: :ok
|
|
def remove_tracer(module) do
|
|
case Process.get(:ash_tracer, module) do
|
|
nil -> :ok
|
|
tracer -> Process.put(:ash_tracer, List.wrap(tracer) -- List.wrap(module))
|
|
end
|
|
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gets the current actor from the process dictionary
|
|
"""
|
|
@spec get_actor() :: term()
|
|
def get_actor do
|
|
case Process.get(:ash_actor) do
|
|
{:actor, value} ->
|
|
value
|
|
|
|
_ ->
|
|
nil
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Gets the current tracer
|
|
"""
|
|
@spec get_tracer() :: term()
|
|
def get_tracer do
|
|
case Process.get(:ash_tracer) do
|
|
{:tracer, value} ->
|
|
value
|
|
|
|
_ ->
|
|
Application.get_env(:ash, :tracer)
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Gets the current authorize? from the process dictionary
|
|
"""
|
|
@spec get_authorize?() :: term()
|
|
def get_authorize? do
|
|
case Process.get(:ash_authorize?) do
|
|
{:authorize?, value} ->
|
|
value
|
|
|
|
_ ->
|
|
nil
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Sets tenant into the process dictionary that is used for all changesets and queries.
|
|
"""
|
|
@spec set_tenant(String.t()) :: :ok
|
|
def set_tenant(tenant) do
|
|
Process.put(:ash_tenant, {:tenant, tenant})
|
|
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gets the current tenant from the process dictionary
|
|
"""
|
|
@spec get_tenant() :: term()
|
|
def get_tenant do
|
|
case Process.get(:ash_tenant) do
|
|
{:tenant, value} ->
|
|
value
|
|
|
|
_ ->
|
|
nil
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Gets the current context from the process dictionary
|
|
"""
|
|
@spec get_context() :: term()
|
|
def get_context do
|
|
Process.get(:ash_context, %{}) || %{}
|
|
end
|
|
end
|