diff --git a/lib/livebook/ecto_types/hex_color.ex b/lib/livebook/ecto_types/hex_color.ex index 398ac4aed..0c0cb27cd 100644 --- a/lib/livebook/ecto_types/hex_color.ex +++ b/lib/livebook/ecto_types/hex_color.ex @@ -2,11 +2,17 @@ defmodule Livebook.EctoTypes.HexColor do @moduledoc false use Ecto.Type + @impl true def type, do: :string + @impl true def load(value), do: {:ok, value} + + @impl true + def dump(value), do: {:ok, value} + @impl true def cast(value) do if valid?(value) do {:ok, value} diff --git a/lib/livebook/ecto_types/secret_origin.ex b/lib/livebook/ecto_types/secret_origin.ex index 06a03f5a8..2f38afd43 100644 --- a/lib/livebook/ecto_types/secret_origin.ex +++ b/lib/livebook/ecto_types/secret_origin.ex @@ -1,45 +1,54 @@ defmodule Livebook.EctoTypes.SecretOrigin do @moduledoc false + use Ecto.Type @type t :: nil | :session | :startup | :app | {:hub, String.t()} + @impl true def type, do: :string - def load("session"), do: {:ok, :session} - def load("app"), do: {:ok, :app} - def load("startup"), do: {:ok, :startup} - - def load("hub-" <> id) do - if hub_secret?(id), - do: {:ok, {:hub, id}}, - else: :error - end - - def load(_), do: :error + @impl true + def load(origin), do: decode(origin) + @impl true def dump(:session), do: {:ok, "session"} def dump(:app), do: {:ok, "app"} def dump(:startup), do: {:ok, "startup"} - - def dump({:hub, id}) when is_binary(id) do - if hub_secret?(id), do: {:ok, "hub-#{id}"}, else: :error - end - + def dump({:hub, id}), do: {:ok, "hub-#{id}"} def dump(_), do: :error + @impl true def cast(:session), do: {:ok, :session} def cast(:app), do: {:ok, :app} def cast(:startup), do: {:ok, :startup} - def cast({:hub, id}) when is_binary(id), do: cast(id) + def cast({:hub, id}), do: {:hub, id} - def cast(id) when is_binary(id) do - if hub_secret?(id), - do: {:ok, {:hub, id}}, - else: {:error, message: "does not exists"} + def cast(encoded) when is_binary(encoded) do + case decode(encoded) do + {:ok, origin} -> {:ok, origin} + :error -> {:error, message: "is invalid"} + end end def cast(_), do: {:error, message: "is invalid"} - defdelegate hub_secret?(id), to: Livebook.Hubs, as: :hub_exists? + @doc """ + Encodes origin into string representation. + """ + @spec encode(t()) :: String.t() + def encode(:session), do: "session" + def encode(:app), do: "app" + def encode(:startup), do: "startup" + def encode({:hub, id}), do: "hub-#{id}" + + @doc """ + Decodes origin from string representation. + """ + @spec decode(String.t()) :: {:ok, t()} | :error + def decode("session"), do: {:ok, :session} + def decode("app"), do: {:ok, :app} + def decode("startup"), do: {:ok, :startup} + def decode("hub-" <> id), do: {:ok, {:hub, id}} + def decode(_other), do: :error end diff --git a/lib/livebook/secrets.ex b/lib/livebook/secrets.ex index c260a474b..b7af82c19 100644 --- a/lib/livebook/secrets.ex +++ b/lib/livebook/secrets.ex @@ -1,8 +1,6 @@ defmodule Livebook.Secrets do @moduledoc false - import Ecto.Changeset, only: [apply_action: 2, add_error: 3, get_field: 2, put_change: 3] - alias Livebook.Storage alias Livebook.Secrets.Secret @@ -49,41 +47,22 @@ defmodule Livebook.Secrets do Storage.fetch(:secrets, id) != :error end - @doc """ - Validates a secret map and either returns a tuple. - - ## Examples - - iex> validate_secret(%{name: "FOO", value: "bar", origin: "session"}) - {:ok, %Secret{}} - - iex> validate_secret(%{}) - {:error, %Ecto.Changeset{}} - - """ - @spec validate_secret(map()) :: {:ok, Secret.t()} | {:error, Ecto.Changeset.t()} - def validate_secret(attrs) do - %Secret{} - |> Secret.changeset(attrs) - |> apply_action(:validate) - end - @doc """ Returns an `%Ecto.Changeset{}` for tracking secret changes. """ @spec change_secret(Secret.t(), map()) :: Ecto.Changeset.t() def change_secret(%Secret{} = secret, attrs) do - secret - |> Secret.changeset(attrs) - |> Map.replace!(:action, :validate) - |> normalize_origin() + Secret.changeset(secret, attrs) end - defp normalize_origin(changeset) do - case get_field(changeset, :origin) do - {:hub, id} -> put_change(changeset, :origin, "hub-#{id}") - _ -> changeset - end + @doc """ + Updates secret with the given changes. + """ + @spec update_secret(Secret.t(), map()) :: {:ok, Secret.t()} | {:error, Ecto.Changeset.t()} + def update_secret(%Secret{} = secret, attrs) do + secret + |> Secret.changeset(attrs) + |> Ecto.Changeset.apply_action(:update) end @doc """ @@ -94,11 +73,11 @@ defmodule Livebook.Secrets do def add_secret_error(%Secret{} = secret, field, message) do secret |> change_secret(%{}) - |> add_error(field, message) + |> Ecto.Changeset.add_error(field, message) end def add_secret_error(%Ecto.Changeset{} = changeset, field, message) do - add_error(changeset, field, message) + Ecto.Changeset.add_error(changeset, field, message) end @doc """ diff --git a/lib/livebook_web/components/form_components.ex b/lib/livebook_web/components/form_components.ex index 9d63b80b9..8f6f20947 100644 --- a/lib/livebook_web/components/form_components.ex +++ b/lib/livebook_web/components/form_components.ex @@ -224,10 +224,11 @@ defmodule LivebookWeb.FormComponents do ~H"""
-
-