Can't get policies to work with AshGraphql
moxley7725:
I have an action,
update_customer_registration
, which requires a
Customer
actor.
My
Customer
policy looks like this:
policies do
policy action(:update_customer_registration) do
authorize_if actor_attribute_equals(:__struct__, __MODULE__)
end
end
This works as expected when using the application’s Ash API directly:
customer
|> Ash.Changeset.new()
|> Ash.Changeset.for_update(:update_customer_registration, %{contact_name: "Test Name"},
actor: customer
)
|> Corp.Ash.Api.update!()
Setting
actor
to
nil
, raises an policy error as expected.
However, it doesn’t seem to work when going through AshGraphql, when the actor is present:
%{
"data" => %{"updateCustomerRegistration" => nil},
"errors" => [%{"code" => "Forbidden", "fields" => [], "locations" => [%{"column" => 5, "line" => 2}], "message" => "forbidden", "path" => ["updateCustomerRegistration"], "short_message" => "forbidden", "vars" => %{}}]
}
I know the actor is being set correctly with
Ash.PlugHelpers.set_actor()
However, when I change the policy to match on any action (
policy always() do
), it works. There seems to be something specific with specifying the action in the policy that doesn’t work with AshGraphql.
_ahey:
Do you have
AshGraphql.Plug
in your :api pipeline?
moxley7725:
Yes, I have it in the pipeline
moxley7725:
And I’m calling
Ash.PlugHelpers.set_actor(conn, session_resource)
,
And I inspected
session_resource
, and it’s the Customer struct.
_ahey:
My pipeline looks like this:
pipeline :api do
plug(:accepts, ["json"])
plug(:load_from_bearer)
plug(HtWeb.AuthPlug) # Here I am calling Ash.PlugHelpers.set_actor
plug(AshGraphql.Plug) # This is needed as well
end
Assuming you have something similar set up, my next steps would be to set the following to see if it offers any more clues.
config :ash, :policies, log_policy_breakdowns: :error
config :ash, :policies, log_successful_policy_breakdowns: :error
moxley7725:
Yes, my pipeline looks similar to that.
moxley7725:
Yes, I’ve set up logging.
moxley7725:
The policy logging doesn’t seem to work when going through AshGraphql through
moxley7725:
When I enable policy logging, it works correctly when I go direct through my Ash API, but when going through GraphQL, this is the only thing that is added to the log output:
[warning] Corp.Customers.Customer.read
moxley7725:
The basic policy integration seems to be working. It just doesn’t work when the policy is specific about which action it applies to.
_ahey:
From memory,
ash_graphql
does need to have permission to also
:read
the thing it’s updating, could that be it?
moxley7725:
Maybe…
moxley7725:
That was it!
moxley7725:
I needed to add the
:read
action to the policy
_ahey:
Great! Glad you got it working. Also I just ran one of my unit tests that uses GQL, and when I turn on the policy logging it does log all the policy logs with breakdown, so i’m not sure why that doesn’t work for you.
moxley7725:
Yeah, I don’t know. That’s strange.
moxley7725:
The other problem I need to solve with this GraphQL query is that it needs to get the Customer from the current actor.
moxley7725:
I was temporarily allowing the request to pass in the Customer ID, but the requirement is that the session token is the only identifying information that will be passed in.
moxley7725:
I’m not sure how to do that.
_ahey:
Does your actor have a relationship to the customer already?
moxley7725:
The actor is the customer
moxley7725:
Do I need to create a new read action to pass the actor along to the
update_customer_registration
action?
_ahey:
You can create a new read action that gets the current actor from session. Here is what I have on my
actor
resource:
read :current_actor do
get? true
manual Ht.Actor.Actions.CurrentActorRead
end
defmodule Ht.Actor.Actions.CurrentActorRead do
use Ash.Resource.ManualRead
@impl true
def read(_, _, _, %{actor: actor}) when not is_nil(actor) do
{:ok, [actor]}
end
def read(_, _, _, _), do: {:ok, []}
end
Then in your graphql definition:
mutations do
update :update do
identity false
read_action :current_actor
end
...
moxley7725:
Nice! I’ll try that.
moxley7725:
Wow, it worked!
moxley7725:
Thanks <@717986162282725387> !
_ahey:
You’re welcome!