Pass actor parameter to member email validation

Extract actor from changeset context and pass it to Ash.read and
Ash.load calls in email uniqueness validation.
This commit is contained in:
Moritz 2026-01-09 05:26:04 +01:00
parent e27bfcb851
commit 3778c5259c

View file

@ -29,7 +29,8 @@ defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
def validate(changeset, _opts, _context) do def validate(changeset, _opts, _context) do
email_changing? = Ash.Changeset.changing_attribute?(changeset, :email) email_changing? = Ash.Changeset.changing_attribute?(changeset, :email)
linked_user_id = get_linked_user_id(changeset.data) actor = Map.get(changeset.context || %{}, :actor)
linked_user_id = get_linked_user_id(changeset.data, actor)
is_linked? = not is_nil(linked_user_id) is_linked? = not is_nil(linked_user_id)
# Only validate if member is already linked AND email is changing # Only validate if member is already linked AND email is changing
@ -38,19 +39,21 @@ defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
if should_validate? do if should_validate? do
new_email = Ash.Changeset.get_attribute(changeset, :email) new_email = Ash.Changeset.get_attribute(changeset, :email)
check_email_uniqueness(new_email, linked_user_id) check_email_uniqueness(new_email, linked_user_id, actor)
else else
:ok :ok
end end
end end
defp check_email_uniqueness(email, exclude_user_id) do defp check_email_uniqueness(email, exclude_user_id, actor) do
query = query =
Mv.Accounts.User Mv.Accounts.User
|> Ash.Query.filter(email == ^email) |> Ash.Query.filter(email == ^email)
|> maybe_exclude_id(exclude_user_id) |> maybe_exclude_id(exclude_user_id)
case Ash.read(query) do opts = if actor, do: [actor: actor], else: []
case Ash.read(query, opts) do
{:ok, []} -> {:ok, []} ->
:ok :ok
@ -65,8 +68,10 @@ defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
defp maybe_exclude_id(query, nil), do: query defp maybe_exclude_id(query, nil), do: query
defp maybe_exclude_id(query, id), do: Ash.Query.filter(query, id != ^id) defp maybe_exclude_id(query, id), do: Ash.Query.filter(query, id != ^id)
defp get_linked_user_id(member_data) do defp get_linked_user_id(member_data, actor) do
case Ash.load(member_data, :user) do opts = if actor, do: [actor: actor], else: []
case Ash.load(member_data, :user, opts) do
{:ok, %{user: %{id: id}}} -> id {:ok, %{user: %{id: id}}} -> id
_ -> nil _ -> nil
end end