fix: enforce multitenancy on aggregates (#952)

The multitenancy attribute was already considered as a filter in
aggregates, but the presence of the tenant was not enforced
This commit is contained in:
Riccardo Binetti 2024-03-27 15:07:53 +01:00 committed by GitHub
parent 4522d7349d
commit 8826c9ec35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 28 additions and 2 deletions

View file

@ -6,7 +6,8 @@ defmodule Ash.Actions.Aggregate do
query = %{query | api: api}
{query, opts} = Ash.Actions.Helpers.add_process_context(query.api, query, opts)
with %{valid?: true} = query <- Ash.Actions.Read.handle_attribute_multitenancy(query) do
with %{valid?: true} = query <- Ash.Actions.Read.handle_attribute_multitenancy(query),
:ok <- Ash.Actions.Read.validate_multitenancy(query) do
aggregates
|> Enum.group_by(fn
%Ash.Query.Aggregate{} = aggregate ->

View file

@ -1155,7 +1155,8 @@ defmodule Ash.Actions.Read do
end
end
defp validate_multitenancy(query) do
@doc false
def validate_multitenancy(query) do
if is_nil(Ash.Resource.Info.multitenancy_strategy(query.resource)) ||
Ash.Resource.Info.multitenancy_global?(query.resource) || query.tenant do
:ok

View file

@ -132,6 +132,18 @@ defmodule Ash.Actions.MultitenancyTest do
assert User |> Ash.Query.set_tenant(tenant2) |> Api.read!() == []
end
test "a record written to one tenant cannot be read from another with aggregate queries", %{
tenant1: tenant1,
tenant2: tenant2
} do
User
|> Ash.Changeset.new()
|> Ash.Changeset.set_tenant(tenant1)
|> Api.create!()
assert User |> Ash.Query.set_tenant(tenant2) |> Api.list!(:name) == []
end
test "a record can be updated in a tenant", %{tenant1: tenant1, tenant2: tenant2} do
User
|> Ash.Changeset.new()
@ -208,5 +220,17 @@ defmodule Ash.Actions.MultitenancyTest do
result = Comment |> Api.read()
assert {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Invalid.TenantRequired{}]}} = result
end
test "an aggregate cannot be used without tenant specified", %{
tenant1: tenant1
} do
Comment
|> Ash.Changeset.new()
|> Ash.Changeset.set_tenant(tenant1)
|> Api.create!()
result = User |> Api.count()
assert {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Invalid.TenantRequired{}]}} = result
end
end
end