mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
fix: fix broken default behavior around managing relationships.
Read more: https://github.com/ash-project/ash/issues/469
This commit is contained in:
parent
05e4f2f2de
commit
b515bb258b
4 changed files with 89 additions and 4 deletions
|
@ -1,5 +1,7 @@
|
||||||
import Config
|
import Config
|
||||||
|
|
||||||
|
config :ash, :use_all_identities_in_manage_relationship?, false
|
||||||
|
|
||||||
if Mix.env() == :dev do
|
if Mix.env() == :dev do
|
||||||
config :git_ops,
|
config :git_ops,
|
||||||
mix_project: Ash.MixProject,
|
mix_project: Ash.MixProject,
|
||||||
|
|
|
@ -6,6 +6,25 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
|
|
||||||
require Ash.Query
|
require Ash.Query
|
||||||
|
|
||||||
|
@use_all_identities_in_manage_relationship Application.compile_env(
|
||||||
|
:ash,
|
||||||
|
:use_all_identities_in_manage_relationship?
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_nil(@use_all_identities_in_manage_relationship) do
|
||||||
|
IO.warn("""
|
||||||
|
* IMPORTANT *
|
||||||
|
|
||||||
|
The configuration `use_all_identities_in_manage_relationship` was not set. It is defaulting to `true`.
|
||||||
|
|
||||||
|
This configuration must now be manually set, and it should be set to `false`.
|
||||||
|
|
||||||
|
If you are currently using `manage_relationship`, please read https://github.com/ash-project/ash/issues/469
|
||||||
|
""")
|
||||||
|
|
||||||
|
@use_all_identities_in_manage_relationship true
|
||||||
|
end
|
||||||
|
|
||||||
def load(_api, created, %{relationships: rels}, _) when rels == %{},
|
def load(_api, created, %{relationships: rels}, _) when rels == %{},
|
||||||
do: {:ok, created}
|
do: {:ok, created}
|
||||||
|
|
||||||
|
@ -531,7 +550,7 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
end
|
end
|
||||||
|
|
||||||
def pkeys(relationship, opts) do
|
def pkeys(relationship, opts) do
|
||||||
identity_priority = opts[:identity_priority] || []
|
identity_priority = opts[:identity_priority] || opts[:use_identities]
|
||||||
use_identities = opts[:use_identities]
|
use_identities = opts[:use_identities]
|
||||||
|
|
||||||
identity_priority =
|
identity_priority =
|
||||||
|
@ -549,8 +568,12 @@ defmodule Ash.Actions.ManagedRelationships do
|
||||||
end)
|
end)
|
||||||
|
|
||||||
unprioritized_identities =
|
unprioritized_identities =
|
||||||
|
if @use_all_identities_in_manage_relationship do
|
||||||
relationship.destination
|
relationship.destination
|
||||||
|> Ash.Resource.Info.identities()
|
|> Ash.Resource.Info.identities()
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|> then(fn identities ->
|
|> then(fn identities ->
|
||||||
if use_identities do
|
if use_identities do
|
||||||
Enum.filter(identities, &(&1.name in use_identities))
|
Enum.filter(identities, &(&1.name in use_identities))
|
||||||
|
|
|
@ -78,7 +78,7 @@ defmodule Ash.Api.Dsl do
|
||||||
"""
|
"""
|
||||||
resources do
|
resources do
|
||||||
registry MyApp.Registry
|
registry MyApp.Registry
|
||||||
end
|
en
|
||||||
"""
|
"""
|
||||||
],
|
],
|
||||||
links: [],
|
links: [],
|
||||||
|
|
|
@ -19,6 +19,66 @@ defmodule Ash.Api.Info do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_manage_relationships_with_identity_not_configured(otp_app) do
|
||||||
|
otp_app
|
||||||
|
|> Application.get_env(:ash_apis, [])
|
||||||
|
|> Enum.flat_map(&Ash.Api.Info.resources/1)
|
||||||
|
|> Enum.flat_map(fn resource ->
|
||||||
|
resource
|
||||||
|
|> Ash.Resource.Info.actions()
|
||||||
|
|> Enum.flat_map(fn action ->
|
||||||
|
action
|
||||||
|
|> Map.get(:changes, [])
|
||||||
|
|> Enum.flat_map(fn
|
||||||
|
%{change: {Ash.Resource.Change.ManageRelationship, opts}} ->
|
||||||
|
related = Ash.Resource.Info.related(resource, opts[:relationship])
|
||||||
|
identities = Ash.Resource.Info.identities(related)
|
||||||
|
argument = Enum.find(action.arguments, &(&1.name == opts[:argument]))
|
||||||
|
|
||||||
|
if argument && map_type?(argument.type) && !Enum.empty?(identities) do
|
||||||
|
[{resource, action.name, opts[:argument]}]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|> Enum.group_by(
|
||||||
|
fn {resource, action, _} ->
|
||||||
|
{resource, action}
|
||||||
|
end,
|
||||||
|
&elem(&1, 2)
|
||||||
|
)
|
||||||
|
|> Enum.map_join("\n\n", fn {{resource, action}, args} ->
|
||||||
|
"#{inspect(resource)}.#{action}:\n" <>
|
||||||
|
Enum.map_join(args, "\n", fn arg ->
|
||||||
|
"* #{arg}"
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp map_type?({:array, type}) do
|
||||||
|
map_type?(type)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp map_type?(:map), do: true
|
||||||
|
defp map_type?(Ash.Type.Map), do: true
|
||||||
|
|
||||||
|
defp map_type?(type) do
|
||||||
|
if Ash.Type.embedded_type?(type) do
|
||||||
|
if is_atom(type) && :erlang.function_exported(type, :admin_map_type?, 0) do
|
||||||
|
type.admin_map_type?()
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets the resources of an Api module. Can be used at compile time.
|
Gets the resources of an Api module. Can be used at compile time.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue