defmodule Amur.Config do @moduledoc """ Configuration resolver for OAuth providers. """ @built_ins %{ github: Amur.Providers.GitHub, google: Amur.Providers.Google } def resolve(provider) when is_binary(provider) do provider |> String.to_existing_atom() |> resolve() rescue ArgumentError -> {:error, :unknown_provider} end def resolve(provider) when is_atom(provider) do configured_providers = Application.get_env(:amur, :providers, []) case Keyword.fetch(configured_providers, provider) do {:ok, module} when is_atom(module) -> build_config(module, provider) {:ok, _credentials} -> case Map.fetch(@built_ins, provider) do {:ok, module} -> build_config(module, provider) :error -> {:error, :unknown_provider} end :error -> {:error, :unknown_provider} end end defp build_config(module, provider) do configured_providers = Application.get_env(:amur, :providers, []) base_url = Application.get_env(:amur, :base_url, "") credentials = Keyword.get(configured_providers, provider, []) {scopes, credentials} = Keyword.pop(credentials, :scopes) config = module.base_config() |> Keyword.merge(credentials) |> Keyword.put(:strategy, module.strategy()) |> Keyword.put_new(:redirect_uri, "#{base_url}/auth/#{provider}/callback") |> merge_scopes(scopes) {:ok, {module, config}} end defp merge_scopes(config, nil), do: config defp merge_scopes(config, scopes) do Keyword.update(config, :authorization_params, [scope: scopes], fn params -> Keyword.put(params, :scope, scopes) end) end end