phuochau
10/22/2017 - 1:08 PM

Custom Plug for Absinthe with multiple schema based on permission

Custom Plug for Absinthe with multiple schema based on permission

defmodule ApiWeb.GraphQL.Plug do
  @moduledoc false
  import Plug.Conn
  alias ApiWeb.GraphQL.Schema

  @guest_schema Absinthe.Plug.init schema: Schema.Guest
  @admin_schema Absinthe.Plug.init schema: Schema.Admin
  @user_schema Absinthe.Plug.init schema: Schema.User

  def init(opts), do: opts
  def call(conn, _opts) do
    # check permission at here
    case build_context(conn) do
      {:ok, context} ->
        put_private(conn, :absinthe, %{context: context})
        %{type: type} = context
        case type do
          :admin -> Absinthe.Plug.call(conn, @admin_schema)
          :user -> Absinthe.Plug.call(conn, @user_schema)
        end
      {:error, reason} ->
        conn
        |> send_resp(403, reason)
        |> halt()
      [] ->
        Absinthe.Plug.call(conn, @guest_schema)
      _ ->
        conn
        |> send_resp(400, "Bad Request")
        |> halt()
    end
  end

  def build_context(conn) do
    with ["Bearer " <> auth_base64] <- get_req_header(conn, "authorization"),
         hash <- Base.decode64!(auth_base64),
         [type, identity, token] <- String.split(hash, ":")
    do
      case type do
        "admin" -> check_admin(identity, token)
        "user" -> check_user(identity, token)
      end
    else
      err -> []
    end
  end

  defp check_admin(identity, token) do
    ## check admin user
  end

  defp check_user(identity, token) do
    # check user
  end

end