defmodule FusionAuth do
require Logger
@moduledoc """
The `FusionAuth` module provides functions for building a dynamic HTTP client as well as standardizing the responses returned from the FusionAuth API.
## Examples
iex> FusionAuth.client("http://localhost:9011", "sQ9wwELaI0whHQqyQUxAJmZvVzZqUL-hpfmAmPgbIu8", "6b40f9d6-cfd8-4312-bff8-b082ad45e93c")
%Tesla.Client{
adapter: {Tesla.Adapter.Hackney, :call, [[recv_timeout: 30000]]},
fun: nil,
post: [],
pre: [
{Tesla.Middleware.BaseUrl, :call, ["http://localhost:9011"]},
{Tesla.Middleware.JSON, :call, [[]]},
{Tesla.Middleware.Headers, :call,
[
[
{"Authorization", "sQ9wwELaI0whHQqyQUxAJmZvVzZqUL-hpfmAmPgbIu8"},
{"X-FusionAuth-TenantId", "6b40f9d6-cfd8-4312-bff8-b082ad45e93c"}
]
]}
]
}
"""
@type client() :: Tesla.Client.t()
@type result() :: {:ok, map() | String.t(), Tesla.Env.t()} | {:error, map(), any}
@doc """
Builds a dynamic client for executing HTTP requests to the FusionAuth API using Application variables
specified in `config/{env}.exs`.
```
config :fusion_auth,
api_key: "FUSION_AUTH_API_KEY",
api_url: "FUSION_AUTH_URL",
tenant_id: "FUSION_AUTH_TENANT_ID"
```
"""
@spec client() :: client()
def client(),
do:
client(
Application.get_env(:fusion_auth, :api_url),
Application.get_env(:fusion_auth, :api_key),
Application.get_env(:fusion_auth, :tenant_id)
)
@doc """
Builds a dynamic client for executing HTTP requests to the FusionAuth API based on runtime arguments.
"""
@spec client(String.t(), String.t(), String.t()) :: client()
def client(base_url, api_key, tenant_id) do
middleware = [
{Tesla.Middleware.BaseUrl, base_url},
Tesla.Middleware.JSON,
Tesla.Middleware.Telemetry,
{Tesla.Middleware.Headers,
[
{"Authorization", api_key},
{"X-FusionAuth-TenantId", tenant_id}
]}
]
Tesla.client(middleware, adapter())
end
@doc """
Standardizes the response to be returned from the FusionAuth API request.
"""
def result(_)
@spec result({:ok, Tesla.Env.t()}) :: result()
def result({:ok, %{status: status, body: body} = env}) when status < 300 do
{:ok, body, env}
end
@spec result({:ok, Tesla.Env.t()}) :: result()
def result({:ok, %{status: status, body: body} = env}) when status >= 300 do
Logger.warn("""
FusionAuth request resulted in a status code >= 300.
Env: #{inspect(env)}
""")
{:error, body, env}
end
@spec result({:error, any}) :: result()
def result({:error, any}) do
Logger.error("""
FusionAuth request resulted in an error.
Error: #{inspect(any)}
""")
{:error, %{}, any}
end
@doc false
def adapter do
case Application.get_env(:fusion_auth, :tesla) do
nil ->
{Tesla.Adapter.Hackney, [pool: false, recv_timeout: 30_000]}
tesla ->
tesla[:adapter]
end
end
end