defmodule Ash.Test.Policy.RelatesToActorViaTest do @doc false use ExUnit.Case alias Ash.Test.Domain, as: Domain defmodule Actor do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets actions do default_accept :* defaults [:read, :destroy, create: :*, update: :*] end ets do private? true end attributes do uuid_primary_key :id end calculations do calculate :type, :atom, expr( if is_nil(role_id) do :user else :role end ) do public?(true) end end relationships do belongs_to :user, Ash.Test.Policy.RelatesToActorViaTest.User, public?: true belongs_to :role, Ash.Test.Policy.RelatesToActorViaTest.Role, public?: true end end defmodule User do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets actions do default_accept :* defaults [:read, :destroy, create: :*, update: :*] end ets do private? true end attributes do uuid_primary_key :id end end defmodule Account do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets, authorizers: [Ash.Policy.Authorizer] actions do default_accept :* defaults [:read, :destroy, create: :*, update: :*] end ets do private? true end attributes do uuid_primary_key :id end policies do policy actor_attribute_equals(:type, :user) do authorize_if relates_to_actor_via(:user, field: :user) end policy actor_attribute_equals(:type, :role) do authorize_if relates_to_actor_via(:roles, field: :role) end end relationships do belongs_to :user, Ash.Test.Policy.RelatesToActorViaTest.User do public?(true) end has_many :roles, Ash.Test.Policy.RelatesToActorViaTest.Role do public?(true) end end end defmodule Role do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets actions do default_accept :* defaults [:read, :destroy, create: :*, update: :*] end ets do private? true end attributes do uuid_primary_key :id end relationships do belongs_to :account, Ash.Test.Policy.RelatesToActorViaTest.Account do public?(true) end end end defmodule BadPolicyRelName do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets, authorizers: [Ash.Policy.Authorizer] actions do default_accept :* defaults [:read, :destroy, create: :*, update: :*] end ets do private? true end attributes do uuid_primary_key :id end policies do policy always() do authorize_if relates_to_actor_via(:does_not_exist) end end end defmodule BadPolicyRelPathName do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets, authorizers: [Ash.Policy.Authorizer] actions do default_accept :* defaults [:read, :destroy, create: :*, update: :*] end ets do private? true end attributes do uuid_primary_key :id end policies do policy always() do authorize_if relates_to_actor_via([:does_not_exist, :neither_does_this]) end end end describe "actor_at option" do test "relates_to_actor_via with belongs_to" do user = User |> Ash.Changeset.for_create(:create) |> Ash.create!() account = Account |> Ash.Changeset.for_create(:create) |> Ash.Changeset.manage_relationship(:user, user, type: :append) |> Ash.create!(authorize?: false) actor = Actor |> Ash.Changeset.for_create(:create) |> Ash.Changeset.manage_relationship(:user, user, type: :append) |> Ash.create!(authorize?: false) |> Ash.load!(:type) assert {:ok, _} = Ash.get(Account, account.id, actor: actor) end test "relates_to_actor_via with has_many" do user = User |> Ash.Changeset.for_create(:create) |> Ash.create!() account = Account |> Ash.Changeset.for_create(:create) |> Ash.Changeset.manage_relationship(:user, user, type: :append) |> Ash.create!(authorize?: false) role = Role |> Ash.Changeset.for_create(:create) |> Ash.Changeset.manage_relationship(:account, account, type: :append) |> Ash.create!(authorize?: false) actor = Actor |> Ash.Changeset.for_create(:create) |> Ash.Changeset.manage_relationship(:role, role, type: :append) |> Ash.create!(authorize?: false) |> Ash.load!(:type) assert {:ok, _} = Ash.get(Account, account.id, actor: actor) end test "relates_to_actor_via raises if relationship does not exist" do assert_raise Ash.Error.Unknown, ~r/does_not_exist/, fn -> BadPolicyRelName |> Ash.Changeset.for_create(:create) |> Ash.create!(authorize?: true) end assert_raise Ash.Error.Unknown, ~r/:does_not_exist/, fn -> BadPolicyRelPathName |> Ash.Changeset.for_create(:create) |> Ash.create!(authorize?: true) end end end end