Enforce Hub when deploying notebooks from LIVEBOOK_APPS_PATH (#2039)

This commit is contained in:
Alexandre de Souza 2023-07-07 15:27:07 -03:00 committed by GitHub
parent be9aab3223
commit f4365e44d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 206 additions and 98 deletions

View file

@ -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.

View file

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

View file

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

View file

@ -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.

View file

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

View file

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

View file

@ -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)

View file

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

View file

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

View file

@ -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})

View 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

View file

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

View file

@ -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
![](images/dog.jpeg)
"""
{_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

View file

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

View file

@ -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())