mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-09-05 04:24:21 +08:00
Enforce Hub when deploying notebooks from LIVEBOOK_APPS_PATH
(#2039)
This commit is contained in:
parent
be9aab3223
commit
f4365e44d2
15 changed files with 206 additions and 98 deletions
12
README.md
12
README.md
|
@ -176,6 +176,9 @@ The following environment variables can be used to configure Livebook on boot:
|
|||
Password-protected notebooks will receive a random password,
|
||||
unless LIVEBOOK_APPS_PATH_PASSWORD is set.
|
||||
|
||||
* LIVEBOOK_APPS_PATH_HUB_ID - the Hub id to use for all apps
|
||||
deployed from LIVEBOOK_APPS_PATH.
|
||||
|
||||
* LIVEBOOK_APPS_PATH_PASSWORD - the password to use for all protected apps
|
||||
deployed from LIVEBOOK_APPS_PATH.
|
||||
|
||||
|
@ -242,6 +245,15 @@ The following environment variables can be used to configure Livebook on boot:
|
|||
* LIVEBOOK_SHUTDOWN_ENABLED - controls if a shutdown button should be shown
|
||||
in the homepage. Set it to "true" to enable it.
|
||||
|
||||
* LIVEBOOK_TEAMS_KEY - sets the secret Livebook Teams key for creating an offline hub.
|
||||
Must be set together with LIVEBOOK_TEAMS_NAME and LIVEBOOK_TEAMS_OFFLINE_KEY.
|
||||
|
||||
* LIVEBOOK_TEAMS_NAME - sets the Livebook Teams name for creating an offline hub.
|
||||
Must be set together with LIVEBOOK_TEAMS_KEY and LIVEBOOK_TEAMS_OFFLINE_KEY.
|
||||
|
||||
* LIVEBOOK_TEAMS_OFFLINE_KEY - sets the Livebook Teams public key for creating an offline hub.
|
||||
Must be set together with LIVEBOOK_TEAMS_NAME and LIVEBOOK_TEAMS_KEY.
|
||||
|
||||
* LIVEBOOK_TOKEN_ENABLED - controls whether token authentication is enabled.
|
||||
Enabled by default unless LIVEBOOK_PASSWORD is set. Set it to "false" to
|
||||
disable it.
|
||||
|
|
|
@ -160,6 +160,10 @@ defmodule Livebook do
|
|||
config :livebook, :apps_path, apps_path
|
||||
end
|
||||
|
||||
if apps_path_hub_id = System.get_env("LIVEBOOK_APPS_PATH_HUB_ID") do
|
||||
config :livebook, :apps_path_hub_id, apps_path_hub_id
|
||||
end
|
||||
|
||||
if apps_path_password = Livebook.Config.password!("LIVEBOOK_APPS_PATH_PASSWORD") do
|
||||
config :livebook, :apps_path_password, apps_path_password
|
||||
end
|
||||
|
|
|
@ -167,7 +167,9 @@ defmodule Livebook.Apps do
|
|||
|
||||
for path <- paths do
|
||||
markdown = File.read!(path)
|
||||
{notebook, warnings} = Livebook.LiveMarkdown.notebook_from_livemd(markdown)
|
||||
|
||||
{notebook, %{warnings: warnings, verified_hub_id: verified_hub_id}} =
|
||||
Livebook.LiveMarkdown.notebook_from_livemd(markdown)
|
||||
|
||||
if warnings != [] do
|
||||
items = Enum.map(warnings, &("- " <> &1))
|
||||
|
@ -186,7 +188,15 @@ defmodule Livebook.Apps do
|
|||
|
||||
if Livebook.Notebook.AppSettings.valid?(notebook.app_settings) do
|
||||
warnings = Enum.map(warnings, &("Import: " <> &1))
|
||||
deploy(notebook, warnings: warnings)
|
||||
apps_path_hub_id = Livebook.Config.apps_path_hub_id()
|
||||
|
||||
if apps_path_hub_id == nil or apps_path_hub_id == verified_hub_id do
|
||||
deploy(notebook, warnings: warnings)
|
||||
else
|
||||
Logger.warning(
|
||||
"Skipping app deployment at #{path}. The notebook is not verified to come from hub #{apps_path_hub_id}"
|
||||
)
|
||||
end
|
||||
else
|
||||
Logger.warning(
|
||||
"Skipping app deployment at #{path}. The deployment settings are missing or invalid. Please configure them under the notebook deploy panel."
|
||||
|
|
|
@ -107,13 +107,21 @@ defmodule Livebook.Config do
|
|||
end
|
||||
|
||||
@doc """
|
||||
Returns the password configured for all apps deployed rom `app_path`.
|
||||
Returns the password configured for all apps deployed from `apps_path`.
|
||||
"""
|
||||
@spec apps_path_password() :: String.t() | nil
|
||||
def apps_path_password() do
|
||||
Application.get_env(:livebook, :apps_path_password)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the hub configured for all apps deployed from `apps_path`.
|
||||
"""
|
||||
@spec apps_path_hub_id() :: String.t() | nil
|
||||
def apps_path_hub_id() do
|
||||
Application.get_env(:livebook, :apps_path_hub_id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the configured port for the Livebook endpoint.
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ defmodule Livebook.Hubs do
|
|||
@offline_hub_key :livebook_offline_hub
|
||||
|
||||
@doc """
|
||||
Get the offline hub.
|
||||
Gets the offline hub if the given id matches.
|
||||
"""
|
||||
@spec get_offline_hub(String.t()) :: Provider.t() | nil
|
||||
def get_offline_hub(id) do
|
||||
|
|
|
@ -98,9 +98,21 @@ defmodule Livebook.LiveMarkdown do
|
|||
@doc """
|
||||
Converts the given Markdown document into a notebook data structure.
|
||||
|
||||
Returns the notebook structure and a list of informative messages/warnings
|
||||
related to the imported input.
|
||||
Returns the notebook struct and info map with the following keys:
|
||||
|
||||
* `:warnings` - a list of informative messages/warnings related
|
||||
to the imported input
|
||||
|
||||
* `:verified_hub_id` - the hub id specified in the notebook
|
||||
provided that the stamp was successfully verified, `nil`
|
||||
otherwise
|
||||
|
||||
"""
|
||||
@spec notebook_from_livemd(String.t()) :: {Notebook.t(), list(String.t())}
|
||||
@spec notebook_from_livemd(String.t()) ::
|
||||
{Notebook.t(),
|
||||
%{
|
||||
required(:warnings) => list(String.t()),
|
||||
required(:verified_hub_id) => String.t() | nil
|
||||
}}
|
||||
defdelegate notebook_from_livemd(markdown), to: Livebook.LiveMarkdown.Import
|
||||
end
|
||||
|
|
|
@ -13,14 +13,14 @@ defmodule Livebook.LiveMarkdown.Import do
|
|||
{notebook, stamp_hub_id, build_messages} = build_notebook(elements)
|
||||
{notebook, postprocess_messages} = postprocess_notebook(notebook)
|
||||
|
||||
{notebook, metadata_messages} =
|
||||
{notebook, verified_hub_id, metadata_messages} =
|
||||
postprocess_stamp(notebook, markdown, stamp_data, stamp_hub_id)
|
||||
|
||||
messages =
|
||||
earmark_messages ++
|
||||
rewrite_messages ++ build_messages ++ postprocess_messages ++ metadata_messages
|
||||
|
||||
{notebook, messages}
|
||||
{notebook, %{warnings: messages, verified_hub_id: verified_hub_id}}
|
||||
end
|
||||
|
||||
defp earmark_message_to_string({_severity, line_number, message}) do
|
||||
|
@ -594,7 +594,7 @@ defmodule Livebook.LiveMarkdown.Import do
|
|||
defp take_stamp_data([{:stamp, data} | elements]), do: {data, elements}
|
||||
defp take_stamp_data(elements), do: {nil, elements}
|
||||
|
||||
defp postprocess_stamp(notebook, _notebook_source, nil, _), do: {notebook, []}
|
||||
defp postprocess_stamp(notebook, _notebook_source, nil, _), do: {notebook, nil, []}
|
||||
|
||||
defp postprocess_stamp(notebook, notebook_source, stamp_data, stamp_hub_id) do
|
||||
{hub, offline?} =
|
||||
|
@ -618,7 +618,9 @@ defmodule Livebook.LiveMarkdown.Import do
|
|||
teams_enabled = is_struct(hub, Livebook.Hubs.Team) and (not offline? or valid_stamp?)
|
||||
|
||||
notebook = %{notebook | teams_enabled: teams_enabled}
|
||||
{notebook, messages}
|
||||
verified_hub_id = if(valid_stamp?, do: hub.id)
|
||||
|
||||
{notebook, verified_hub_id, messages}
|
||||
end
|
||||
|
||||
defp safe_binary_slice(binary, start, size)
|
||||
|
|
|
@ -120,7 +120,7 @@ defmodule Livebook.Notebook.Learn do
|
|||
markdown = File.read!(path)
|
||||
# Parse the file to ensure no warnings and read the title.
|
||||
# However, in the info we keep just the file contents to save on memory.
|
||||
{notebook, warnings} = Livebook.LiveMarkdown.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: warnings}} = Livebook.LiveMarkdown.notebook_from_livemd(markdown)
|
||||
|
||||
if warnings != [] do
|
||||
items = Enum.map(warnings, &("- " <> &1))
|
||||
|
@ -197,7 +197,9 @@ defmodule Livebook.Notebook.Learn do
|
|||
raise NotFoundError, slug: slug
|
||||
|
||||
notebook_info ->
|
||||
{notebook, []} = Livebook.LiveMarkdown.notebook_from_livemd(notebook_info.livemd)
|
||||
{notebook, %{warnings: []}} =
|
||||
Livebook.LiveMarkdown.notebook_from_livemd(notebook_info.livemd)
|
||||
|
||||
{notebook, notebook_info.files}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -253,7 +253,7 @@ defmodule LivebookWeb.OpenLive do
|
|||
defp file_from_params(_params), do: Livebook.Settings.default_file_system_home()
|
||||
|
||||
defp import_source(socket, source, session_opts) do
|
||||
{notebook, messages} = Livebook.LiveMarkdown.notebook_from_livemd(source)
|
||||
{notebook, %{warnings: messages}} = Livebook.LiveMarkdown.notebook_from_livemd(source)
|
||||
|
||||
socket =
|
||||
socket
|
||||
|
|
|
@ -104,7 +104,7 @@ defmodule LivebookWeb.SessionHelpers do
|
|||
@spec fork_notebook(Socket.t(), FileSystem.File.t()) :: Socket.t()
|
||||
def fork_notebook(socket, file) do
|
||||
case import_notebook(file) do
|
||||
{:ok, {notebook, messages}} ->
|
||||
{:ok, {notebook, %{warnings: messages}}} ->
|
||||
notebook = Livebook.Notebook.forked(notebook)
|
||||
files_dir = Session.files_dir_for_notebook(file)
|
||||
|
||||
|
@ -127,7 +127,7 @@ defmodule LivebookWeb.SessionHelpers do
|
|||
@spec open_notebook(Socket.t(), FileSystem.File.t()) :: Socket.t()
|
||||
def open_notebook(socket, file) do
|
||||
case import_notebook(file) do
|
||||
{:ok, {notebook, messages}} ->
|
||||
{:ok, {notebook, %{warnings: messages}}} ->
|
||||
socket
|
||||
|> put_import_warnings(messages)
|
||||
|> create_session(notebook: notebook, file: file, origin: {:file, file})
|
||||
|
|
|
@ -1663,7 +1663,7 @@ defmodule LivebookWeb.SessionLive do
|
|||
defp open_notebook(socket, origin, fallback_locations, requested_url) do
|
||||
case fetch_content_with_fallbacks(origin, fallback_locations) do
|
||||
{:ok, content} ->
|
||||
{notebook, messages} = Livebook.LiveMarkdown.notebook_from_livemd(content)
|
||||
{notebook, %{warnings: messages}} = Livebook.LiveMarkdown.notebook_from_livemd(content)
|
||||
|
||||
# If the current session has no file, fork the notebook
|
||||
fork? = socket.private.data.file == nil
|
||||
|
|
|
@ -2,6 +2,7 @@ defmodule Livebook.AppsTest do
|
|||
use ExUnit.Case, async: true
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Livebook.HubHelpers
|
||||
|
||||
describe "deploy_apps_in_dir/1" do
|
||||
@tag :tmp_dir
|
||||
|
@ -39,6 +40,66 @@ defmodule Livebook.AppsTest do
|
|||
Livebook.App.close(app2.pid)
|
||||
end
|
||||
|
||||
@tag :capture_log
|
||||
@tag :tmp_dir
|
||||
test "deploys apps with offline hub stamp", %{tmp_dir: tmp_dir} do
|
||||
app1_path = Path.join(tmp_dir, "app1.livemd")
|
||||
app2_path = Path.join(tmp_dir, "app2.livemd")
|
||||
app3_path = Path.join(tmp_dir, "app3.livemd")
|
||||
|
||||
File.write!(app1_path, """
|
||||
<!-- livebook:{"app_settings":{"slug":"offline_hub_app1"}} -->
|
||||
|
||||
# App 1
|
||||
""")
|
||||
|
||||
File.write!(app2_path, """
|
||||
<!-- livebook:{"app_settings":{"slug":"offline_hub_app2"},"hub_id":"team-org-number-3079"} -->
|
||||
|
||||
# App 2
|
||||
|
||||
## Section 1
|
||||
|
||||
```elixir
|
||||
IO.puts("hey")
|
||||
```
|
||||
|
||||
<!-- livebook:{"offset":148,"stamp":{"token":"QTEyOEdDTQ.M486X5ISDg_wVwvndrMYJKIkfXa5qAwggh5LzkV41wVOY8SNQvfA4EFx4Tk.RrcteIrzJVrqQdhH.mtmu5KFj.bibmp2rxZoniYX1xY8dTvw","token_signature":"28ucTCoDXxahOIMg7SvdYIoLpGIUSahEa7mchH0jKncKeZH8-w-vOaL1F1uj_94lqQJFkmHWv988__1bPmYCorw7F1wAvAaprt3o2vSitWWmBszuF5JaimkFqOFcK3mc4NHuswQKuBjSL0W_yR-viiwlx6zPNsTpftVKjRI2Cri1PsMeZgahfdR2gy1OEgavzU6J6YWsNQHIMWgt5gwT6fIua1zaV7K8-TA6-6NRgcfG-pSJqRIm-3-vnbH5lkXRCgXCo_S9zWa6Jrcl5AbLObSr5DUueiwac1RobH7jNghCm1F-o1cUk9W-BJRZ7igVMwaYqLaOnKO8ya9CrkIiMg","version":1}} -->
|
||||
""")
|
||||
|
||||
File.write!(app3_path, """
|
||||
<!-- livebook:{"app_settings":{"slug":"offline_hub_app3"}} -->
|
||||
|
||||
# App 3
|
||||
|
||||
## Section 1
|
||||
|
||||
```elixir
|
||||
IO.puts("hey")
|
||||
```
|
||||
|
||||
<!-- livebook:{"offset":111,"stamp":{"token":"invalid","token_signature":"invalid","version":1}} -->
|
||||
""")
|
||||
|
||||
Livebook.Apps.subscribe()
|
||||
|
||||
Application.put_env(:livebook, :apps_path_hub_id, offline_hub().id, persistent: true)
|
||||
Livebook.Apps.deploy_apps_in_dir(tmp_dir)
|
||||
Application.delete_env(:livebook, :apps_path_hub_id, persistent: true)
|
||||
|
||||
refute_receive {:app_created, %{slug: "offline_hub_app1"}}
|
||||
assert_receive {:app_created, %{pid: pid, slug: "offline_hub_app2"}}
|
||||
refute_receive {:app_created, %{slug: "offline_hub_app3"}}
|
||||
|
||||
assert_receive {:app_updated,
|
||||
%{
|
||||
slug: "offline_hub_app2",
|
||||
sessions: [%{app_status: %{execution: :executed}}]
|
||||
}}
|
||||
|
||||
Livebook.App.close(pid)
|
||||
end
|
||||
|
||||
@tag :tmp_dir
|
||||
test "skips apps with incomplete config and warns", %{tmp_dir: tmp_dir} do
|
||||
app_path = Path.join(tmp_dir, "app.livemd")
|
||||
|
|
|
@ -62,7 +62,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
# Match only on the relevant fields as some may be generated (ids).
|
||||
|
||||
|
@ -159,7 +159,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
| Maine | ME | Augusta |
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -188,7 +188,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
Some markdown.
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "Untitled notebook",
|
||||
|
@ -213,7 +213,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
###### Tiny heading
|
||||
"""
|
||||
|
||||
{notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "Untitled notebook",
|
||||
|
@ -257,7 +257,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
## # Section
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My *Notebook*",
|
||||
|
@ -278,7 +278,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
## Actual section
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -307,7 +307,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "Untitled notebook",
|
||||
|
@ -337,7 +337,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
Some markdown.
|
||||
"""
|
||||
|
||||
{notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -369,7 +369,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
Some markdown.
|
||||
"""
|
||||
|
||||
{_notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{_notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert ["line 3 - closing unclosed backquotes ` at end of input"] == messages
|
||||
end
|
||||
|
@ -395,7 +395,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -451,7 +451,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -499,7 +499,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
Cell 2
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -543,7 +543,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
Cell 1
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -581,10 +581,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
Cell 1
|
||||
"""
|
||||
|
||||
{notebook,
|
||||
[
|
||||
"found an invalid sequence of comments at the beginning, make sure custom comments are at the very top"
|
||||
]} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -603,6 +600,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
}
|
||||
]
|
||||
} = notebook
|
||||
|
||||
assert messages == [
|
||||
"found an invalid sequence of comments at the beginning, make sure custom comments are at the very top"
|
||||
]
|
||||
end
|
||||
|
||||
describe "outputs" do
|
||||
|
@ -629,7 +630,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -675,7 +676,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -714,7 +715,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{name: "My Notebook", persist_outputs: true} = notebook
|
||||
end
|
||||
|
@ -727,7 +728,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{name: "My Notebook", autosave_interval_s: 10} = notebook
|
||||
end
|
||||
|
@ -739,7 +740,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{name: "My Notebook", default_language: :erlang} = notebook
|
||||
end
|
||||
|
@ -753,7 +754,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{name: "My Notebook", hub_id: ^hub_id} = notebook
|
||||
end
|
||||
|
@ -765,7 +766,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert messages == ["ignoring notebook Hub with unknown id"]
|
||||
assert notebook.hub_id != "nonexistent"
|
||||
|
@ -779,7 +780,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -803,7 +804,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -822,7 +823,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
<!-- livebook:{"livebook_object":"cell_input","name":"length","type":"text","value":"100"} -->
|
||||
"""
|
||||
|
||||
{_notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{_notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert [
|
||||
"found an input cell, but those are no longer supported, please use Kino.Input instead"
|
||||
|
@ -838,7 +839,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
<!-- livebook:{"livebook_object":"cell_input","name":"length","reactive":true,"type":"text","value":"100"} -->
|
||||
"""
|
||||
|
||||
{_notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{_notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert [
|
||||
"found an input cell, but those are no longer supported, please use Kino.Input instead." <>
|
||||
|
@ -869,7 +870,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -901,7 +902,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||

|
||||
"""
|
||||
|
||||
{_notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{_notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert [
|
||||
"found Markdown images pointing to the images/ directory. Using this directory has been deprecated, please use notebook files instead"
|
||||
|
@ -928,10 +929,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
assert {notebook,
|
||||
[
|
||||
"ignoring the parent section of \"Section 1\", because it comes later in the notebook"
|
||||
]} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -944,6 +942,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
}
|
||||
]
|
||||
} = notebook
|
||||
|
||||
assert messages == [
|
||||
"ignoring the parent section of \"Section 1\", because it comes later in the notebook"
|
||||
]
|
||||
end
|
||||
|
||||
test "import notebook with parent section pointing to the section itself produces a warning" do
|
||||
|
@ -959,10 +961,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
assert {notebook,
|
||||
[
|
||||
"ignoring the parent section of \"Section 1\", because it comes later in the notebook"
|
||||
]} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -972,6 +971,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
}
|
||||
]
|
||||
} = notebook
|
||||
|
||||
assert messages == [
|
||||
"ignoring the parent section of \"Section 1\", because it comes later in the notebook"
|
||||
]
|
||||
end
|
||||
|
||||
test "importing notebook with parent section being a branching section itself produces a warning" do
|
||||
|
@ -1000,10 +1003,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
assert {notebook,
|
||||
[
|
||||
"ignoring the parent section of \"Section 3\", because it is itself a branching section"
|
||||
]} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -1022,6 +1022,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
}
|
||||
]
|
||||
} = notebook
|
||||
|
||||
assert messages == [
|
||||
"ignoring the parent section of \"Section 3\", because it is itself a branching section"
|
||||
]
|
||||
end
|
||||
|
||||
describe "setup cell" do
|
||||
|
@ -1036,7 +1040,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
## Section 1
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -1063,7 +1067,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
```
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
|
@ -1116,7 +1120,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
<!-- livebook:{"offset":58,"stamp":{"token":"QTEyOEdDTQ.LF8LTeMYrtq8S7wsKMmk2YgOQzMAkEKT2d8fq1Gz3Ot1mydOgEZ1B4hcEZc.Wec6NwBQ584kE661.a_N-5jDiWrjhHha9zxHQ6JJOmxeqgiya3m6YlKt1Na_DPnEfXyLnengaUzQSrf8.ZoD5r6-H87RpTyvFkvEOQw","version":1}} -->
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{hub_secret_names: ["DB_PASSWORD"]} = notebook
|
||||
end
|
||||
|
@ -1134,27 +1138,15 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
<!-- livebook:{"offset":58,"stamp":{"token":"invalid","version":1}} -->
|
||||
"""
|
||||
|
||||
{notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{hub_secret_names: []} = notebook
|
||||
|
||||
assert messages == ["failed to verify notebook stamp"]
|
||||
end
|
||||
|
||||
test "restores hub secret names from notebook stamp using offline hub" do
|
||||
hub =
|
||||
Livebook.Factory.build(:team,
|
||||
id: "team-org-number-2946",
|
||||
teams_key: "AleIxOFlwSiOS78WXtVU01ySmitjzy-5pAuCh4i1wZE",
|
||||
org_public_key:
|
||||
"MIIBCgKCAQEA2uRttEa6UvtiAUhv-MhPZvvlrCNeeL5n6oP4pliqoMBD7vsi4EvwnrqjCCicwHeT4y8Pu1kmzTelDAHEyO8alllBtfnZnQkPOqo1Y6c6qBHhcioc2FrNvdAydMiByhyn_aqNbFNeMMgy9ogHerAQ6XPrGSaXEvIcWn3myz-zxYdeEDW5G5W95o7Q0x7lokdVBUwXbazH0JVu_-1FUr7aOSjjuNHX6rXMRA3wr4n2SuhGOvihrX5IYRb733pae2aTOfJZGD_83eUPHTu_cPoUflcvIPtnVlGTxBgSX9Ayl1X3uDOnJsk2pxawFF6GxBMUKjMGyGDTg_lL45cgsWovXQIDAQAB",
|
||||
hub_name: "org-number-2946"
|
||||
)
|
||||
|
||||
Livebook.Hubs.set_offline_hub(hub)
|
||||
|
||||
markdown = """
|
||||
<!-- livebook:{"hub_id":"team-org-number-2946"} -->
|
||||
<!-- livebook:{"hub_id":"team-org-number-3079"} -->
|
||||
|
||||
# My Notebook
|
||||
|
||||
|
@ -1164,10 +1156,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
IO.puts("hey")
|
||||
```
|
||||
|
||||
<!-- livebook:{"offset":111,"stamp":{"token":"QTEyOEdDTQ.yw3drh2WcwU8K6jS9Wp0HPupyX3qoc8iBmUXrMVKvSPnIOGEYMmu160e89E.xyzsr7PxSBrA8Elt.N3KyvcuTrFyMYpSl8WB1Sctv-1YjSjv_DCZoOVje_zXPYpm4iV_Ss5tVUSA7IWE.lV7grc6HYOYJrf0YYScPwQ","token_signature":"KSd-EhXw2CrmS9m4aZnPhTgWzlNdQNJ0wvYmuNvi8Pxaqb-prKO0FN_BTcPHtk4ZDHJaIFac-8dyefkCHpIElAc_N7vExgO9_7wSOJ8Hagip7DOxOBfqcR6iC17ejiw-2wWFJu0p6deaXpm2RWkWJU--wiU1cAHoKoJGqIsMMxNmgAkT44Pok0ni5BtnTfZjq_c2iPTYfP-8uU2WFIDmzEeOL-He5iWNUlixnf5Aj1YSVNldi6vTtR70xBRvlUxPCkWbt1x6XjanspY15j43PgVTo0EPM4kGCkS2HcWBZB_XscxZ4-V-WdpQ0pkv1goPdfDGDcAbjP7z8oum9_ZKNA","version":1}} -->
|
||||
<!-- livebook:{"offset":111,"stamp":{"token":"QTEyOEdDTQ.VezIVId8jnwawq79Mrxfx-bCeatRPQhg6zRw4gHjfGC_SimS5WSbdETLVnc.IXXzTiDf3JRLiNGt.rtLJ97RxNYLeF_x-2AigBt_y0bYdlh30bnEKUO7FKfJL-9EB6EQOgr1WbdHTkw.rU1OsjOhfU48tE3s0GB6Ag","token_signature":"M_LZP7ssEdLiVqo8_bZYFtJYAzqV5wczQF1mUdaOZeTYoCYXeLA9VuEajMCOwiVgMjfG24Y4PHrnABGUj0bB74xgEMOLtb6Ark42pCJfGUDLXpB2azMnwY6VRXi1nBUTnb_-MajpJVF_MgWGuj0cxyQ4rlfBu2VK1FQn8JGopLKBD7LcICZ9wkLJw3H_lXGTbVxnS6tLcvJZQdLJccTe4edpdF-_uG-d1KqtJva50jZ9vevyxh6zUubl0k5JnA3SUaTpc7AEsqmAMx9qQsoR64P-VobSFTKuuOFrlQsq21OupPCRKmUBU-RKrBvHbc6Fa1eoQigEQom5droj9cASdw","version":1}} -->
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
hub_id: "personal-hub",
|
||||
|
@ -1177,19 +1169,8 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
end
|
||||
|
||||
test "returns a warning when notebook stamp is invalid using offline hub" do
|
||||
hub =
|
||||
Livebook.Factory.build(:team,
|
||||
id: "team-org-number-2946",
|
||||
teams_key: "AleIxOFlwSiOS78WXtVU01ySmitjzy-5pAuCh4i1wZE",
|
||||
org_public_key:
|
||||
"MIIBCgKCAQEA2uRttEa6UvtiAUhv-MhPZvvlrCNeeL5n6oP4pliqoMBD7vsi4EvwnrqjCCicwHeT4y8Pu1kmzTelDAHEyO8alllBtfnZnQkPOqo1Y6c6qBHhcioc2FrNvdAydMiByhyn_aqNbFNeMMgy9ogHerAQ6XPrGSaXEvIcWn3myz-zxYdeEDW5G5W95o7Q0x7lokdVBUwXbazH0JVu_-1FUr7aOSjjuNHX6rXMRA3wr4n2SuhGOvihrX5IYRb733pae2aTOfJZGD_83eUPHTu_cPoUflcvIPtnVlGTxBgSX9Ayl1X3uDOnJsk2pxawFF6GxBMUKjMGyGDTg_lL45cgsWovXQIDAQAB",
|
||||
hub_name: "org-number-2946"
|
||||
)
|
||||
|
||||
Livebook.Hubs.set_offline_hub(hub)
|
||||
|
||||
markdown = """
|
||||
<!-- livebook:{"hub_id":"team-org-number-2946"} -->
|
||||
<!-- livebook:{"hub_id":"team-org-number-3079"} -->
|
||||
|
||||
# My Notebook
|
||||
|
||||
|
@ -1202,11 +1183,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
<!-- livebook:{"offset":58,"stamp":{"token":"invalid","token_signature":"invalid","version":1}} -->
|
||||
"""
|
||||
|
||||
assert {%Notebook{
|
||||
hub_id: "personal-hub",
|
||||
hub_secret_names: [],
|
||||
teams_enabled: false
|
||||
}, ["failed to verify notebook stamp"]} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{hub_id: "personal-hub", teams_enabled: false} = notebook
|
||||
assert messages == ["failed to verify notebook stamp"]
|
||||
end
|
||||
|
||||
test "sets :teams_enabled to true when the teams hub exist regardless the stamp" do
|
||||
|
@ -1226,7 +1206,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
<!-- livebook:{"offset":58,"stamp":{"token":"invalid","token_signature":"invalid","version":1}} -->
|
||||
"""
|
||||
|
||||
{notebook, [_]} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: [_]}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{hub_id: ^hub_id, teams_enabled: true} = notebook
|
||||
end
|
||||
|
@ -1240,7 +1220,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
file_entries: [
|
||||
|
@ -1265,7 +1245,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
# My Notebook
|
||||
"""
|
||||
|
||||
{notebook, messages} = Import.notebook_from_livemd(markdown)
|
||||
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||
|
||||
assert %Notebook{file_entries: []} = notebook
|
||||
|
||||
|
|
|
@ -5,6 +5,14 @@ defmodule Livebook.HubHelpers do
|
|||
import Livebook.Factory
|
||||
import Phoenix.LiveViewTest
|
||||
|
||||
@offline_hub %Livebook.Hubs.Team{
|
||||
id: "team-org-number-3079",
|
||||
teams_key: "A9TarFeAzmX3sDwSPm5JP5qbLPnNpLpzmjVZUCHXwmI",
|
||||
org_public_key:
|
||||
"MIIBCgKCAQEA5v_qciaRGOZd5kgCQbhQDgFCnTnIKI5xzN4m4rVtLXMPH7RTA-K6C-e4wy2gn8zulXgSYX4vXDACSjFAG4PlFhXTPgb-v3rFLwbBrUHdaTMTyxRdK52NyNoDpYklQ7FaEU9vr3Z_-cpAQjdADOV1k45GmFe3bo4gImIfUSDYp1rRiEsYcIBt0Wc0S-vQHKSlmfcCexe254_UkvWjLW7KO790bem-PSWcBI_713oRr2mQoxXeeGKd5dSyFsIr5SZXVRWcRK3soQimCXB0ddBSXZ7d2Md3P9Ylo7TcYdBGHlwVIsrmB-P70KPHPYuAVgS9QsIiiMGXPwYVW77xNRTlcwIDAQAB",
|
||||
hub_name: "org-number-3079"
|
||||
}
|
||||
|
||||
def create_team_hub(user, node) do
|
||||
hub = build_team_hub(user, node)
|
||||
Livebook.Hubs.save_hub(hub)
|
||||
|
@ -58,6 +66,12 @@ defmodule Livebook.HubHelpers do
|
|||
refute has_element?(view, hub_element_id(id))
|
||||
end
|
||||
|
||||
def set_offline_hub() do
|
||||
Livebook.Hubs.set_offline_hub(@offline_hub)
|
||||
end
|
||||
|
||||
def offline_hub(), do: @offline_hub
|
||||
|
||||
defp hub_element_id(id), do: "#hubs #hub-#{id}"
|
||||
|
||||
defp erpc_call(node, fun, args) do
|
||||
|
|
|
@ -47,6 +47,9 @@ secret_key =
|
|||
personal_hub = Livebook.Hubs.fetch_hub!(Livebook.Hubs.Personal.id())
|
||||
Livebook.Hubs.Personal.update_hub(personal_hub, %{secret_key: secret_key})
|
||||
|
||||
# Always set the same offline team hub in tests
|
||||
Livebook.HubHelpers.set_offline_hub()
|
||||
|
||||
erl_docs_available? = Code.fetch_docs(:gen_server) != {:error, :chunk_not_found}
|
||||
|
||||
windows? = match?({:win32, _}, :os.type())
|
||||
|
|
Loading…
Add table
Reference in a new issue