I’ve tried the union operator but whenever I supply an invalid username/password pair so that to get ValidationError
I keep getting this error instead
[error] #PID<0.726.0> running Web.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /api
** (exit) an exception was raised:
** (CaseClauseError) no case clause matching: %Absinthe.Type.List{of_type: :validation_error}
(absinthe) lib/absinthe/type/union.ex:91: Absinthe.Type.Union.resolve_type/3
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:389: Absinthe.Phase.Document.Execution.Resolution.passes_type_condition?/4
(elixir) lib/enum.ex:2718: Enum.do_all?/2
(elixir) lib/enum.ex:814: anonymous fn/3 in Enum.filter/2
(elixir) lib/enum.ex:1755: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir) lib/enum.ex:814: Enum.filter/2
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:174: Absinthe.Phase.Document.Execution.Resolution.resolve_fields/4
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:133: Absinthe.Phase.Document.Execution.Resolution.walk_result/5
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:186: Absinthe.Phase.Document.Execution.Resolution.do_resolve_fields/5
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:133: Absinthe.Phase.Document.Execution.Resolution.walk_result/5
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:101: Absinthe.Phase.Document.Execution.Resolution.perform_resolution/3
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:78: Absinthe.Phase.Document.Execution.Resolution.resolve_current/3
(absinthe) lib/absinthe/pipeline.ex:204: Absinthe.Pipeline.run_phase/3
(absinthe_plug) lib/absinthe/plug.ex:158: Absinthe.Plug.execute/2
(absinthe_plug) lib/absinthe/plug.ex:125: Absinthe.Plug.call/2
(phoenix) lib/phoenix/router/route.ex:161: Phoenix.Router.Route.forward/4
(phoenix) lib/phoenix/router.ex:277: Phoenix.Router.__call__/1
(web) lib/web/endpoint.ex:1: Web.Endpoint.plug_builder_call/2
(web) lib/plug/debugger.ex:123: Web.Endpoint."call (overridable 3)"/2
(web) lib/web/endpoint.ex:1: Web.Endpoint.call/2
Here’s my schema.ex
union :validation_result do
types [list_of(:validation_error), :session]
resolve_type fn
%{token: _, user: _}, _ ->
:session
_, _ ->
list_of(:validation_error)
end
end
mutation do
field :sign_up, type: :validation_result do
arg :username, non_null(:string)
arg :password, non_null(:string)
resolve &Session.sign_up/3
end
field :sign_in, type: :validation_result do
arg :username, non_null(:string)
arg :password, non_null(:string)
resolve &Session.sign_in/3
end
end
schema/types.ex
object :user do
field :id, :id
field :username, :string
end
object :session do
field :token, :string
field :user, :user
end
object :validation_error do
field :field, :string
field :message, :string
end
and resolver/session.ex
defmodule Web.Resolver.Session do
import Comeonin.Bcrypt, only: [checkpw: 2, dummy_checkpw: 0]
import Web.ErrorHelpers, only: [translate_error: 1]
def sign_in(_parent, %{username: username, password: password}, _info) do
case verify(username, password) do
{:ok, token, user} ->
{:ok, %{token: token, user: user}}
{:error, _msg} ->
{:ok, [%{message: "incorrect login credentials", field: :password}]}
end
end
def sign_up(_parent, user_params, _info) do
case Store.Users.insert(user_params) do
{:ok, user} ->
token = Phoenix.Token.sign(Web.Endpoint, "user", user.id)
{:ok, %{token: token, user: user}}
{:error, changeset} ->
{:ok, translate(changeset.errors)}
end
end
defp verify(username, given_password) do
user = Store.Users.get_by(username: username)
cond do
user && checkpw(given_password, user.password_hash) ->
token = Phoenix.Token.sign(Web.Endpoint, "user", user.id)
{:ok, token, user}
user ->
{:error, :unauthorized}
true ->
dummy_checkpw()
{:error, :not_found}
end
end
defp translate(errors) do
Enum.map(errors, fn {field, error} ->
%{field: field, message: translate_error(error)}
end)
end
end
and the document I send
mutation SignUp($username: String!, $password: String!) {
signUp(username: $username, password: $password) {
... on Session {
token
user {
id
username
}
}
... on ValidationError {
field
message
}
}
}