diff --git a/lib/ash/actions/destroy/destroy.ex b/lib/ash/actions/destroy/destroy.ex index 707cfbd9..fdf5dbed 100644 --- a/lib/ash/actions/destroy/destroy.ex +++ b/lib/ash/actions/destroy/destroy.ex @@ -171,6 +171,8 @@ defmodule Ash.Actions.Destroy do {:ok, new_data, _} -> changeset = %{changeset | data: new_data} + changeset = set_tenant(changeset) + if changeset.action.manual do {mod, action_opts} = changeset.action.manual @@ -264,6 +266,20 @@ defmodule Ash.Actions.Destroy do end end + defp set_tenant(changeset) do + if changeset.tenant && + Ash.Resource.Info.multitenancy_strategy(changeset.resource) == :attribute do + attribute = Ash.Resource.Info.multitenancy_attribute(changeset.resource) + + {m, f, a} = Ash.Resource.Info.multitenancy_parse_attribute(changeset.resource) + attribute_value = apply(m, f, [changeset.to_tenant | a]) + + Ash.Changeset.filter(changeset, [{attribute, attribute_value}]) + else + changeset + end + end + defp validate_manual_action_return_result!({:ok, %resource{}} = result, resource, _) do result end diff --git a/lib/ash/actions/update/update.ex b/lib/ash/actions/update/update.ex index fe412c4a..8b676faf 100644 --- a/lib/ash/actions/update/update.ex +++ b/lib/ash/actions/update/update.ex @@ -5,6 +5,7 @@ defmodule Ash.Actions.Update do require Ash.Tracer require Logger + import Ash.Expr @spec run(Ash.Domain.t(), Ash.Resource.record(), Ash.Resource.Actions.action(), Keyword.t()) :: {:ok, Ash.Resource.record(), list(Ash.Notifier.Notification.t())} @@ -631,7 +632,7 @@ defmodule Ash.Actions.Update do {m, f, a} = Ash.Resource.Info.multitenancy_parse_attribute(changeset.resource) attribute_value = apply(m, f, [changeset.to_tenant | a]) - Ash.Changeset.force_change_attribute(changeset, attribute, attribute_value) + Ash.Changeset.filter(changeset, expr(^ref(attribute) == ^attribute_value)) else changeset end diff --git a/lib/ash/changeset/changeset.ex b/lib/ash/changeset/changeset.ex index 68e7bd56..e3e78acf 100644 --- a/lib/ash/changeset/changeset.ex +++ b/lib/ash/changeset/changeset.ex @@ -151,7 +151,7 @@ defmodule Ash.Changeset do %Ash.Filter{expression: nil} -> empty() - true -> + _ -> concat("filter: ", to_doc(changeset.filter, opts)) end diff --git a/test/actions/multitenancy_test.exs b/test/actions/multitenancy_test.exs index 480fdda5..ee636550 100644 --- a/test/actions/multitenancy_test.exs +++ b/test/actions/multitenancy_test.exs @@ -380,6 +380,19 @@ defmodule Ash.Actions.MultitenancyTest do assert User |> Ash.Query.set_tenant(tenant2) |> Ash.read!() == [] end + test "a record for a different tenant cant be updated from the other one", %{ + tenant1: tenant1, + tenant2: tenant2 + } do + assert_raise Ash.Error.Invalid, ~r/Attempted to update stale record/, fn -> + User + |> Ash.Changeset.for_create(:create, %{}, tenant: tenant1) + |> Ash.create!() + |> Ash.Changeset.for_update(:update, %{name: "new name"}, tenant: tenant2) + |> Ash.update!() + end + end + test "a record can be destroyed in a tenant", %{tenant1: tenant1} do User |> Ash.Changeset.for_create(:create, %{}, tenant: tenant1)