GraphQL API fails if custom type is not allowed via a field_policy

I noticed that if I ask my graphQL API to return a field that is forbidden, if the field is built-in, it will just return the field as null, all the other fields normally (assuming they are not forbidden as-well) and an error in the errors list telling that this field is forbidden. But, if I try the same with a custom type, then I just get the full result as null:
{
"data": {
"listValidProperties": {
"results": null
}
},
"errors": [
{
"code": "forbidden_field",
"message": "forbidden field",
"path": [
"listValidProperties",
"results",
0,
"price"
],
"fields": [],
"vars": {},
"locations": [
{
"line": 5,
"column": 4
}
],
"short_message": "forbidden field"
}
]
}
{
"data": {
"listValidProperties": {
"results": null
}
},
"errors": [
{
"code": "forbidden_field",
"message": "forbidden field",
"path": [
"listValidProperties",
"results",
0,
"price"
],
"fields": [],
"vars": {},
"locations": [
{
"line": 5,
"column": 4
}
],
"short_message": "forbidden field"
}
]
}
5 Replies
ZachDaniel
ZachDaniel2y ago
What kind of custom type?
Blibs
BlibsOP2y ago
I have some custom types, but all of them have the same issue, here is one of them:
defmodule Marketplace.Ash.Types.PhoneNumber do
@moduledoc false

use Ash.Type

@regex ~r/^\+?((?<ddi>(1))\s?)((?<ddd_1>\d{3})|\((?<ddd_2>\d{3})\))[\s\-]?(?<first_part>\d{3})[\s\-]?(?<second_part>\d{4})$/

@impl true
def storage_type, do: :string

@impl true
def cast_input(nil, _), do: {:ok, nil}

def cast_input(value, _) do
case Regex.named_captures(@regex, value) do
nil ->
{:ok, nil}

groups ->
phone_number =
%{}
|> handle_ddi(groups)
|> handle_ddd(groups)
|> handle_first_part(groups)
|> handle_second_part(groups)
|> combine()

{:ok, phone_number}
end
end

@impl true
def cast_stored(nil, _), do: {:ok, nil}
def cast_stored(value, _), do: {:ok, value}

@impl true
def dump_to_native(nil, _), do: {:ok, nil}
def dump_to_native(value, _) when is_binary(value), do: {:ok, value}

def graphql_input_type, do: :string
def graphql_type, do: :string

defp handle_ddi(map, %{"ddi" => ddi}) when ddi != "", do: Map.put(map, :ddi, ddi)

defp handle_ddd(map, %{"ddd_1" => "", "ddd_2" => ddd}), do: Map.put(map, :ddd, ddd)
defp handle_ddd(map, %{"ddd_1" => ddd, "ddd_2" => ""}), do: Map.put(map, :ddd, ddd)

defp handle_first_part(map, %{"first_part" => first_part}) when first_part != "",
do: Map.put(map, :first_part, first_part)

defp handle_second_part(map, %{"second_part" => second_part}) when second_part != "",
do: Map.put(map, :second_part, second_part)

defp combine(map), do: "+#{map.ddi} (#{map.ddd}) #{map.first_part}-#{map.second_part}"
end
defmodule Marketplace.Ash.Types.PhoneNumber do
@moduledoc false

use Ash.Type

@regex ~r/^\+?((?<ddi>(1))\s?)((?<ddd_1>\d{3})|\((?<ddd_2>\d{3})\))[\s\-]?(?<first_part>\d{3})[\s\-]?(?<second_part>\d{4})$/

@impl true
def storage_type, do: :string

@impl true
def cast_input(nil, _), do: {:ok, nil}

def cast_input(value, _) do
case Regex.named_captures(@regex, value) do
nil ->
{:ok, nil}

groups ->
phone_number =
%{}
|> handle_ddi(groups)
|> handle_ddd(groups)
|> handle_first_part(groups)
|> handle_second_part(groups)
|> combine()

{:ok, phone_number}
end
end

@impl true
def cast_stored(nil, _), do: {:ok, nil}
def cast_stored(value, _), do: {:ok, value}

@impl true
def dump_to_native(nil, _), do: {:ok, nil}
def dump_to_native(value, _) when is_binary(value), do: {:ok, value}

def graphql_input_type, do: :string
def graphql_type, do: :string

defp handle_ddi(map, %{"ddi" => ddi}) when ddi != "", do: Map.put(map, :ddi, ddi)

defp handle_ddd(map, %{"ddd_1" => "", "ddd_2" => ddd}), do: Map.put(map, :ddd, ddd)
defp handle_ddd(map, %{"ddd_1" => ddd, "ddd_2" => ""}), do: Map.put(map, :ddd, ddd)

defp handle_first_part(map, %{"first_part" => first_part}) when first_part != "",
do: Map.put(map, :first_part, first_part)

defp handle_second_part(map, %{"second_part" => second_part}) when second_part != "",
do: Map.put(map, :second_part, second_part)

defp combine(map), do: "+#{map.ddi} (#{map.ddd}) #{map.first_part}-#{map.second_part}"
end
ZachDaniel
ZachDaniel2y ago
That’s actually very strange I don’t see why that would happen Field types don’t have anything to do with field policies
Blibs
BlibsOP2y ago
I will try to create a small reproducible project to help debug this
ZachDaniel
ZachDaniel2y ago
That would be great. A test in the ash_graphql test suite would be even better

Did you find this page helpful?