diff --git a/lib/ash/data_layer/ets/ets.ex b/lib/ash/data_layer/ets/ets.ex index 2985baa4..76b070a6 100644 --- a/lib/ash/data_layer/ets/ets.ex +++ b/lib/ash/data_layer/ets/ets.ex @@ -391,10 +391,18 @@ defmodule Ash.DataLayer.Ets do kind: :count, relationship_path: relationship_path, query: query, + authorization_filter: authorization_filter, name: name, load: load }, {:ok, record} -> + query = + if authorization_filter do + Ash.Query.do_filter(query, authorization_filter) + else + query + end + with {:ok, loaded_record} <- api.load(record, relationship_path), related <- Ash.Filter.Runtime.get_related(loaded_record, relationship_path), {:ok, filtered} <- diff --git a/lib/ash/filter/filter.ex b/lib/ash/filter/filter.ex index c8e62f57..2423ed7f 100644 --- a/lib/ash/filter/filter.ex +++ b/lib/ash/filter/filter.ex @@ -1225,7 +1225,7 @@ defmodule Ash.Filter do case do_run_other_data_layer_filters( expr, api, - Ash.Resource.Info.related(resource, path), + Ash.Resource.Info.related(resource, at_path ++ path), data ) do {:ok, new_nested} -> diff --git a/lib/ash/filter/runtime.ex b/lib/ash/filter/runtime.ex index e15c25c8..a47e2386 100644 --- a/lib/ash/filter/runtime.ex +++ b/lib/ash/filter/runtime.ex @@ -168,7 +168,7 @@ defmodule Ash.Filter.Runtime do end defp flatten_many_to_many(record, rel, values, rest) do - full_flattened = Enum.map(values, &flatten_relationships(&1, [rest])) + full_flattened = Enum.map(values, &flatten_relationships(&1, [rest])) |> List.flatten() Enum.map(full_flattened, fn value -> record diff --git a/lib/ash/policy/check/relates_to_actor_via.ex b/lib/ash/policy/check/relates_to_actor_via.ex index b684b393..47588f27 100644 --- a/lib/ash/policy/check/relates_to_actor_via.ex +++ b/lib/ash/policy/check/relates_to_actor_via.ex @@ -21,3 +21,71 @@ defmodule Ash.Policy.Check.RelatesToActorVia do Ash.Expr.expr(exists(^opts[:relationship_path], ^Enum.map(pkey, &{&1, {:_actor, &1}}))) end end + +# defmodule Ash.Policy.Check.RelatesToActorVia do +# @moduledoc false +# use Ash.Policy.FilterCheck + +# require Ash.Expr + +# @impl true +# def describe(opts) do +# path = Enum.join(opts[:relationship_path], ".") +# "record.#{path} == actor" +# end + +# @impl true +# def filter(opts) do +# {last_relationship, to_many?} = relationship_info(opts[:resource], opts[:relationship_path]) + +# pkey = +# last_relationship.destination +# |> Ash.Resource.Info.primary_key() + +# if to_many? do +# Ash.Expr.expr(exists(^opts[:relationship_path], ^Enum.map(pkey, &{&1, {:_actor, &1}}))) +# else +# put_in_path(opts[:relationship_path], Enum.map(pkey, &{&1, {:_actor, &1}})) +# end +# end + +# @impl true +# def reject(opts) do +# {last_relationship, to_many?} = relationship_info(opts[:resource], opts[:relationship_path]) + +# pkey = +# last_relationship.destination +# |> Ash.Resource.Info.primary_key() + +# if to_many? do +# Ash.Expr.expr(not exists(^opts[:relationship_path], ^Enum.map(pkey, &{&1, {:_actor, &1}}))) +# else +# [ +# or: [ +# [not: filter(opts)], +# [put_in_path(opts[:relationship_path], Enum.map(pkey, &{:is_nil, &1}))] +# ] +# ] +# end +# end + +# defp relationship_info(resource, path, to_many? \\ false) + +# defp relationship_info(resource, [rel], to_many?) do +# rel = Ash.Resource.Info.relationship(resource, rel) +# {rel, to_many? || rel.cardinality == :many} +# end + +# defp relationship_info(resource, [rel | rest], to_many?) do +# rel = Ash.Resource.Info.relationship(resource, rel) +# relationship_info(rel.destination, rest, to_many? || rel.cardinality == :many) +# end + +# defp put_in_path([], value) do +# value +# end + +# defp put_in_path([key | rest], value) do +# [{key, put_in_path(rest, value)}] +# end +# end diff --git a/test/policy/complex_test.exs b/test/policy/complex_test.exs index d033c4f0..9b1836e6 100644 --- a/test/policy/complex_test.exs +++ b/test/policy/complex_test.exs @@ -90,4 +90,11 @@ defmodule Ash.Test.Policy.ComplexTest do |> Ash.Query.filter(comments.text == "comment by a friend of a friend on my post") |> Api.read!(actor: me) end + + test "aggregates can be loaded", %{me: me} do + Post + |> Ash.Query.load(:count_of_comments) + |> Ash.Query.filter(count_of_comments == 10) + |> Api.read!(actor: me) + end end diff --git a/test/support/policy_complex/resources/post.ex b/test/support/policy_complex/resources/post.ex index da3aa289..173d805d 100644 --- a/test/support/policy_complex/resources/post.ex +++ b/test/support/policy_complex/resources/post.ex @@ -43,6 +43,10 @@ defmodule Ash.Test.Support.PolicyComplex.Post do end end + aggregates do + count :count_of_comments, :comments + end + code_interface do define_for Ash.Test.Support.PolicyComplex.Api define :create, args: [:text]