Current section

Files

Jump to
goth lib goth config.ex
Raw

lib/goth/config.ex

defmodule Goth.Config do
@moduledoc """
`Goth.Config` is a `GenServer` that holds the current configuration.
This configuration is loaded from one of three places:
1. a JSON string passed in via your application's config
2. a ENV variable passed in via your application's config
3. The Application Default Credentials, as defined by
https://developers.google.com/identity/protocols/application-default-credentials
The `Goth.Config` server exists mostly for other parts of your application
(or other libraries) to pull the current configuration state,
via `Goth.Config.get/1`. If necessary, you can also set config values via
`Goth.Config.set/2`
"""
use GenServer
alias Goth.Client
def start_link do
GenServer.start_link(__MODULE__, :ok, [name: __MODULE__])
end
def init(:ok) do
config = from_json() ||
from_config() ||
from_creds_file() ||
from_gcloud_adc() ||
from_metadata()
project_id = determine_project_id(config)
{:ok, Map.put(config, "project_id", project_id)}
end
defp from_json() do
case Application.get_env(:goth, :json) do
nil -> nil
{:system, var} -> decode_json(System.get_env(var))
json -> decode_json(json)
end
end
defp from_config() do
Application.get_env(:goth, :config)
end
defp from_creds_file() do
case System.get_env("GOOGLE_APPLICATION_CREDENTIALS") do
nil -> nil
filename -> filename |> File.read!() |> decode_json()
end
end
# Search the well-known path for application default credentials provided
# by the gcloud sdk. Note there are different paths for unix and windows.
defp from_gcloud_adc() do
config_root_dir = Application.get_env(:goth, :config_root_dir)
path_root = if config_root_dir == nil do
case :os.type() do
{:win32, _} ->
System.get_env("APPDATA") || ""
{:unix, _} ->
home_dir = System.get_env("HOME") || ""
Path.join([home_dir, ".config"])
end
else
config_root_dir
end
path = Path.join([path_root, "gcloud", "application_default_credentials.json"])
if File.regular?(path) do
path |> File.read!() |> decode_json()
else
nil
end
end
defp from_metadata() do
%{"token_source" => :metadata}
end
defp determine_project_id(config) do
Application.get_env(:goth, :project_id) ||
System.get_env("GOOGLE_CLOUD_PROJECT") ||
System.get_env("GCLOUD_PROJECT") ||
System.get_env("DEVSHELL_PROJECT_ID") ||
config["project_id"] ||
Client.retrieve_metadata_project()
end
# Decodes JSON (if configured) and sets oauth token source
defp decode_json(json) do
json
|> Poison.decode!
|> set_token_source
end
defp set_token_source(map = %{"private_key" => _}) do
Map.put(map, "token_source", :oauth_jwt)
end
defp set_token_source(map = %{"refresh_token" => _, "client_id" => _, "client_secret" => _}) do
Map.put(map, "token_source", :oauth_refresh)
end
def set(key, value) when is_atom(key), do: key |> to_string |> set(value)
def set(key, value) do
GenServer.call(__MODULE__, {:set, key, value})
end
def get(key) when is_atom(key), do: key |> to_string |> get
def get(key) do
GenServer.call(__MODULE__, {:get, key})
end
def handle_call({:set, key, value}, _from, keys) do
{:reply, :ok, Map.put(keys, key, value)}
end
def handle_call({:get, key}, _from, keys) do
{:reply, Map.fetch(keys, key), keys}
end
end