Use system actor for email synchronization

Update email sync loader and changes to use system actor instead of user actor.
This ensures email sync always works regardless of user permissions.
This commit is contained in:
Moritz 2026-01-20 22:09:18 +01:00 committed by Simon
parent ffe5faa999
commit 8f06442de9
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2
3 changed files with 27 additions and 39 deletions

View file

@ -41,10 +41,8 @@ defmodule Mv.EmailSync.Changes.SyncMemberEmailToUser do
Ash.Changeset.around_transaction(changeset, fn cs, callback ->
result = callback.(cs)
actor = Map.get(changeset.context, :actor)
with {:ok, member} <- Helpers.extract_record(result),
linked_user <- Loader.get_linked_user(member, actor) do
linked_user <- Loader.get_linked_user(member) do
Helpers.sync_email_to_linked_record(result, linked_user, new_email)
else
_ -> result

View file

@ -33,17 +33,7 @@ defmodule Mv.EmailSync.Changes.SyncUserEmailToMember do
if Map.get(context, :syncing_email, false) do
changeset
else
# Ensure actor is in changeset context - get it from context if available
actor = Map.get(changeset.context, :actor) || Map.get(context, :actor)
changeset_with_actor =
if actor && !Map.has_key?(changeset.context, :actor) do
Ash.Changeset.put_context(changeset, :actor, actor)
else
changeset
end
sync_email(changeset_with_actor)
sync_email(changeset)
end
end
@ -52,7 +42,7 @@ defmodule Mv.EmailSync.Changes.SyncUserEmailToMember do
result = callback.(cs)
with {:ok, record} <- Helpers.extract_record(result),
{:ok, user, member} <- get_user_and_member(record, cs) do
{:ok, user, member} <- get_user_and_member(record) do
# When called from Member-side, we need to update the member in the result
# When called from User-side, we update the linked member in DB only
case record do
@ -71,19 +61,16 @@ defmodule Mv.EmailSync.Changes.SyncUserEmailToMember do
end
# Retrieves user and member - works for both resource types
defp get_user_and_member(%Mv.Accounts.User{} = user, changeset) do
actor = Map.get(changeset.context, :actor)
case Loader.get_linked_member(user, actor) do
# Uses system actor via Loader functions
defp get_user_and_member(%Mv.Accounts.User{} = user) do
case Loader.get_linked_member(user) do
nil -> {:error, :no_member}
member -> {:ok, user, member}
end
end
defp get_user_and_member(%Mv.Membership.Member{} = member, changeset) do
actor = Map.get(changeset.context, :actor)
case Loader.load_linked_user!(member, actor) do
defp get_user_and_member(%Mv.Membership.Member{} = member) do
case Loader.load_linked_user!(member) do
{:ok, user} -> {:ok, user, member}
error -> error
end