Current section
Files
Jump to
Current section
Files
lib/supabase/auth/schemas/mfa/challenge_params.ex
defmodule Supabase.Auth.Schemas.MFA.ChallengeParams do
@moduledoc false
use Ecto.Schema
import Ecto.Changeset
@type totp :: %{}
@type phone :: %{channel: :sms | :whatsapp}
@type webauthn :: %{
webauthn: %{
rp_id: String.t(),
rp_origins: [String.t()] | nil
}
}
@type t :: totp | phone | webauthn
@phone_types %{channel: Ecto.ParameterizedType.init(Ecto.Enum, values: [:sms, :whatsapp])}
@webauthn_types %{webauthn: :map}
@webauthn_nested_types %{rp_id: :string, rp_origins: {:array, :string}}
@spec parse(phone) :: {:ok, phone} | {:error, Ecto.Changeset.t()}
@spec parse(webauthn) :: {:ok, webauthn} | {:error, Ecto.Changeset.t()}
@spec parse(totp) :: {:ok, totp} | {:error, Ecto.Changeset.t()}
def parse(%{channel: _} = attrs) do
{%{}, @phone_types}
|> cast(attrs, [:channel])
|> validate_required([:channel])
|> validate_inclusion(:channel, [:sms, :whatsapp])
|> apply_action(:parse)
end
def parse(%{webauthn: _} = attrs) do
{%{}, @webauthn_types}
|> cast(attrs, [:webauthn])
|> validate_required([:webauthn])
|> webauthn_changeset()
|> apply_action(:parse)
end
def parse(%{} = attrs) when map_size(attrs) == 0 do
{:ok, attrs}
end
defp webauthn_changeset(%Ecto.Changeset{valid?: false} = changeset), do: changeset
defp webauthn_changeset(%Ecto.Changeset{} = changeset) do
if webauthn = get_change(changeset, :webauthn) do
{:ok, result} =
{%{}, @webauthn_nested_types}
|> cast(webauthn, Map.keys(@webauthn_nested_types))
|> validate_required([:rp_id])
|> apply_action(:parse)
put_change(changeset, :webauthn, result)
else
changeset
end
end
end