diff --git a/lib/samly/helper.ex b/lib/samly/helper.ex index aa1bf7e..d82ede1 100644 --- a/lib/samly/helper.ex +++ b/lib/samly/helper.ex @@ -6,8 +6,7 @@ defmodule Samly.Helper do @spec get_idp(binary) :: nil | IdpData.t() def get_idp(idp_id) do - idps = Application.get_env(:samly, :identity_providers, %{}) - Map.get(idps, idp_id) + IdpData.store().get(idp_id) end @spec get_metadata_uri(nil | binary, binary) :: nil | charlist diff --git a/lib/samly/idp_data.ex b/lib/samly/idp_data.ex index 0aa662c..c281318 100644 --- a/lib/samly/idp_data.ex +++ b/lib/samly/idp_data.ex @@ -85,6 +85,11 @@ defmodule Samly.IdpData do @type id :: binary() + def store() do + Application.get_env(:samly, Samly.Provider, []) + |> Keyword.get(:idp_data_store, Samly.IdpDataStore.Config) + end + @spec load_providers([map], %{required(id()) => %SpData{}}) :: %{required(id()) => %IdpData{}} | no_return() def load_providers(prov_config, service_providers) do diff --git a/lib/samly/idp_data_store/config.ex b/lib/samly/idp_data_store/config.ex new file mode 100644 index 0000000..dafb297 --- /dev/null +++ b/lib/samly/idp_data_store/config.ex @@ -0,0 +1,35 @@ +defmodule Samly.IdpDataStore.Config do + @moduledoc """ + Reads identity providers data from Application environment (config files). + + This is the default behaviour. To change it, set the following config: + + config :samly, Samly.Provider, + idp_data_store: MyApp.IdpStore + + This implementation only provides `init/2` and `get/1`.any() + `delete/1` and `put/2` will return `:unsupported`. + """ + + @behaviour Samly.IdpDataStore.Store + + @impl true + def init(opts, service_providers) do + identity_providers = + Samly.IdpData.load_providers(opts || [], service_providers) + + Application.put_env(:samly, :identity_providers, identity_providers) + end + + @impl true + def get(idp_id) do + idps = Application.get_env(:samly, :identity_providers, %{}) + Map.get(idps, idp_id) + end + + @impl true + def put(_idp_id, _idp_data), do: :unsupported + + @impl true + def delete(_idp_id), do: :unsupported +end diff --git a/lib/samly/idp_data_store/store.ex b/lib/samly/idp_data_store/store.ex new file mode 100644 index 0000000..090d874 --- /dev/null +++ b/lib/samly/idp_data_store/store.ex @@ -0,0 +1,29 @@ +defmodule Samly.IdpDataStore.Store do + alias Samly.IdpData + alias Samly.SpData + + @doc """ + Called during GenServer init to initializes the store. + + Takes an optional list of `identity_providers` to populate the store from, + and the already-configured map of `service_providers` data. + """ + @callback init([map], %{SpData.id() => SpData.t()}) :: :ok | {:error, any()} + + @doc """ + Fetches the IdpData for the given Id from the store. + """ + @callback get(binary) :: nil | IdpData.t() + + @doc """ + Saves the IdpData for the given Id into the store. + Could be omitted by implementation. In that case, it should return `:unsupported` + """ + @callback put(binary, IdpData.t()) :: :ok | :unsupported | {:error, any()} + + @doc """ + Removes the IdpData for the given Id from the store. + Could be omitted by implementation. In that case, it should return `:unsupported` + """ + @callback delete(binary) :: :ok | :unsupported | {:error, any()} +end diff --git a/lib/samly/provider.ex b/lib/samly/provider.ex index 5c9e032..953bcd8 100644 --- a/lib/samly/provider.ex +++ b/lib/samly/provider.ex @@ -22,7 +22,7 @@ defmodule Samly.Provider do require Logger require Samly.Esaml - alias Samly.{State} + alias Samly.{State, IdpData} @doc false def start_link(gs_opts \\ []) do @@ -58,12 +58,9 @@ defmodule Samly.Provider do Application.put_env(:samly, :idp_id_from, idp_id_from) service_providers = Samly.SpData.load_providers(opts[:service_providers] || []) - - identity_providers = - Samly.IdpData.load_providers(opts[:identity_providers] || [], service_providers) - Application.put_env(:samly, :service_providers, service_providers) - Application.put_env(:samly, :identity_providers, identity_providers) + + :ok = IdpData.store().init(opts[:identity_providers], service_providers) {:ok, %{}} end