Current section

Files

Jump to
btrz_ex_auth_api lib plug verify_providers.ex
Raw

lib/plug/verify_providers.ex

defmodule BtrzAuth.Plug.VerifyProviders do
@moduledoc """
Looks for and validates if there are `provider_ids` in the query params and if they are valids with the account data under `conn.private.account`
saved by `BtrzAuth.Plug.VerifyApiKey` (the order of the plugs is very important!)
This plug will look for `providerId` or `provider_id` or a list of comma separated ids in `providerIds` or
`provider_ids`.
This, like all other Guardian plugs, requires a Guardian pipeline to be setup.
It requires an error handler as `error_handler`.
These can be set either:
1. Upstream on the connection with `plug Guardian.Pipeline`
2. Upstream on the connection with `Guardian.Pipeline.{put_module, put_error_handler, put_key}`
3. Inline with an option of `:module`, `:error_handler`, `:key`
If any provider is invalid, the pipeline will be halted and an error with status 400 will be set in the `conn.resp_body` like this:
```elixir
%{
"status" => 400,
"code" => "INVALID_PROVIDER_ID",
"message" => "Error getting provider"
}
```
### Example
```elixir
plug BtrzAuth.Plug.VerifyProviders
```
"""
import Plug.Conn
alias Guardian.Plug.Pipeline
require Logger
@spec init(Keyword.t()) :: Keyword.t()
def init(opts), do: opts
@spec call(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()
def call(conn, opts) do
Logger.debug("accessing VerifyProviders plug..")
conn
|> get_provider_ids_from_query()
|> validate_provider_ids(conn, Pipeline.fetch_error_handler!(conn, opts))
end
defp get_provider_ids_from_query(conn) do
conn = fetch_query_params(conn)
(conn.query_params["providerIds"] || conn.query_params["provider_ids"] ||
conn.query_params["providerId"] || conn.query_params["provider_id"] || "")
|> String.split(",", trim: true)
|> Enum.map(&String.trim/1)
end
defp is_a_valid_provider?(account, provider_id) do
nil !=
account
|> Map.get("providers", %{})
|> Map.get(provider_id)
end
defp validate_provider_ids([], conn, _error_handler), do: conn
defp validate_provider_ids(provider_ids, %{private: %{account: account}} = conn, error_handler)
when is_map(account) do
if Enum.all?(provider_ids, &is_a_valid_provider?(account, &1)) do
conn
else
respond_error(conn, error_handler)
end
end
defp validate_provider_ids(_provider_id, conn, error_handler),
do: respond_error(conn, error_handler)
defp respond_error(conn, error_handler) do
error_handler
|> apply(:validation_error, [conn])
|> halt()
end
end