defmodule Amur.Controller do
import Plug.Conn
def request(conn, %{"provider" => provider}) do
with {:ok, {_module, config}} <- Amur.Config.resolve(provider),
strategy = Keyword.fetch!(config, :strategy),
{:ok, %{url: url, session_params: session_params}} <- strategy.authorize_url(config) do
conn
|> put_session(:amur_session_params, session_params)
|> redirect(url)
else
{:error, reason} -> handle_failure(conn, reason)
end
end
def callback(conn, %{"provider" => provider} = params) do
session_params = get_session(conn, :amur_session_params)
with {:ok, {module, config}} <- Amur.Config.resolve(provider),
strategy = Keyword.fetch!(config, :strategy),
config = Keyword.put(config, :session_params, session_params),
{:ok, %{user: user, token: _token}} <- strategy.callback(config, params) do
normalized =
user
|> module.normalize_user()
|> Map.put(:provider, provider)
on_success = Application.fetch_env!(:amur, :on_success)
on_success.(conn, normalized)
else
{:error, reason} -> handle_failure(conn, reason)
end
end
def logout(conn, _params) do
conn
|> Amur.logout()
|> redirect("/")
end
defp handle_failure(conn, reason) do
on_failure = Application.get_env(:amur, :on_failure, &Amur.Controller.default_failure/2)
on_failure.(conn, reason)
end
def default_failure(conn, _reason) do
conn
|> redirect("/")
end
defp redirect(conn, to) do
conn
|> put_resp_header("location", to)
|> send_resp(302, "")
|> halt()
end
end