Skip to content

Commit

Permalink
Check live_session when patching to same LiveView
Browse files Browse the repository at this point in the history
Fixes #3520
  • Loading branch information
SteffenDE committed Nov 19, 2024
1 parent 6784005 commit cea4078
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
37 changes: 29 additions & 8 deletions lib/phoenix_live_view/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1110,11 +1110,9 @@ defmodule Phoenix.LiveView.Channel do
%Session{
id: id,
view: view,
root_view: root_view,
parent_pid: parent,
root_pid: root_pid,
parent_pid: parent,
session: verified_user_session,
assign_new: assign_new,
router: router
} = verified

Expand Down Expand Up @@ -1164,7 +1162,7 @@ defmodule Phoenix.LiveView.Channel do
merged_session = Map.merge(socket_session, verified_user_session)
lifecycle = load_lifecycle(config, route)

case mount_private(parent, root_view, assign_new, connect_params, connect_info, lifecycle) do
case mount_private(verified, connect_params, connect_info, lifecycle) do
{:ok, mount_priv} ->
socket = Utils.configure_socket(socket, mount_priv, action, flash, host_uri)

Expand Down Expand Up @@ -1254,19 +1252,40 @@ defmodule Phoenix.LiveView.Channel do
socket
end

defp mount_private(nil, root_view, assign_new, connect_params, connect_info, lifecycle) do
defp mount_private(%Session{parent_pid: nil} = session, connect_params, connect_info, lifecycle) do
%{
root_view: root_view,
assign_new: assign_new,
live_session_name: live_session_name,
live_session_vsn: live_session_vsn
} = session

{:ok,
%{
connect_params: connect_params,
connect_info: connect_info,
assign_new: {%{}, assign_new},
lifecycle: lifecycle,
root_view: root_view,
live_temp: %{}
live_temp: %{},
live_session_name: live_session_name,
live_session_vsn: live_session_vsn
}}
end

defp mount_private(parent, root_view, assign_new, connect_params, connect_info, lifecycle) do
defp mount_private(
%Session{parent_pid: parent} = session,
connect_params,
connect_info,
lifecycle
) do
%{
root_view: root_view,
assign_new: assign_new,
live_session_name: live_session_name,
live_session_vsn: live_session_vsn
} = session

case sync_with_parent(parent, assign_new) do
{:ok, parent_assigns} ->
# Child live views always ignore the layout on `:use`.
Expand All @@ -1278,7 +1297,9 @@ defmodule Phoenix.LiveView.Channel do
live_layout: false,
lifecycle: lifecycle,
root_view: root_view,
live_temp: %{}
live_temp: %{},
live_session_name: live_session_name,
live_session_vsn: live_session_vsn
}}

{:error, :noproc} ->
Expand Down
5 changes: 4 additions & 1 deletion lib/phoenix_live_view/route.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ defmodule Phoenix.LiveView.Route do
end

def live_link_info!(%Socket{} = socket, view, uri) do
%{private: %{live_session_name: session_name, live_session_vsn: session_version}} = socket

case live_link_info(socket.endpoint, socket.router, uri) do
{:internal, %Route{view: ^view} = route} ->
{:internal,
%Route{view: ^view, live_session: %{name: ^session_name, vsn: ^session_version}} = route} ->
{:internal, route}

{:internal, %Route{view: _view} = route} ->
Expand Down
31 changes: 31 additions & 0 deletions test/phoenix_live_view/router_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -283,5 +283,36 @@ defmodule Phoenix.LiveView.RouterTest do
assert html_response(conn, 200) =~
~r|<div[^>]+>LIVEOVERRIDESTART\-123\-The value is: 123\-LIVEOVERRIDEEND|
end

test "classifies route as external when same view, but different session" do
# previously, a patch to the same LV, but a different path in a different live_session
# would succeed when it should not
{_, %Route{live_session: %{vsn: vsn}}} =
Route.live_link_info(
@endpoint,
Phoenix.LiveViewTest.Support.Router,
"/clock-live-session"
)

socket = %Phoenix.LiveView.Socket{
router: Phoenix.LiveViewTest.Support.Router,
endpoint: @endpoint,
private: %{live_session_name: :test, live_session_vsn: vsn}
}

assert {:external, _} =
Route.live_link_info!(
socket,
Phoenix.LiveViewTest.Support.ClockLive,
"/clock-live-session-admin"
)

assert {:internal, _} =
Route.live_link_info!(
socket,
Phoenix.LiveViewTest.Support.ClockLive,
"/clock-live-session"
)
end
end
end

0 comments on commit cea4078

Please sign in to comment.