zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

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:
Dsrc/zenflows/admin.ex | 17-----------------
Dsrc/zenflows/gql/errors.ex | 24------------------------
Asrc/zenflows/gql/mw/admin.ex | 21+++++++++++++++++++++
Asrc/zenflows/gql/mw/errors.ex | 24++++++++++++++++++++++++
Asrc/zenflows/gql/mw/sign.ex | 25+++++++++++++++++++++++++
Msrc/zenflows/gql/schema.ex | 10++++++----
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