commit eff8673f22099d54eff951d7f582df3518a87011
parent bfaf0d08a8e1d94ab494fb42df046c427f7c8ee0
Author: srfsh <dev@srf.sh>
Date: Mon, 18 Jul 2022 15:02:16 +0300
gql: restructure middlewares and add sign
Diffstat:
6 files changed, 76 insertions(+), 45 deletions(-)
diff --git a/src/zenflows/admin.ex b/src/zenflows/admin.ex
@@ -1,17 +0,0 @@
-defmodule Zenflows.Admin do
-@moduledoc """
-Functionality to authenticate of admin-related calls.
-"""
-
-alias Zenflows.Restroom
-
-def auth(key) do
- with {:ok, key_given} <- Base.decode16(key, case: :lower),
- key_want = Application.fetch_env!(:zenflows, Zenflows.Admin)[:admin_key],
- true <- Restroom.byte_equal?(key_given, key_want) do
- :ok
- else _ ->
- {:error, "you are not authorized"}
- end
-end
-end
diff --git a/src/zenflows/gql/errors.ex b/src/zenflows/gql/errors.ex
@@ -1,24 +0,0 @@
-defmodule Zenflows.GQL.Errors do
-@moduledoc """
-Absinthe middleware for errors (Ecto.Changeset-only, for now).
-"""
-
-alias Ecto.Changeset, as: Chgset
-
-@behaviour Absinthe.Middleware
-
-@impl true
-def call(res, _) do
- %{res | errors: Enum.flat_map(res.errors, &handle/1)}
-end
-
-defp handle(%Chgset{} = cset) do
- cset
- |> Chgset.traverse_errors(&elem(&1, 0))
- |> Enum.map(fn {k, v} -> "#{k}: #{v}" end)
-end
-
-defp handle(error) do
- [error]
-end
-end
diff --git a/src/zenflows/gql/mw/admin.ex b/src/zenflows/gql/mw/admin.ex
@@ -0,0 +1,21 @@
+defmodule Zenflows.GQL.MW.Admin do
+@moduledoc """
+Absinthe middleware to authenticate administrative calls.
+"""
+
+@behaviour Absinthe.Middleware
+
+alias Zenflows.Restroom
+
+@impl true
+def call(res, _opts) do
+ with %{gql_admin: key} <- res.context |> IO.inspect(),
+ {:ok, key_given} <- Base.decode16(key, case: :lower),
+ key_want = Application.fetch_env!(:zenflows, Zenflows.Admin)[:admin_key],
+ true <- Restroom.byte_equal?(key_given, key_want) do
+ res
+ else _ ->
+ Absinthe.Resolution.put_result(res, {:error, "you are not an admin"})
+ end
+end
+end
diff --git a/src/zenflows/gql/mw/errors.ex b/src/zenflows/gql/mw/errors.ex
@@ -0,0 +1,24 @@
+defmodule Zenflows.GQL.MW.Errors do
+@moduledoc """
+Absinthe middleware for errors (Ecto.Changeset-only, for now).
+"""
+
+alias Ecto.Changeset, as: Chgset
+
+@behaviour Absinthe.Middleware
+
+@impl true
+def call(res, _) do
+ %{res | errors: Enum.flat_map(res.errors, &handle/1)}
+end
+
+defp handle(%Chgset{} = cset) do
+ cset
+ |> Chgset.traverse_errors(&elem(&1, 0))
+ |> Enum.map(fn {k, v} -> "#{k}: #{v}" end)
+end
+
+defp handle(error) do
+ [error]
+end
+end
diff --git a/src/zenflows/gql/mw/sign.ex b/src/zenflows/gql/mw/sign.ex
@@ -0,0 +1,25 @@
+defmodule Zenflows.GQL.MW.Sign do
+@moduledoc """
+Absinthe middleware to verify GraphQL calls.
+"""
+
+@behaviour Absinthe.Middleware
+
+@impl true
+def call(res, _opts) do
+ # if this is admin-related call (such as createPerson and importRepos mutations),
+ # skip it (since the `middleware/3` callback in # `Zenflows.GQL.Schema` is
+ # called over and over.
+ if match?(%{gql_admin: _}, res.context) do
+ res
+ else
+ with %{gql_user: user, gql_sign: sign} <- res.context do
+ # TODO: fetch raw query and provide `user`, `sign`, and the raw query to restroom.
+ IO.inspect(res.context, label: "should be authenticated here")
+ res
+ else _ ->
+ Absinthe.Resolution.put_result(res, {:error, "you are not authenticated"})
+ end
+ end
+end
+end
diff --git a/src/zenflows/gql/schema.ex b/src/zenflows/gql/schema.ex
@@ -4,6 +4,7 @@ defmodule Zenflows.GQL.Schema do
use Absinthe.Schema
alias Zenflows.VF
+alias Zenflows.GQL.MW
import_types Absinthe.Type.Custom
import_types Zenflows.GQL.Type
@@ -127,12 +128,13 @@ mutation do
end
@impl true
-def middleware(midware, _field, %{identifier: :mutation}) do
- midware ++ [Zenflows.GQL.Errors]
+def middleware(mw, %{identifier: ident}, _)
+ when ident in ~w[create_person delete_person import_repos]a do
+ mw ++ [MW.Errors, MW.Admin]
end
-def middleware(midware, _field, _obj) do
- midware
+def middleware(mw, _, _) do
+ mw ++ [MW.Errors, MW.Sign]
end
@impl true