defmodule AshAuthentication.Strategy.Password.Plug do @moduledoc """ Plugs for the password strategy. Handles registration, sign-in and password resets. """ alias AshAuthentication.{Info, Strategy, Strategy.Password} alias Plug.Conn import Ash.PlugHelpers, only: [get_actor: 1, get_tenant: 1, get_context: 1] import AshAuthentication.Plug.Helpers, only: [store_authentication_result: 2] @doc "Handle a registration request" @spec register(Conn.t(), Password.t()) :: Conn.t() def register(conn, strategy) do params = subject_params(conn, strategy) opts = opts(conn) result = Strategy.action(strategy, :register, params, opts) store_authentication_result(conn, result) end @doc "Handle a sign-in request" @spec sign_in(Conn.t(), Password.t()) :: Conn.t() def sign_in(conn, strategy) do params = subject_params(conn, strategy) opts = opts(conn) result = Strategy.action(strategy, :sign_in, params, opts) store_authentication_result(conn, result) end @doc "Handle a request to validate a sign in token" @spec sign_in_with_token(Conn.t(), Password.t()) :: Conn.t() def sign_in_with_token(conn, strategy) do params = conn.params opts = opts(conn) result = Strategy.action(strategy, :sign_in_with_token, params, opts) store_authentication_result(conn, result) end @doc "Handle a reset request request" @spec reset_request(Conn.t(), Password.t()) :: Conn.t() def reset_request(conn, strategy) do params = subject_params(conn, strategy) opts = opts(conn) result = Strategy.action(strategy, :reset_request, params, opts) store_authentication_result(conn, result) end @doc "Handle a reset request" @spec reset(Conn.t(), Password.t()) :: Conn.t() def reset(conn, strategy) do get_tenant(conn) params = subject_params(conn, strategy) opts = opts(conn) result = Strategy.action(strategy, :reset, params, opts) store_authentication_result(conn, result) end defp subject_params(conn, strategy) do subject_name = strategy.resource |> Info.authentication_subject_name!() |> to_string() Map.get(conn.params, subject_name, %{}) end defp opts(conn) do [actor: get_actor(conn), tenant: get_tenant(conn), context: get_context(conn)] |> Enum.reject(&is_nil(elem(&1, 1))) end end