Absinthe doesn't answer introspection query from GraphiQL correctly

It’s response is {:ok, %{data: %{}}}.

It does work properly with the following mutations:

mutation CreateUser($username: String!, $password: String!) {
  createUser(username: $username, password: $password) {
    id
  }
}

mutation CreateSession($username: String!, $password: String!) {
  createSession(username: $username, password: $password) {
    token
  }
}

schema/types.ex

defmodule Web.Schema.Types do
  use Absinthe.Schema.Notation

  @desc "a user"
  object :user do
    field :id, :id
    field :username, :string
  end

  @desc "a session"
  object :session do
    field :token, :string
  end
end

resolver/user.ex btw what’s a better way to translate changeset errors?

defmodule Web.Resolver.User do

  def create(_parent, user_params, _info) do
    case Users.insert(user_params) do
      {:ok, user} ->
        {:ok, user}
      {:error, changeset} ->
        {:error, translate(changeset.errors)}
    end
  end

  defp translate(errors) do
    errors
    |> Enum.map(fn {key, {value, _}} -> "#{key} #{value}" end)
    |> Enum.join()
  end
end

resolver/session.ex

defmodule Web.Resolver.Session do
  import Comeonin.Bcrypt, only: [checkpw: 2, dummy_checkpw: 0]

  def create(_parent, %{username: username, password: password}, _info) do
    case verify(username, password) do
      {:ok, token} ->
        {:ok, %{token: token}}
      {:error, msg} ->
        {:error, "Incorrect login credentials"}
    end
  end

  defp verify(username, given_password) do
    user = 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 ->
        {:error, :unauthorized}
      true ->
        dummy_checkpw()
        {:error, :not_found}
    end
  end
end

schema.ex

defmodule Web.Schema do
  use Absinthe.Schema
  alias Web.Resolver.{User, Session}

  import_types Web.Schema.Types


  mutation do
    field :create_user, type: :user do
      arg :username, non_null(:string)
      arg :password, non_null(:string)

      resolve &User.create/3
    end

    field :create_session, type: :session do
      arg :username, non_null(:string)
      arg :password, non_null(:string)

      resolve &Session.create/3
    end
  end
end
2 Likes

I’ve tried adding query macro to the schema.ex and it worked. It seems that Absinthe expects at least one query to exist. Is it a feature of GraphQL or a bug in Absinthe?

1 Like