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 5ffd2b334e
commit 74fe60f768
Signed by: moritz
GPG key ID: 1020A035E5DD0824

View file

@ -29,7 +29,8 @@ defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
def validate(changeset, _opts, _context) do
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)
# 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
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
:ok
end
end
defp check_email_uniqueness(email, exclude_user_id) do
defp check_email_uniqueness(email, exclude_user_id, actor) do
query =
Mv.Accounts.User
|> Ash.Query.filter(email == ^email)
|> 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
@ -65,8 +68,10 @@ defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
defp maybe_exclude_id(query, nil), do: query
defp maybe_exclude_id(query, id), do: Ash.Query.filter(query, id != ^id)
defp get_linked_user_id(member_data) do
case Ash.load(member_data, :user) do
defp get_linked_user_id(member_data, actor) do
opts = if actor, do: [actor: actor], else: []
case Ash.load(member_data, :user, opts) do
{:ok, %{user: %{id: id}}} -> id
_ -> nil
end