mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-11-10 14:11:29 +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,
|
Password-protected notebooks will receive a random password,
|
||||||
unless LIVEBOOK_APPS_PATH_PASSWORD is set.
|
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
|
* LIVEBOOK_APPS_PATH_PASSWORD - the password to use for all protected apps
|
||||||
deployed from LIVEBOOK_APPS_PATH.
|
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
|
* LIVEBOOK_SHUTDOWN_ENABLED - controls if a shutdown button should be shown
|
||||||
in the homepage. Set it to "true" to enable it.
|
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.
|
* LIVEBOOK_TOKEN_ENABLED - controls whether token authentication is enabled.
|
||||||
Enabled by default unless LIVEBOOK_PASSWORD is set. Set it to "false" to
|
Enabled by default unless LIVEBOOK_PASSWORD is set. Set it to "false" to
|
||||||
disable it.
|
disable it.
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,10 @@ defmodule Livebook do
|
||||||
config :livebook, :apps_path, apps_path
|
config :livebook, :apps_path, apps_path
|
||||||
end
|
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
|
if apps_path_password = Livebook.Config.password!("LIVEBOOK_APPS_PATH_PASSWORD") do
|
||||||
config :livebook, :apps_path_password, apps_path_password
|
config :livebook, :apps_path_password, apps_path_password
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,9 @@ defmodule Livebook.Apps do
|
||||||
|
|
||||||
for path <- paths do
|
for path <- paths do
|
||||||
markdown = File.read!(path)
|
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
|
if warnings != [] do
|
||||||
items = Enum.map(warnings, &("- " <> &1))
|
items = Enum.map(warnings, &("- " <> &1))
|
||||||
|
|
@ -186,7 +188,15 @@ defmodule Livebook.Apps do
|
||||||
|
|
||||||
if Livebook.Notebook.AppSettings.valid?(notebook.app_settings) do
|
if Livebook.Notebook.AppSettings.valid?(notebook.app_settings) do
|
||||||
warnings = Enum.map(warnings, &("Import: " <> &1))
|
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
|
else
|
||||||
Logger.warning(
|
Logger.warning(
|
||||||
"Skipping app deployment at #{path}. The deployment settings are missing or invalid. Please configure them under the notebook deploy panel."
|
"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
|
end
|
||||||
|
|
||||||
@doc """
|
@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
|
@spec apps_path_password() :: String.t() | nil
|
||||||
def apps_path_password() do
|
def apps_path_password() do
|
||||||
Application.get_env(:livebook, :apps_path_password)
|
Application.get_env(:livebook, :apps_path_password)
|
||||||
end
|
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 """
|
@doc """
|
||||||
Returns the configured port for the Livebook endpoint.
|
Returns the configured port for the Livebook endpoint.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ defmodule Livebook.Hubs do
|
||||||
@offline_hub_key :livebook_offline_hub
|
@offline_hub_key :livebook_offline_hub
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Get the offline hub.
|
Gets the offline hub if the given id matches.
|
||||||
"""
|
"""
|
||||||
@spec get_offline_hub(String.t()) :: Provider.t() | nil
|
@spec get_offline_hub(String.t()) :: Provider.t() | nil
|
||||||
def get_offline_hub(id) do
|
def get_offline_hub(id) do
|
||||||
|
|
|
||||||
|
|
@ -98,9 +98,21 @@ defmodule Livebook.LiveMarkdown do
|
||||||
@doc """
|
@doc """
|
||||||
Converts the given Markdown document into a notebook data structure.
|
Converts the given Markdown document into a notebook data structure.
|
||||||
|
|
||||||
Returns the notebook structure and a list of informative messages/warnings
|
Returns the notebook struct and info map with the following keys:
|
||||||
related to the imported input.
|
|
||||||
|
* `: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
|
defdelegate notebook_from_livemd(markdown), to: Livebook.LiveMarkdown.Import
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,14 @@ defmodule Livebook.LiveMarkdown.Import do
|
||||||
{notebook, stamp_hub_id, build_messages} = build_notebook(elements)
|
{notebook, stamp_hub_id, build_messages} = build_notebook(elements)
|
||||||
{notebook, postprocess_messages} = postprocess_notebook(notebook)
|
{notebook, postprocess_messages} = postprocess_notebook(notebook)
|
||||||
|
|
||||||
{notebook, metadata_messages} =
|
{notebook, verified_hub_id, metadata_messages} =
|
||||||
postprocess_stamp(notebook, markdown, stamp_data, stamp_hub_id)
|
postprocess_stamp(notebook, markdown, stamp_data, stamp_hub_id)
|
||||||
|
|
||||||
messages =
|
messages =
|
||||||
earmark_messages ++
|
earmark_messages ++
|
||||||
rewrite_messages ++ build_messages ++ postprocess_messages ++ metadata_messages
|
rewrite_messages ++ build_messages ++ postprocess_messages ++ metadata_messages
|
||||||
|
|
||||||
{notebook, messages}
|
{notebook, %{warnings: messages, verified_hub_id: verified_hub_id}}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp earmark_message_to_string({_severity, line_number, message}) do
|
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([{:stamp, data} | elements]), do: {data, elements}
|
||||||
defp take_stamp_data(elements), do: {nil, 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
|
defp postprocess_stamp(notebook, notebook_source, stamp_data, stamp_hub_id) do
|
||||||
{hub, offline?} =
|
{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?)
|
teams_enabled = is_struct(hub, Livebook.Hubs.Team) and (not offline? or valid_stamp?)
|
||||||
|
|
||||||
notebook = %{notebook | teams_enabled: teams_enabled}
|
notebook = %{notebook | teams_enabled: teams_enabled}
|
||||||
{notebook, messages}
|
verified_hub_id = if(valid_stamp?, do: hub.id)
|
||||||
|
|
||||||
|
{notebook, verified_hub_id, messages}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp safe_binary_slice(binary, start, size)
|
defp safe_binary_slice(binary, start, size)
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ defmodule Livebook.Notebook.Learn do
|
||||||
markdown = File.read!(path)
|
markdown = File.read!(path)
|
||||||
# Parse the file to ensure no warnings and read the title.
|
# 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.
|
# 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
|
if warnings != [] do
|
||||||
items = Enum.map(warnings, &("- " <> &1))
|
items = Enum.map(warnings, &("- " <> &1))
|
||||||
|
|
@ -197,7 +197,9 @@ defmodule Livebook.Notebook.Learn do
|
||||||
raise NotFoundError, slug: slug
|
raise NotFoundError, slug: slug
|
||||||
|
|
||||||
notebook_info ->
|
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}
|
{notebook, notebook_info.files}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ defmodule LivebookWeb.OpenLive do
|
||||||
defp file_from_params(_params), do: Livebook.Settings.default_file_system_home()
|
defp file_from_params(_params), do: Livebook.Settings.default_file_system_home()
|
||||||
|
|
||||||
defp import_source(socket, source, session_opts) do
|
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 =
|
||||||
socket
|
socket
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ defmodule LivebookWeb.SessionHelpers do
|
||||||
@spec fork_notebook(Socket.t(), FileSystem.File.t()) :: Socket.t()
|
@spec fork_notebook(Socket.t(), FileSystem.File.t()) :: Socket.t()
|
||||||
def fork_notebook(socket, file) do
|
def fork_notebook(socket, file) do
|
||||||
case import_notebook(file) do
|
case import_notebook(file) do
|
||||||
{:ok, {notebook, messages}} ->
|
{:ok, {notebook, %{warnings: messages}}} ->
|
||||||
notebook = Livebook.Notebook.forked(notebook)
|
notebook = Livebook.Notebook.forked(notebook)
|
||||||
files_dir = Session.files_dir_for_notebook(file)
|
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()
|
@spec open_notebook(Socket.t(), FileSystem.File.t()) :: Socket.t()
|
||||||
def open_notebook(socket, file) do
|
def open_notebook(socket, file) do
|
||||||
case import_notebook(file) do
|
case import_notebook(file) do
|
||||||
{:ok, {notebook, messages}} ->
|
{:ok, {notebook, %{warnings: messages}}} ->
|
||||||
socket
|
socket
|
||||||
|> put_import_warnings(messages)
|
|> put_import_warnings(messages)
|
||||||
|> create_session(notebook: notebook, file: file, origin: {:file, file})
|
|> 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
|
defp open_notebook(socket, origin, fallback_locations, requested_url) do
|
||||||
case fetch_content_with_fallbacks(origin, fallback_locations) do
|
case fetch_content_with_fallbacks(origin, fallback_locations) do
|
||||||
{:ok, content} ->
|
{: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
|
# If the current session has no file, fork the notebook
|
||||||
fork? = socket.private.data.file == nil
|
fork? = socket.private.data.file == nil
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ defmodule Livebook.AppsTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
import ExUnit.CaptureLog
|
import ExUnit.CaptureLog
|
||||||
|
import Livebook.HubHelpers
|
||||||
|
|
||||||
describe "deploy_apps_in_dir/1" do
|
describe "deploy_apps_in_dir/1" do
|
||||||
@tag :tmp_dir
|
@tag :tmp_dir
|
||||||
|
|
@ -39,6 +40,66 @@ defmodule Livebook.AppsTest do
|
||||||
Livebook.App.close(app2.pid)
|
Livebook.App.close(app2.pid)
|
||||||
end
|
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
|
@tag :tmp_dir
|
||||||
test "skips apps with incomplete config and warns", %{tmp_dir: tmp_dir} do
|
test "skips apps with incomplete config and warns", %{tmp_dir: tmp_dir} do
|
||||||
app_path = Path.join(tmp_dir, "app.livemd")
|
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).
|
# Match only on the relevant fields as some may be generated (ids).
|
||||||
|
|
||||||
|
|
@ -159,7 +159,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
| Maine | ME | Augusta |
|
| Maine | ME | Augusta |
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -188,7 +188,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
Some markdown.
|
Some markdown.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "Untitled notebook",
|
name: "Untitled notebook",
|
||||||
|
|
@ -213,7 +213,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
###### Tiny heading
|
###### Tiny heading
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, messages} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "Untitled notebook",
|
name: "Untitled notebook",
|
||||||
|
|
@ -257,7 +257,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
## # Section
|
## # Section
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My *Notebook*",
|
name: "My *Notebook*",
|
||||||
|
|
@ -278,7 +278,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
## Actual section
|
## Actual section
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My 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{
|
assert %Notebook{
|
||||||
name: "Untitled notebook",
|
name: "Untitled notebook",
|
||||||
|
|
@ -337,7 +337,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
Some markdown.
|
Some markdown.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, messages} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -369,7 +369,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
Some markdown.
|
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
|
assert ["line 3 - closing unclosed backquotes ` at end of input"] == messages
|
||||||
end
|
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{
|
assert %Notebook{
|
||||||
name: "My 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{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -499,7 +499,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
Cell 2
|
Cell 2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -543,7 +543,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
Cell 1
|
Cell 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -581,10 +581,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
Cell 1
|
Cell 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook,
|
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||||
[
|
|
||||||
"found an invalid sequence of comments at the beginning, make sure custom comments are at the very top"
|
|
||||||
]} = Import.notebook_from_livemd(markdown)
|
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -603,6 +600,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
} = notebook
|
} = notebook
|
||||||
|
|
||||||
|
assert messages == [
|
||||||
|
"found an invalid sequence of comments at the beginning, make sure custom comments are at the very top"
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "outputs" do
|
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{
|
assert %Notebook{
|
||||||
name: "My 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{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -714,7 +715,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# My Notebook
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{name: "My Notebook", persist_outputs: true} = notebook
|
assert %Notebook{name: "My Notebook", persist_outputs: true} = notebook
|
||||||
end
|
end
|
||||||
|
|
@ -727,7 +728,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# 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
|
assert %Notebook{name: "My Notebook", autosave_interval_s: 10} = notebook
|
||||||
end
|
end
|
||||||
|
|
@ -739,7 +740,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# My Notebook
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{name: "My Notebook", default_language: :erlang} = notebook
|
assert %Notebook{name: "My Notebook", default_language: :erlang} = notebook
|
||||||
end
|
end
|
||||||
|
|
@ -753,7 +754,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# 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
|
assert %Notebook{name: "My Notebook", hub_id: ^hub_id} = notebook
|
||||||
end
|
end
|
||||||
|
|
@ -765,7 +766,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# 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 messages == ["ignoring notebook Hub with unknown id"]
|
||||||
assert notebook.hub_id != "nonexistent"
|
assert notebook.hub_id != "nonexistent"
|
||||||
|
|
@ -779,7 +780,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# My Notebook
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -803,7 +804,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# My Notebook
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -822,7 +823,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
<!-- livebook:{"livebook_object":"cell_input","name":"length","type":"text","value":"100"} -->
|
<!-- 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 [
|
assert [
|
||||||
"found an input cell, but those are no longer supported, please use Kino.Input instead"
|
"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"} -->
|
<!-- 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 [
|
assert [
|
||||||
"found an input cell, but those are no longer supported, please use Kino.Input instead." <>
|
"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{
|
assert %Notebook{
|
||||||
name: "My 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 [
|
assert [
|
||||||
"found Markdown images pointing to the images/ directory. Using this directory has been deprecated, please use notebook files instead"
|
"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,
|
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||||
[
|
|
||||||
"ignoring the parent section of \"Section 1\", because it comes later in the notebook"
|
|
||||||
]} = Import.notebook_from_livemd(markdown)
|
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -944,6 +942,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
} = notebook
|
} = notebook
|
||||||
|
|
||||||
|
assert messages == [
|
||||||
|
"ignoring the parent section of \"Section 1\", because it comes later in the notebook"
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "import notebook with parent section pointing to the section itself produces a warning" do
|
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,
|
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||||
[
|
|
||||||
"ignoring the parent section of \"Section 1\", because it comes later in the notebook"
|
|
||||||
]} = Import.notebook_from_livemd(markdown)
|
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -972,6 +971,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
} = notebook
|
} = notebook
|
||||||
|
|
||||||
|
assert messages == [
|
||||||
|
"ignoring the parent section of \"Section 1\", because it comes later in the notebook"
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "importing notebook with parent section being a branching section itself produces a warning" do
|
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,
|
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||||
[
|
|
||||||
"ignoring the parent section of \"Section 3\", because it is itself a branching section"
|
|
||||||
]} = Import.notebook_from_livemd(markdown)
|
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My Notebook",
|
name: "My Notebook",
|
||||||
|
|
@ -1022,6 +1022,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
} = notebook
|
} = notebook
|
||||||
|
|
||||||
|
assert messages == [
|
||||||
|
"ignoring the parent section of \"Section 3\", because it is itself a branching section"
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "setup cell" do
|
describe "setup cell" do
|
||||||
|
|
@ -1036,7 +1040,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
## Section 1
|
## Section 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
name: "My 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{
|
assert %Notebook{
|
||||||
name: "My 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}} -->
|
<!-- 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
|
assert %Notebook{hub_secret_names: ["DB_PASSWORD"]} = notebook
|
||||||
end
|
end
|
||||||
|
|
@ -1134,27 +1138,15 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
<!-- livebook:{"offset":58,"stamp":{"token":"invalid","version":1}} -->
|
<!-- 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 %Notebook{hub_secret_names: []} = notebook
|
||||||
|
|
||||||
assert messages == ["failed to verify notebook stamp"]
|
assert messages == ["failed to verify notebook stamp"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "restores hub secret names from notebook stamp using offline hub" do
|
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 = """
|
markdown = """
|
||||||
<!-- livebook:{"hub_id":"team-org-number-2946"} -->
|
<!-- livebook:{"hub_id":"team-org-number-3079"} -->
|
||||||
|
|
||||||
# My Notebook
|
# My Notebook
|
||||||
|
|
||||||
|
|
@ -1164,10 +1156,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
IO.puts("hey")
|
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{
|
assert %Notebook{
|
||||||
hub_id: "personal-hub",
|
hub_id: "personal-hub",
|
||||||
|
|
@ -1177,19 +1169,8 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns a warning when notebook stamp is invalid using offline hub" do
|
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 = """
|
markdown = """
|
||||||
<!-- livebook:{"hub_id":"team-org-number-2946"} -->
|
<!-- livebook:{"hub_id":"team-org-number-3079"} -->
|
||||||
|
|
||||||
# My Notebook
|
# My Notebook
|
||||||
|
|
||||||
|
|
@ -1202,11 +1183,10 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
<!-- livebook:{"offset":58,"stamp":{"token":"invalid","token_signature":"invalid","version":1}} -->
|
<!-- livebook:{"offset":58,"stamp":{"token":"invalid","token_signature":"invalid","version":1}} -->
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert {%Notebook{
|
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||||
hub_id: "personal-hub",
|
|
||||||
hub_secret_names: [],
|
assert %Notebook{hub_id: "personal-hub", teams_enabled: false} = notebook
|
||||||
teams_enabled: false
|
assert messages == ["failed to verify notebook stamp"]
|
||||||
}, ["failed to verify notebook stamp"]} = Import.notebook_from_livemd(markdown)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "sets :teams_enabled to true when the teams hub exist regardless the stamp" do
|
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}} -->
|
<!-- 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
|
assert %Notebook{hub_id: ^hub_id, teams_enabled: true} = notebook
|
||||||
end
|
end
|
||||||
|
|
@ -1240,7 +1220,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# My Notebook
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, []} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: []}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{
|
assert %Notebook{
|
||||||
file_entries: [
|
file_entries: [
|
||||||
|
|
@ -1265,7 +1245,7 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
# My Notebook
|
# My Notebook
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{notebook, messages} = Import.notebook_from_livemd(markdown)
|
{notebook, %{warnings: messages}} = Import.notebook_from_livemd(markdown)
|
||||||
|
|
||||||
assert %Notebook{file_entries: []} = notebook
|
assert %Notebook{file_entries: []} = notebook
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,14 @@ defmodule Livebook.HubHelpers do
|
||||||
import Livebook.Factory
|
import Livebook.Factory
|
||||||
import Phoenix.LiveViewTest
|
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
|
def create_team_hub(user, node) do
|
||||||
hub = build_team_hub(user, node)
|
hub = build_team_hub(user, node)
|
||||||
Livebook.Hubs.save_hub(hub)
|
Livebook.Hubs.save_hub(hub)
|
||||||
|
|
@ -58,6 +66,12 @@ defmodule Livebook.HubHelpers do
|
||||||
refute has_element?(view, hub_element_id(id))
|
refute has_element?(view, hub_element_id(id))
|
||||||
end
|
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 hub_element_id(id), do: "#hubs #hub-#{id}"
|
||||||
|
|
||||||
defp erpc_call(node, fun, args) do
|
defp erpc_call(node, fun, args) do
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@ secret_key =
|
||||||
personal_hub = Livebook.Hubs.fetch_hub!(Livebook.Hubs.Personal.id())
|
personal_hub = Livebook.Hubs.fetch_hub!(Livebook.Hubs.Personal.id())
|
||||||
Livebook.Hubs.Personal.update_hub(personal_hub, %{secret_key: secret_key})
|
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}
|
erl_docs_available? = Code.fetch_docs(:gen_server) != {:error, :chunk_not_found}
|
||||||
|
|
||||||
windows? = match?({:win32, _}, :os.type())
|
windows? = match?({:win32, _}, :os.type())
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue