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"""
-
-