mitgliederverwaltung/lib/membership/member/changes/unrelate_user_when_argument_nil.ex
Moritz 95472424b1
Some checks reported errors
continuous-integration/drone/push Build was killed
continuous-integration/drone/promote/production Build is passing
Fix member unlink: use User update_user action
UnrelateUserWhenArgumentNil used User :update which only accepts :email.
Switch to :update_user with member: nil so manage_relationship clears member_id.
2026-02-04 14:46:23 +01:00

50 lines
1.7 KiB
Elixir

defmodule Mv.Membership.Member.Changes.UnrelateUserWhenArgumentNil do
@moduledoc """
When :user argument is present and nil/empty on update_member, unrelate the current user.
With on_missing: :ignore, manage_relationship does not unrelate when input is nil/[].
This change handles explicit unlink (user: nil or user: %{}) by updating the linked
User to set member_id = nil. Only runs when the argument key is present (policy
ForbidMemberUserLinkUnlessAdmin ensures only admins can pass :user).
"""
use Ash.Resource.Change
@spec change(Ash.Changeset.t(), keyword(), Ash.Resource.Change.context()) :: Ash.Changeset.t()
def change(changeset, _opts, _context) do
if unlink_requested?(changeset) do
unrelate_current_user(changeset)
else
changeset
end
end
defp unlink_requested?(changeset) do
args = changeset.arguments || %{}
if Map.has_key?(args, :user) or Map.has_key?(args, "user") do
user_arg = Ash.Changeset.get_argument(changeset, :user)
user_arg == nil or (is_map(user_arg) and map_size(user_arg) == 0)
else
false
end
end
defp unrelate_current_user(changeset) do
member = changeset.data
actor = Map.get(changeset.context || %{}, :actor)
case Ash.load(member, :user, domain: Mv.Membership, authorize?: false) do
{:ok, %{user: user}} when not is_nil(user) ->
# User's :update action only accepts [:email]; use :update_user so
# manage_relationship(:member, ..., on_missing: :unrelate) runs and clears member_id.
user
|> Ash.Changeset.for_update(:update_user, %{member: nil}, domain: Mv.Accounts)
|> Ash.update(domain: Mv.Accounts, actor: actor, authorize?: false)
changeset
_ ->
changeset
end
end
end