From 5d48ffd0519c332c9a96152b5ef7b7f502591d02 Mon Sep 17 00:00:00 2001 From: Alexandre de Souza Date: Tue, 28 Feb 2023 10:55:52 -0300 Subject: [PATCH] Remove entire app secrets implementation (#1734) --- lib/livebook/application.ex | 9 +++++ lib/livebook/ecto_types/secret_origin.ex | 8 +--- lib/livebook/hubs.ex | 8 +++- lib/livebook/hubs/enterprise.ex | 2 +- lib/livebook/hubs/provider.ex | 3 +- lib/livebook/secrets/secret.ex | 2 +- lib/livebook_web/live/session_live.ex | 13 ++++-- .../live/session_live/secrets_component.ex | 28 +++++++------ .../session_live/secrets_list_component.ex | 40 ++++++------------- .../web_socket/client_connection_test.exs | 2 +- .../session_live/secrets_component_test.exs | 24 ++++++++++- test/livebook_web/live/session_live_test.exs | 20 ++++++---- test/support/factory.ex | 5 ++- test/support/session_helpers.ex | 3 +- 14 files changed, 100 insertions(+), 67 deletions(-) diff --git a/lib/livebook/application.ex b/lib/livebook/application.ex index 7a05faa6b..afc79d841 100644 --- a/lib/livebook/application.ex +++ b/lib/livebook/application.ex @@ -55,6 +55,7 @@ defmodule Livebook.Application do display_startup_info() insert_personal_hub() Livebook.Hubs.connect_hubs() + update_app_secrets_origin() result {:error, error} -> @@ -213,6 +214,14 @@ defmodule Livebook.Application do end end + # TODO: Remove in the future + defp update_app_secrets_origin do + for %{origin: :app} = secret <- Livebook.Secrets.get_secrets() do + {:ok, secret} = Livebook.Secrets.update_secret(secret, %{origin: {:hub, "personal-hub"}}) + Livebook.Secrets.set_secret(secret) + end + end + defp iframe_server_specs() do server? = Phoenix.Endpoint.server?(:livebook, LivebookWeb.Endpoint) port = Livebook.Config.iframe_port() diff --git a/lib/livebook/ecto_types/secret_origin.ex b/lib/livebook/ecto_types/secret_origin.ex index 2f38afd43..249063498 100644 --- a/lib/livebook/ecto_types/secret_origin.ex +++ b/lib/livebook/ecto_types/secret_origin.ex @@ -3,7 +3,7 @@ defmodule Livebook.EctoTypes.SecretOrigin do use Ecto.Type - @type t :: nil | :session | :startup | :app | {:hub, String.t()} + @type t :: nil | :session | :startup | {:hub, String.t()} @impl true def type, do: :string @@ -13,16 +13,14 @@ defmodule Livebook.EctoTypes.SecretOrigin do @impl true def dump(:session), do: {:ok, "session"} - def dump(:app), do: {:ok, "app"} def dump(:startup), do: {:ok, "startup"} 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}), do: {:hub, id} + def cast({:hub, id}), do: {:ok, {:hub, id}} def cast(encoded) when is_binary(encoded) do case decode(encoded) do @@ -38,7 +36,6 @@ defmodule Livebook.EctoTypes.SecretOrigin do """ @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}" @@ -47,7 +44,6 @@ defmodule Livebook.EctoTypes.SecretOrigin do """ @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 diff --git a/lib/livebook/hubs.ex b/lib/livebook/hubs.ex index c3456cec7..abdf14354 100644 --- a/lib/livebook/hubs.ex +++ b/lib/livebook/hubs.ex @@ -200,7 +200,7 @@ defmodule Livebook.Hubs do """ @spec get_secrets() :: list(Secret.t()) def get_secrets do - for hub <- get_hubs([:secrets]), + for hub <- get_hubs([:list_secrets]), secret <- Provider.get_secrets(hub), do: secret end @@ -238,7 +238,11 @@ defmodule Livebook.Hubs do Provider.delete_secret(hub, secret) end - defp capability?(hub, capabilities) do + @doc """ + Checks the hub capability for given hub. + """ + @spec capability?(Provider.t(), list(atom())) :: boolean() + def capability?(hub, capabilities) do capabilities -- Provider.capabilities(hub) == [] end end diff --git a/lib/livebook/hubs/enterprise.ex b/lib/livebook/hubs/enterprise.ex index eb2583c03..a30c40650 100644 --- a/lib/livebook/hubs/enterprise.ex +++ b/lib/livebook/hubs/enterprise.ex @@ -145,7 +145,7 @@ defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Enterprise do EnterpriseClient.stop(enterprise.id) end - def capabilities(_enterprise), do: ~w(connect secrets list_secrets create_secret)a + def capabilities(_enterprise), do: ~w(connect list_secrets create_secret)a def get_secrets(enterprise) do EnterpriseClient.get_secrets(enterprise.id) diff --git a/lib/livebook/hubs/provider.ex b/lib/livebook/hubs/provider.ex index cbaf67314..dc6886e71 100644 --- a/lib/livebook/hubs/provider.ex +++ b/lib/livebook/hubs/provider.ex @@ -4,8 +4,7 @@ defprotocol Livebook.Hubs.Provider do alias Livebook.Secrets.Secret @type t :: Livebook.Hubs.Enterprise.t() | Livebook.Hubs.Fly.t() | Livebook.Hubs.Personal.t() - @type capability :: - :connect | :secrets | :list_secrets | :create_secret | :update_secret | :delete_secret + @type capability :: :connect | :list_secrets | :create_secret | :update_secret | :delete_secret @type capabilities :: list(capability()) @type changeset_errors :: %{required(:errors) => list({String.t(), {Stirng.t(), list()}})} diff --git a/lib/livebook/secrets/secret.ex b/lib/livebook/secrets/secret.ex index fd9349f8e..9328d9f59 100644 --- a/lib/livebook/secrets/secret.ex +++ b/lib/livebook/secrets/secret.ex @@ -14,7 +14,7 @@ defmodule Livebook.Secrets.Secret do @primary_key {:name, :string, autogenerate: false} embedded_schema do field :value, :string - field :origin, SecretOrigin, default: :app + field :origin, SecretOrigin end def changeset(secret, attrs \\ %{}) do diff --git a/lib/livebook_web/live/session_live.ex b/lib/livebook_web/live/session_live.ex index d31244715..1922d4a24 100644 --- a/lib/livebook_web/live/session_live.ex +++ b/lib/livebook_web/live/session_live.ex @@ -1188,14 +1188,21 @@ defmodule LivebookWeb.SessionLive do {:noreply, socket |> assign(saved_secrets: get_saved_secrets()) - |> put_flash(:info, "A new secret has been created on your Livebook Enterprise")} + |> put_flash(:info, "A new secret has been created on your Livebook Hub")} end def handle_info({:secret_updated, %{origin: {:hub, _id}}}, socket) do {:noreply, socket |> assign(saved_secrets: get_saved_secrets()) - |> put_flash(:info, "An existing secret has been updated on your Livebook Enterprise")} + |> put_flash(:info, "An existing secret has been updated on your Livebook Hub")} + end + + def handle_info({:secret_deleted, %{origin: {:hub, _id}}}, socket) do + {:noreply, + socket + |> assign(saved_secrets: get_saved_secrets()) + |> put_flash(:info, "An existing secret has been deleted on your Livebook Hub")} end def handle_info(:hubs_changed, socket) do @@ -2040,7 +2047,7 @@ defmodule LivebookWeb.SessionLive do end defp get_saved_secrets do - Enum.sort(Hubs.get_secrets() ++ Secrets.get_secrets()) + Enum.sort(Hubs.get_secrets()) end defp app_status_color(nil), do: "bg-gray-400" diff --git a/lib/livebook_web/live/session_live/secrets_component.ex b/lib/livebook_web/live/session_live/secrets_component.ex index 77216d055..b4c09b71c 100644 --- a/lib/livebook_web/live/session_live/secrets_component.ex +++ b/lib/livebook_web/live/session_live/secrets_component.ex @@ -9,7 +9,7 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do @impl true def mount(socket) do - {:ok, assign(socket, title: title(socket), hubs: Livebook.Hubs.get_hubs([:secrets]))} + {:ok, assign(socket, title: title(socket), hubs: Livebook.Hubs.get_hubs([:create_secret]))} end @impl true @@ -62,7 +62,7 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do :for={secret <- @saved_secrets} secret_name={secret.name} secret_origin={secret.origin} - stored={stored(secret)} + stored={stored(secret, @hubs)} active={false} target={@myself} /> @@ -113,7 +113,7 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do value={SecretOrigin.encode(f[:origin].value)} label="Storage" options={ - [{"session", "only this session"}, {"app", "in the Livebook app"}] ++ + [{"session", "only this session"}] ++ if Livebook.Config.feature_flag_enabled?(:hub) do for hub <- @hubs, do: {"hub-#{hub.id}", "in #{hub.hub_emoji} #{hub.hub_name}"} else @@ -188,7 +188,7 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do icon="error-warning-fill" class="align-middle text-2xl flex text-gray-100 rounded-lg py-2" /> - <%= if @secret.origin in [:app, :startup] do %> + <%= if @secret.origin == :startup do %> There is a secret named <%= @secret.name %> @@ -218,9 +218,6 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do """ end - defp stored(%{origin: {:hub, _}}), do: "Hub" - defp stored(%{origin: origin}) when origin in [:app, :startup], do: "Livebook" - @impl true def handle_event("save", %{"secret" => attrs}, socket) do with {:ok, secret} <- Secrets.update_secret(%Secret{}, attrs), @@ -278,11 +275,6 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do Session.set_secret(socket.assigns.session.pid, secret) end - defp set_secret(socket, %Secret{origin: :app} = secret) do - Secrets.set_secret(secret) - Session.set_secret(socket.assigns.session.pid, secret) - end - defp set_secret(socket, %Secret{origin: {:hub, id}} = secret) when is_binary(id) do with :ok <- Hubs.create_secret(secret) do Session.set_secret(socket.assigns.session.pid, secret) @@ -294,4 +286,16 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do if secret, do: Livebook.Session.set_secret(socket.assigns.session.pid, secret) end + + defp stored(%{origin: {:hub, id}}, hubs), do: stored(id, hubs) + defp stored(%{origin: :startup}, hubs), do: stored("personal-hub", hubs) + + defp stored(id, hubs) do + hub = fetch_hub!(id, hubs) + "#{hub.hub_emoji} #{hub.hub_name}" + end + + defp fetch_hub!(id, hubs) do + Enum.find(hubs, &(&1.id == id)) || raise "unknown hub id: #{id}" + end end diff --git a/lib/livebook_web/live/session_live/secrets_list_component.ex b/lib/livebook_web/live/session_live/secrets_list_component.ex index 276d6167c..288f81003 100644 --- a/lib/livebook_web/live/session_live/secrets_list_component.ex +++ b/lib/livebook_web/live/session_live/secrets_list_component.ex @@ -67,30 +67,6 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do New secret -
-

- App secrets -

- - <%= if @saved_secrets == [] do %> - No secrets stored in Livebook so far - <% else %> - Toggle to share with this session - <% end %> - -
- -
- <.secrets_item - :for={secret when secret.origin in [:app, :startup] <- @saved_secrets} - secret={secret} - prefix={to_string(secret.origin)} - data_secrets={@secrets} - hubs={@hubs} - myself={@myself} - /> -
-

Hub secrets @@ -106,9 +82,9 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do
<.secrets_item - :for={%{origin: {:hub, id}} = secret <- @saved_secrets} + :for={secret <- @saved_secrets} secret={secret} - prefix={"hub-#{id}"} + prefix={prefix(secret)} data_secrets={@secrets} hubs={@hubs} myself={@myself} @@ -162,7 +138,7 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do <%= @secret.value %>