Does anyone know if Manual Read actions are incompatible with policies.
I can’t get this policy to deny anything
test "" do
# Arrange
...
# Act & Assert
# via Query.for_read
assert {:error, _} =
MyApp.ManualUser
|> Ash.Query.for_read(:get_manual_user, %{id: id}, actor: user |> build_actor(), authorize?: true)
|> Ash.read()
end
defmodule MyApp.ManualUser do
use Ash.Resource,
domain: MyApp.Core,
authorizers: [Ash.Policy.Authorizer]
attributes do
uuid_primary_key :id
attribute :user_number, :string, public?: true
end
actions do
read :get_user_number do
primary? true
argument :id, :string, allow_nil?: false
manual Ht.Actions.GetUserNumber
end
end
policies do
policy always() do
forbid_if always()
end
end
end
I can confirm that this is not an issue when using a Generic Action. This works fine with the policy:
action :get_user_number, :map do
argument :user_number, :string, allow_nil?: false
run fn input, _ ->
number = # ...
{:ok, [number]}
end
end
assert {:error, _} =
MyApp.ManualUser
|> Ash.ActionInput.for_action(:get_user_number, %{id: id})
|> Ash.run_action()
Running on latest commit from main branch of Ash:
# mix.exs
...
# Ash main branches from github
{:ash, github: "ash-project/ash", override: true},
{:ash_authentication,
github: "team-alembic/ash_authentication", override: true},
{:ash_authentication_phoenix,
github: "team-alembic/ash_authentication_phoenix"},
{:ash_graphql, github: "ash-project/ash_graphql", override: true},
{:ash_paper_trail, github: "ash-project/ash_paper_trail"},
{:ash_phoenix, github: "ash-project/ash_phoenix", override: true},
{:ash_postgres, github: "ash-project/ash_postgres", override: true},
{:spark, github: "ash-project/spark", override: true},
...
The problem is that for read actions the default behavior of queries is to add a filter to the query
Your manual read action is likely ignoring the provided query, which is how the policies are being applied.
The default access_type
of a policy is :filter
which allows it to be applied this way. You could change your policy’s access_type
to :strict
policies do
policy always() do
access_type :strict
forbid_if always()
end
end