fix validation behaviour

This commit is contained in:
Moritz 2025-10-20 14:38:00 +02:00
parent 001fca1d16
commit 1495ef4592
Signed by: moritz
GPG key ID: 1020A035E5DD0824
3 changed files with 369 additions and 59 deletions

View file

@ -1,26 +1,37 @@
defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
@moduledoc """
Validates that the member's email is not already used by another user.
Allows syncing with linked user (excludes linked user from check).
Only validates when:
- Member is already linked to a user (user != nil) AND email is changing
- Member is being linked to a user (user relationship is changing)
This allows creating members with the same email as unlinked users.
"""
use Ash.Resource.Validation
@impl true
def validate(changeset, _opts, _context) do
case Ash.Changeset.fetch_change(changeset, :email) do
{:ok, new_email} ->
linked_user_id = get_linked_user_id(changeset.data)
check_email_uniqueness(new_email, linked_user_id)
email_changing? = Ash.Changeset.changing_attribute?(changeset, :email)
:error ->
:ok
linked_user_id = get_linked_user_id(changeset.data)
is_linked? = not is_nil(linked_user_id)
# Only validate if member is already linked AND email is changing
# Do NOT validate when member is being linked (email will be overridden from user)
should_validate? = is_linked? and email_changing?
if should_validate? do
new_email = Ash.Changeset.get_attribute(changeset, :email)
check_email_uniqueness(new_email, linked_user_id)
else
:ok
end
end
defp check_email_uniqueness(new_email, exclude_user_id) do
defp check_email_uniqueness(email, exclude_user_id) do
query =
Mv.Accounts.User
|> Ash.Query.filter(email == ^new_email)
|> Ash.Query.filter(email == ^email)
|> maybe_exclude_id(exclude_user_id)
case Ash.read(query) do
@ -28,7 +39,7 @@ defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
:ok
{:ok, _} ->
{:error, field: :email, message: "is already used by another user", value: new_email}
{:error, field: :email, message: "is already used by another user", value: email}
{:error, _} ->
:ok