ash/test/policy/selecting_test.exs

145 lines
3.3 KiB
Elixir
Raw Normal View History

2024-01-26 05:08:31 +13:00
defmodule Ash.Test.Policy.SelectingTest do
use ExUnit.Case
defmodule Parent do
use Ash.Resource,
data_layer: Ash.DataLayer.Ets,
authorizers: [Ash.Policy.Authorizer]
actions do
defaults [:create, :read, :update, :destroy]
end
ets do
private? true
end
attributes do
uuid_primary_key :id
attribute :owner_id, :string
attribute :guest_id, :string
end
relationships do
has_one :owner_only_resource, Ash.Test.Policy.SelectingTest.OwnerOnlyResource do
source_attribute :id
destination_attribute :parent_id
end
end
policies do
policy always() do
authorize_if expr(owner_id == ^actor(:id) or guest_id == ^actor(:id))
end
end
end
defmodule OwnerOnlyResource do
use Ash.Resource,
data_layer: Ash.DataLayer.Ets,
authorizers: [Ash.Policy.Authorizer]
actions do
defaults [:create, :read, :update, :destroy]
end
ets do
private? true
end
attributes do
uuid_primary_key :id
attribute :parent_id, :uuid
attribute :state, :string
attribute :forbidden_field, :string do
default "forbidden"
end
end
relationships do
belongs_to :owner_resource, Ash.Test.Policy.SelectingTest.Parent do
source_attribute :parent_id
destination_attribute :id
end
end
policies do
bypass actor_attribute_equals(:id, "owner") do
authorize_if always()
end
policy always() do
forbid_if selecting(:forbidden_field)
authorize_if expr(
owner_resource.owner_id == ^actor(:id) and state in ["active", "inactive"]
)
end
end
field_policies do
field_policy [:forbidden_field] do
authorize_if actor_attribute_equals(:id, "owner")
end
field_policy :* do
authorize_if always()
end
end
end
defmodule Api do
use Ash.Api
resources do
resource Parent
resource OwnerOnlyResource
end
end
test "owner can can select forbidden field on related resource" do
parent =
Parent
|> Ash.Changeset.new(%{owner_id: "owner", guest_id: "guest"})
|> Ash.Changeset.for_create(:create)
|> Api.create!()
OwnerOnlyResource
|> Ash.Changeset.new(%{parent_id: parent.id, state: "active"})
|> Ash.Changeset.for_create(:create)
|> Api.create!()
assert {:ok, parent} =
Parent
|> Ash.Query.for_read(:read)
|> Ash.Query.load(:owner_only_resource)
|> Ash.Query.limit(1)
|> Api.read_one(actor: %{id: "owner"})
refute is_nil(parent.owner_only_resource)
end
test "guest is forbidden from querying if selecting a forbidden field on the rel" do
parent =
Parent
|> Ash.Changeset.new(%{owner_id: "owner", guest_id: "guest"})
|> Ash.Changeset.for_create(:create)
|> Api.create!()
OwnerOnlyResource
|> Ash.Changeset.new(%{parent_id: parent.id, state: "active"})
|> Ash.Changeset.for_create(:create)
|> Api.create!()
assert {:error, %Ash.Error.Forbidden{}} =
Parent
|> Ash.Query.for_read(:read)
|> Ash.Query.load(:owner_only_resource)
|> Ash.Query.limit(1)
|> Api.read_one(actor: %{id: "guest"})
end
end