defmodule GlificWeb.Schema.Middleware.Authorize do
@moduledoc """
Implementing middleware functions to transform errors from Ecto Changeset into a format
consumable and displayable to the API user. This version is specifically for mutations.
"""
import GlificWeb.Gettext
@behaviour Absinthe.Middleware
@doc """
This is the main middleware callback.
It receives an %Absinthe.Resolution{} struct and it needs to return an %Absinthe.Resolution{} struct.
The second argument will be whatever value was passed to the middleware call that setup the middleware.
"""
@spec call(Absinthe.Resolution.t(), term()) :: Absinthe.Resolution.t()
def call(resolution, role) do
with %{roles: roles} <- resolution.context.current_user,
true <- is_valid_role?(roles, role) do
resolution
else
_ ->
resolution
|> Absinthe.Resolution.put_result({:error, dgettext("errors", "Unauthorized")})
end
end
# Check role with hierarchy
@spec is_valid_role?(list(), atom() | list()) :: boolean()
defp is_valid_role?(_, :any), do: true
defp is_valid_role?(roles, :glific_admin), do: is_valid_role?(roles, [:glific_admin])
defp is_valid_role?(roles, :admin), do: is_valid_role?(roles, [:glific_admin, :admin])
defp is_valid_role?(roles, :manager),
do: is_valid_role?(roles, [:glific_admin, :admin, :manager])
defp is_valid_role?(roles, :staff),
do: is_valid_role?(roles, [:glific_admin, :admin, :manager, :staff])
defp is_valid_role?(roles, role) when is_list(role), do: Enum.any?(roles, fn x -> x in role end)
defp is_valid_role?(_, _), do: false
end