Fix email sync (user->member) when changing password and email #380

Merged
moritz merged 1 commit from fix/email_sync into main 2026-01-27 18:08:07 +01:00
2 changed files with 42 additions and 0 deletions
Showing only changes of commit 2b4e1e3963 - Show all commits

View file

@ -194,6 +194,11 @@ defmodule Mv.Accounts.User do
# Use the official Ash Authentication password change # Use the official Ash Authentication password change
change AshAuthentication.Strategy.Password.HashPasswordChange change AshAuthentication.Strategy.Password.HashPasswordChange
# Sync email changes to linked member when email is changed (e.g. form changes both)
change Mv.EmailSync.Changes.SyncUserEmailToMember do
where [changing(:email)]
end
end end
# Action to link an OIDC account to an existing password-only user # Action to link an OIDC account to an existing password-only user

View file

@ -120,6 +120,43 @@ defmodule Mv.Accounts.UserEmailSyncTest do
{:ok, member_after_unlink} = Ash.get(Mv.Membership.Member, member.id, actor: actor) {:ok, member_after_unlink} = Ash.get(Mv.Membership.Member, member.id, actor: actor)
assert member_after_unlink.email == "user@example.com" assert member_after_unlink.email == "user@example.com"
end end
test "admin_set_password with email change syncs to linked member", %{actor: actor} do
# Create member and user linked to it (with password so admin_set_password applies)
{:ok, member} = Membership.create_member(@valid_member_attrs, actor: actor)
{:ok, user} =
Mv.Accounts.User
|> Ash.Changeset.for_create(:register_with_password, %{
email: "user@example.com",
password: "initialpass123"
})
|> Ash.create(actor: actor)
{:ok, user} =
user
|> Ash.Changeset.for_update(:update_user, %{member: %{id: member.id}})
|> Ash.update(actor: actor)
assert user.member_id == member.id
{:ok, m} = Ash.get(Mv.Membership.Member, member.id, actor: actor)
assert m.email == "user@example.com"
# Change both email and password via admin_set_password (e.g. user form "Change Password")
{:ok, updated_user} =
user
|> Ash.Changeset.for_update(:admin_set_password, %{
email: "newemail@example.com",
password: "newpassword123"
})
|> Ash.update(actor: actor)
assert to_string(updated_user.email) == "newemail@example.com"
# Member email must be synced (Option A: SyncUserEmailToMember on admin_set_password)
{:ok, synced_member} = Ash.get(Mv.Membership.Member, member.id, actor: actor)
assert synced_member.email == "newemail@example.com"
end
end end
describe "AshAuthentication compatibility" do describe "AshAuthentication compatibility" do