feat: email uniqueness constraint between user and member

This commit is contained in:
Moritz 2025-10-17 14:21:23 +02:00
parent 5a0a261cd6
commit 39afaf3999
Signed by: moritz
GPG key ID: 1020A035E5DD0824
5 changed files with 329 additions and 6 deletions

View file

@ -66,14 +66,17 @@ defmodule Mv.Accounts.User do
end
actions do
# Default actions kept for framework/tooling integration:
# - :create -> Used by AshAdmin's generated "Create" UI and by generic
# AshPhoenix helpers that assume a default create action.
# It does NOT manage the :member relationship. For admin
# flows that may link an existing member, use :create_user.
# Default actions for framework/tooling integration:
# - :read -> Standard read used across the app and by admin tooling.
# - :destroy-> Standard delete used by admin tooling and maintenance tasks.
defaults [:read, :create, :destroy]
#
# NOTE: :create is INTENTIONALLY excluded from defaults!
# Using a default :create would bypass email-synchronization logic.
# Always use one of these explicit create actions instead:
# - :create_user (for manual user creation with optional member link)
# - :register_with_password (for password-based registration)
# - :register_with_rauthy (for OIDC-based registration)
defaults [:read, :destroy]
# Primary generic update action:
# - Selected by AshAdmin's generated "Edit" UI and generic AshPhoenix
@ -209,6 +212,10 @@ defmodule Mv.Accounts.User do
where: [action_is([:register_with_password, :admin_set_password])],
message: "must have length of at least 8"
# Email uniqueness check for all actions that change the email attribute
# Validates that user email is not already used by another (unlinked) member
validate Mv.Accounts.User.Validations.EmailNotUsedByOtherMember
# Email validation with EctoCommons.EmailValidator (same as Member)
# This ensures consistency between User and Member email validation
validate fn changeset, _ ->