livebook/test/livebook_web/live/app_auth_live_test.exs

149 lines
4.4 KiB
Elixir
Raw Normal View History

defmodule LivebookWeb.AppAuthLiveTest do
use LivebookWeb.ConnCase, async: false
import Phoenix.LiveViewTest
setup ctx do
{slug, app_pid} = create_app(ctx[:app_settings] || %{})
on_exit(fn ->
Livebook.App.close(app_pid)
end)
Application.put_env(:livebook, :authentication_mode, :password)
Application.put_env(:livebook, :password, ctx[:livebook_password])
on_exit(fn ->
Application.put_env(:livebook, :authentication_mode, :disabled)
Application.delete_env(:livebook, :password)
end)
%{slug: slug}
end
defp create_app(app_settings_attrs) do
slug = Livebook.Utils.random_id()
app_settings =
Livebook.Notebook.AppSettings.new()
|> Map.replace!(:slug, slug)
|> Map.merge(app_settings_attrs)
notebook = %{Livebook.Notebook.new() | app_settings: app_settings}
{:ok, app_pid} = Livebook.Apps.deploy(notebook)
{slug, app_pid}
end
# Integration tests for the authentication scenarios
describe "public app" do
@describetag app_settings: %{access_type: :public}
test "does not require authentication", %{conn: conn, slug: slug} do
{:ok, view, _} =
conn
|> live(~p"/apps/#{slug}")
|> follow_redirect(conn)
assert render(view) =~ "Untitled notebook"
end
end
describe "protected app" do
@describetag livebook_password: "long_livebook_password"
@describetag app_settings: %{access_type: :protected, password: "long_app_password"}
test "redirect to auth page when not authenticated", %{conn: conn, slug: slug} do
2023-02-23 02:34:54 +08:00
{:error, {:live_redirect, %{to: to}}} = live(conn, ~p"/apps/#{slug}")
assert to == "/apps/#{slug}/authenticate"
end
test "shows an error on invalid password", %{conn: conn, slug: slug} do
2023-02-23 02:34:54 +08:00
{:ok, view, _} = live(conn, ~p"/apps/#{slug}/authenticate")
assert view
|> element("form")
|> render_submit(%{password: "invalid password"}) =~ "app password is invalid"
end
test "persists authentication across requests", %{conn: conn, slug: slug} do
2023-02-23 02:34:54 +08:00
{:ok, view, _} = live(conn, ~p"/apps/#{slug}/authenticate")
view
|> element("form")
|> render_submit(%{password: "long_app_password"})
# The token is stored on the client
assert_push_event(view, "persist_app_auth", %{"slug" => ^slug, "token" => token})
assert {:error, {:live_redirect, %{to: to}}} = render_hook(view, "app_auth_persisted")
assert to == "/apps/#{slug}"
# Then, the client passes the token in connect params
conn = put_connect_params(conn, %{"app_auth_token" => token})
{:ok, view, _} =
conn
|> live("/apps/#{slug}")
|> follow_redirect(conn)
assert render(view) =~ "Untitled notebook"
# The auth page redirects to the app
{:error, {:live_redirect, %{to: to}}} = live(conn, "/apps/#{slug}/authenticate")
assert to == "/apps/#{slug}"
end
test "when redirected from app session page, returns to that same page",
%{conn: conn, slug: slug} do
{:ok, %{sessions: [%{id: session_id}]}} = Livebook.Apps.fetch_app(slug)
# We navigate to a specific session and get redirected to auth
{:ok, view, _} =
conn
|> live(~p"/apps/#{slug}/#{session_id}")
|> follow_redirect(conn)
view
|> element("form")
|> render_submit(%{password: "long_app_password"})
assert_push_event(view, "persist_app_auth", %{"slug" => ^slug, "token" => _token})
assert {:error, {:live_redirect, %{to: to}}} = render_hook(view, "app_auth_persisted")
assert to == ~p"/apps/#{slug}/#{session_id}"
end
test "redirects to the app page when authenticating in Livebook", %{conn: conn, slug: slug} do
2023-02-23 02:34:54 +08:00
conn = get(conn, ~p"/authenticate?redirect_to=/apps/#{slug}")
assert redirected_to(conn) == "/authenticate"
2023-02-23 02:34:54 +08:00
conn = post(conn, ~p"/authenticate", password: "long_livebook_password")
assert redirected_to(conn) == "/apps/#{slug}"
{:ok, view, _} =
conn
|> live(~p"/apps/#{slug}")
|> follow_redirect(conn)
assert render(view) =~ "Untitled notebook"
# The auth page redirects to the app
2023-02-23 02:34:54 +08:00
{:error, {:live_redirect, %{to: to}}} = live(conn, ~p"/apps/#{slug}/authenticate")
assert to == "/apps/#{slug}"
end
end
test "redirects to homepage when accessing non-existent app", %{conn: conn} do
2023-02-23 02:34:54 +08:00
assert {:error, {:redirect, %{to: "/"}}} = live(conn, ~p"/apps/nonexistent")
end
end