mirror of
https://github.com/livebook-dev/livebook.git
synced 2024-09-20 18:15:56 +08:00
Require cookie for connecting to an attached node (#245)
* Require cookie for connecting to an attached node * Fix modals sizing
This commit is contained in:
parent
5fede30764
commit
3694576244
|
@ -9,23 +9,27 @@ defmodule Livebook.Runtime.Attached do
|
|||
# The node can be an ordinary Elixir runtime,
|
||||
# a Mix project shell, a running release or anything else.
|
||||
|
||||
defstruct [:node]
|
||||
defstruct [:node, :cookie]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
node: node()
|
||||
node: node(),
|
||||
cookie: atom()
|
||||
}
|
||||
|
||||
@doc """
|
||||
Checks if the given node is available for use and initializes
|
||||
it with Livebook-specific modules and processes.
|
||||
"""
|
||||
@spec init(node()) :: {:ok, t()} | {:error, :unreachable | :already_in_use}
|
||||
def init(node) do
|
||||
@spec init(node(), atom()) :: {:ok, t()} | {:error, :unreachable | :already_in_use}
|
||||
def init(node, cookie \\ Node.get_cookie()) do
|
||||
# Set cookie for connecting to this specific node
|
||||
Node.set_cookie(node, cookie)
|
||||
|
||||
case Node.ping(node) do
|
||||
:pong ->
|
||||
case Livebook.Runtime.ErlDist.initialize(node) do
|
||||
:ok ->
|
||||
{:ok, %__MODULE__{node: node}}
|
||||
{:ok, %__MODULE__{node: node, cookie: cookie}}
|
||||
|
||||
{:error, :already_in_use} ->
|
||||
{:error, :already_in_use}
|
||||
|
|
|
@ -11,7 +11,16 @@ defmodule LivebookWeb.Helpers do
|
|||
"""
|
||||
def live_modal(socket, component, opts) do
|
||||
path = Keyword.fetch!(opts, :return_to)
|
||||
modal_opts = [id: :modal, return_to: path, component: component, opts: opts]
|
||||
modal_class = Keyword.get(opts, :modal_class)
|
||||
|
||||
modal_opts = [
|
||||
id: :modal,
|
||||
return_to: path,
|
||||
modal_class: modal_class,
|
||||
component: component,
|
||||
opts: opts
|
||||
]
|
||||
|
||||
live_component(socket, LivebookWeb.ModalComponent, modal_opts)
|
||||
end
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ defmodule LivebookWeb.HomeLive do
|
|||
<%= if @live_action == :close_session do %>
|
||||
<%= live_modal @socket, LivebookWeb.HomeLive.CloseSessionComponent,
|
||||
id: :close_session_modal,
|
||||
modal_class: "w-full max-w-xl",
|
||||
return_to: Routes.home_path(@socket, :page),
|
||||
session_summary: @session_summary %>
|
||||
<% end %>
|
||||
|
@ -109,6 +110,7 @@ defmodule LivebookWeb.HomeLive do
|
|||
<%= if @live_action == :import do %>
|
||||
<%= live_modal @socket, LivebookWeb.HomeLive.ImportComponent,
|
||||
id: :import_modal,
|
||||
modal_class: "w-full max-w-xl",
|
||||
return_to: Routes.home_path(@socket, :page),
|
||||
tab: @tab %>
|
||||
<% end %>
|
||||
|
|
|
@ -6,7 +6,7 @@ defmodule LivebookWeb.HomeLive.CloseSessionComponent do
|
|||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div class="p-6 pb-4 max-w-xl w-screen flex flex-col space-y-8">
|
||||
<div class="p-6 pb-4 flex flex-col space-y-8">
|
||||
<h3 class="text-2xl font-semibold text-gray-800">
|
||||
Close session
|
||||
</h3>
|
||||
|
|
|
@ -4,7 +4,7 @@ defmodule LivebookWeb.HomeLive.ImportComponent do
|
|||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div class="p-6 pb-4 max-w-xl w-screen flex flex-col space-y-8">
|
||||
<div class="p-6 pb-4 flex flex-col space-y-8">
|
||||
<h3 class="text-2xl font-semibold text-gray-800">
|
||||
Import notebook
|
||||
</h3>
|
||||
|
|
|
@ -19,7 +19,7 @@ defmodule LivebookWeb.ModalComponent do
|
|||
phx-page-loading></div>
|
||||
|
||||
<!-- Modal box -->
|
||||
<div class="relative max-h-full overflow-y-auto bg-white rounded-lg shadow-xl"
|
||||
<div class="relative max-h-full overflow-y-auto bg-white rounded-lg shadow-xl <%= @modal_class %>"
|
||||
role="dialog"
|
||||
aria-modal="true">
|
||||
|
||||
|
|
|
@ -173,6 +173,7 @@ defmodule LivebookWeb.SessionLive do
|
|||
<%= if @live_action == :runtime_settings do %>
|
||||
<%= live_modal @socket, LivebookWeb.SessionLive.RuntimeComponent,
|
||||
id: :runtime_settings_modal,
|
||||
modal_class: "w-full max-w-4xl",
|
||||
return_to: Routes.session_path(@socket, :page, @session_id),
|
||||
session_id: @session_id,
|
||||
runtime: @data_view.runtime %>
|
||||
|
@ -181,6 +182,7 @@ defmodule LivebookWeb.SessionLive do
|
|||
<%= if @live_action == :file_settings do %>
|
||||
<%= live_modal @socket, LivebookWeb.SessionLive.PersistenceComponent,
|
||||
id: :runtime_settings_modal,
|
||||
modal_class: "w-full max-w-4xl",
|
||||
return_to: Routes.session_path(@socket, :page, @session_id),
|
||||
session_id: @session_id,
|
||||
current_path: @data_view.path,
|
||||
|
@ -190,6 +192,7 @@ defmodule LivebookWeb.SessionLive do
|
|||
<%= if @live_action == :shortcuts do %>
|
||||
<%= live_modal @socket, LivebookWeb.SessionLive.ShortcutsComponent,
|
||||
id: :shortcuts_modal,
|
||||
modal_class: "w-full max-w-5xl",
|
||||
platform: @platform,
|
||||
return_to: Routes.session_path(@socket, :page, @session_id) %>
|
||||
<% end %>
|
||||
|
@ -197,6 +200,7 @@ defmodule LivebookWeb.SessionLive do
|
|||
<%= if @live_action == :cell_settings do %>
|
||||
<%= live_modal @socket, LivebookWeb.SessionLive.CellSettingsComponent,
|
||||
id: :cell_settings_modal,
|
||||
modal_class: "w-full max-w-xl",
|
||||
session_id: @session_id,
|
||||
cell: @cell,
|
||||
return_to: Routes.session_path(@socket, :page, @session_id) %>
|
||||
|
@ -205,6 +209,7 @@ defmodule LivebookWeb.SessionLive do
|
|||
<%= if @live_action == :cell_upload do %>
|
||||
<%= live_modal @socket, LivebookWeb.SessionLive.CellUploadComponent,
|
||||
id: :cell_upload_modal,
|
||||
modal_class: "w-full max-w-xl",
|
||||
session_id: @session_id,
|
||||
cell: @cell,
|
||||
uploads: @uploads,
|
||||
|
|
|
@ -9,7 +9,7 @@ defmodule LivebookWeb.SessionLive.AttachedLive do
|
|||
assign(socket,
|
||||
session_id: session_id,
|
||||
error_message: nil,
|
||||
name: initial_name(current_runtime)
|
||||
data: initial_data(current_runtime)
|
||||
)}
|
||||
end
|
||||
|
||||
|
@ -27,45 +27,68 @@ defmodule LivebookWeb.SessionLive.AttachedLive do
|
|||
and evaluate code in the context of that node.
|
||||
Thanks to this approach you can work with
|
||||
an arbitrary Elixir runtime.
|
||||
Make sure to give the node a name, for example:
|
||||
Make sure to give the node a name and a cookie, for example:
|
||||
</p>
|
||||
<div class="text-gray-700 markdown">
|
||||
<%= if Livebook.Config.shortnames? do %>
|
||||
<pre><code>iex --sname test</code></pre>
|
||||
<pre><code>iex --sname test --cookie mycookie</code></pre>
|
||||
<% else %>
|
||||
<pre><code>iex --name test@127.0.0.1</code></pre>
|
||||
<pre><code>iex --name test@127.0.0.1 --cookie mycookie</code></pre>
|
||||
<% end %>
|
||||
</div>
|
||||
<p class="text-gray-700">
|
||||
Then enter the name of the node below:
|
||||
Then enter the connection information below:
|
||||
</p>
|
||||
<%= f = form_for :node, "#", phx_submit: "init" %>
|
||||
<%= text_input f, :name, value: @name, class: "input",
|
||||
placeholder: if(Livebook.Config.shortnames?, do: "test", else: "test@127.0.0.1") %>
|
||||
|
||||
<%= submit "Connect", class: "mt-5 button button-blue" %>
|
||||
<%= f = form_for :data, "#", phx_submit: "init", phx_change: "validate" %>
|
||||
<div class="flex flex-col space-y-4">
|
||||
<div>
|
||||
<div class="mb-0.5 text-sm text-gray-800 font-medium">Name</div>
|
||||
<%= text_input f, :name, value: @data["name"], class: "input",
|
||||
placeholder: if(Livebook.Config.shortnames?, do: "test", else: "test@127.0.0.1") %>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-0.5 text-sm text-gray-800 font-medium">Cookie</div>
|
||||
<%= text_input f, :cookie, value: @data["cookie"], class: "input", placeholder: "mycookie" %>
|
||||
</div>
|
||||
</div>
|
||||
<%= submit "Connect", class: "mt-5 button button-blue", disabled: not data_valid?(@data) %>
|
||||
</form>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("init", %{"node" => %{"name" => name}}, socket) do
|
||||
node = Utils.node_from_name(name)
|
||||
def handle_event("validate", %{"data" => data}, socket) do
|
||||
{:noreply, assign(socket, data: data)}
|
||||
end
|
||||
|
||||
case Runtime.Attached.init(node) do
|
||||
def handle_event("init", %{"data" => data}, socket) do
|
||||
node = Utils.node_from_name(data["name"])
|
||||
cookie = String.to_atom(data["cookie"])
|
||||
|
||||
case Runtime.Attached.init(node, cookie) do
|
||||
{:ok, runtime} ->
|
||||
Session.connect_runtime(socket.assigns.session_id, runtime)
|
||||
{:noreply, assign(socket, name: name, error_message: nil)}
|
||||
{:noreply, assign(socket, data: data, error_message: nil)}
|
||||
|
||||
{:error, error} ->
|
||||
message = runtime_error_to_message(error)
|
||||
{:noreply, assign(socket, name: name, error_message: message)}
|
||||
{:noreply, assign(socket, data: data, error_message: message)}
|
||||
end
|
||||
end
|
||||
|
||||
defp initial_name(%Runtime.Attached{} = current_runtime), do: current_runtime.node
|
||||
defp initial_name(_runtime), do: ""
|
||||
defp initial_data(%Runtime.Attached{node: node, cookie: cookie}) do
|
||||
%{
|
||||
"name" => Atom.to_string(node),
|
||||
"cookie" => Atom.to_string(cookie)
|
||||
}
|
||||
end
|
||||
|
||||
defp initial_data(_runtime), do: %{"name" => "", "cookie" => ""}
|
||||
|
||||
defp data_valid?(data) do
|
||||
data["name"] != "" and data["cookie"] != ""
|
||||
end
|
||||
|
||||
defp runtime_error_to_message(:unreachable), do: "Node unreachable"
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ defmodule LivebookWeb.SessionLive.CellSettingsComponent do
|
|||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div class="p-6 pb-4 max-w-xl w-screen flex flex-col space-y-8">
|
||||
<div class="p-6 pb-4 flex flex-col space-y-8">
|
||||
<h3 class="text-2xl font-semibold text-gray-800">
|
||||
Cell settings
|
||||
</h3>
|
||||
|
|
|
@ -11,7 +11,7 @@ defmodule LivebookWeb.SessionLive.CellUploadComponent do
|
|||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div class="p-6 pb-4 max-w-xl w-screen flex flex-col space-y-8">
|
||||
<div class="p-6 pb-4 flex flex-col space-y-8">
|
||||
<h3 class="text-2xl font-semibold text-gray-800">
|
||||
Insert image
|
||||
</h3>
|
||||
|
|
|
@ -13,7 +13,7 @@ defmodule LivebookWeb.SessionLive.PersistenceComponent do
|
|||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div class="p-6 pb-4 max-w-4xl w-screen flex flex-col space-y-3">
|
||||
<div class="p-6 pb-4 flex flex-col space-y-3">
|
||||
<h3 class="text-2xl font-semibold text-gray-800">
|
||||
File
|
||||
</h3>
|
||||
|
|
|
@ -30,7 +30,7 @@ defmodule LivebookWeb.SessionLive.RuntimeComponent do
|
|||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div class="p-6 pb-4 max-w-4xl w-screen flex flex-col space-y-3">
|
||||
<div class="p-6 pb-4 max-w-4xl flex flex-col space-y-3">
|
||||
<h3 class="text-2xl font-semibold text-gray-800">
|
||||
Runtime
|
||||
</h3>
|
||||
|
|
|
@ -42,7 +42,7 @@ defmodule LivebookWeb.SessionLive.ShortcutsComponent do
|
|||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div class="p-6 sm:max-w-5xl sm:w-full flex flex-col space-y-3">
|
||||
<div class="p-6 flex flex-col space-y-3">
|
||||
<h3 class="text-2xl font-semibold text-gray-800">
|
||||
Keyboard shortcuts
|
||||
</h3>
|
||||
|
|
Loading…
Reference in a new issue