From be327ca982654a37d0dc0f977a8e59ded9df1c33 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Wed, 14 Jan 2026 03:17:50 +0100 Subject: [PATCH 1/4] Switch Phoenix back to upstream See for `:sec_websocket_protocol` -> `:sec_websocket_headers` --- changelog.d/phoenix-sec-websocket-headers.change | 1 + lib/pleroma/web.ex | 2 +- lib/pleroma/web/endpoint.ex | 2 +- lib/pleroma/web/mastodon_api/websocket_handler.ex | 12 +++++++----- mix.exs | 3 +-- mix.lock | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 changelog.d/phoenix-sec-websocket-headers.change diff --git a/changelog.d/phoenix-sec-websocket-headers.change b/changelog.d/phoenix-sec-websocket-headers.change new file mode 100644 index 000000000..b3cb4ad3f --- /dev/null +++ b/changelog.d/phoenix-sec-websocket-headers.change @@ -0,0 +1 @@ +Switch patched Phoenix 1.7.14 back to upstream with Phoenix 1.8.0+ diff --git a/lib/pleroma/web.ex b/lib/pleroma/web.ex index e7e7e96f9..1c1333aac 100644 --- a/lib/pleroma/web.ex +++ b/lib/pleroma/web.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Web do def controller do quote do - use Phoenix.Controller, namespace: Pleroma.Web + use Phoenix.Controller, formats: [json: "View", html: "View"] import Plug.Conn diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index bab3c9fd0..fa0bd6c12 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -14,7 +14,7 @@ defmodule Pleroma.Web.Endpoint do websocket: [ path: "/", compress: false, - connect_info: [:sec_websocket_protocol], + connect_info: [:sec_websocket_headers], error_handler: {Pleroma.Web.MastodonAPI.WebsocketHandler, :handle_error, []}, fullsweep_after: 20 ] diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex index 3ed1cdd6c..616f35912 100644 --- a/lib/pleroma/web/mastodon_api/websocket_handler.ex +++ b/lib/pleroma/web/mastodon_api/websocket_handler.ex @@ -245,12 +245,14 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do Plug.Conn.send_resp(conn, 404, "Not Found") end - defp find_access_token(%{ - connect_info: %{sec_websocket_protocol: [token]} - }), - do: token - defp find_access_token(%{params: %{"access_token" => token}}), do: token + defp find_access_token(%{connect_info: %{sec_websocket_headers: sec_headers}}), + do: + Enum.find_value(sec_headers, fn + {"sec-websocket-protocol", v} -> v + _ -> nil + end) + defp find_access_token(_), do: nil end diff --git a/mix.exs b/mix.exs index 48ec9b68f..9f45864e2 100644 --- a/mix.exs +++ b/mix.exs @@ -123,8 +123,7 @@ defmodule Pleroma.Mixfile do # Type `mix help deps` for examples and options. defp deps do [ - {:phoenix, - git: "https://github.com/feld/phoenix", branch: "v1.7.14-websocket-headers", override: true}, + {:phoenix, "~> 1.8.0"}, {:phoenix_ecto, "~> 4.4"}, {:ecto_sql, "~> 3.10"}, {:ecto_enum, "~> 1.4"}, diff --git a/mix.lock b/mix.lock index c469f4f01..60fa6f6b4 100644 --- a/mix.lock +++ b/mix.lock @@ -102,7 +102,7 @@ "open_api_spex": {:hex, :open_api_spex, "3.22.0", "fbf90dc82681dc042a4ee79853c8e989efbba73d9e87439085daf849bbf8bc20", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "dd751ddbdd709bb4a5313e9a24530da6e66594773c7242a0c2592cbd9f589063"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"}, - "phoenix": {:git, "https://github.com/feld/phoenix", "fb6dc76c657422e49600896c64aab4253fceaef6", [branch: "v1.7.14-websocket-headers"]}, + "phoenix": {:hex, :phoenix, "1.8.3", "49ac5e485083cb1495a905e47eb554277bdd9c65ccb4fc5100306b350151aa95", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "36169f95cc2e155b78be93d9590acc3f462f1e5438db06e6248613f27c80caec"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.5", "c4ef322acd15a574a8b1a08eff0ee0a85e73096b53ce1403b6563709f15e1cea", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "26ec3208eef407f31b748cadd044045c6fd485fbff168e35963d2f9dfff28d4b"}, "phoenix_html": {:hex, :phoenix_html, "3.3.4", "42a09fc443bbc1da37e372a5c8e6755d046f22b9b11343bf885067357da21cb3", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0249d3abec3714aff3415e7ee3d9786cb325be3151e6c4b3021502c585bf53fb"}, "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.7", "405880012cb4b706f26dd1c6349125bfc903fb9e44d1ea668adaf4e04d4884b7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "3a8625cab39ec261d48a13b7468dc619c0ede099601b084e343968309bd4d7d7"}, From 6f86883cca5024c57ba8b0ddecd6ca1161d62dd5 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Wed, 14 Jan 2026 05:15:28 +0100 Subject: [PATCH 2/4] Web: remove legacy :set_put_layout plug Phoenix 1.8 requires a View module with put_layout so can't set it that early. It was introduced in 2019 with commit 1097ce6d9f06a7552652c5990cee12e7b7b3cc59 but nothing seems to provide app.html (anymore?) and it would likely better be set by something like OAuthController / OAuthView. --- lib/pleroma/web.ex | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/pleroma/web.ex b/lib/pleroma/web.ex index 1c1333aac..bf7fa86a3 100644 --- a/lib/pleroma/web.ex +++ b/lib/pleroma/web.ex @@ -39,12 +39,6 @@ defmodule Pleroma.Web do alias Pleroma.Web.Router.Helpers, as: Routes - plug(:set_put_layout) - - defp set_put_layout(conn, _) do - put_layout(conn, Pleroma.Config.get(:app_layout, "app.html")) - end - # Marks plugs intentionally skipped and blocks their execution if present in plugs chain defp skip_plug(conn, plug_modules) do plug_modules From ab9fd33762cb8a0cada9e526296d1e96f039b10b Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Mon, 11 May 2026 22:10:08 +0400 Subject: [PATCH 3/4] Fix Phoenix upstream migration regressions --- lib/pleroma/web.ex | 9 ++++++++ .../web/mastodon_api/websocket_handler.ex | 22 ++++++++++++------- .../integration/mastodon_websocket_test.exs | 20 +++++++++++++++++ .../static_fe/static_fe_controller_test.exs | 9 ++++++++ 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/lib/pleroma/web.ex b/lib/pleroma/web.ex index bf7fa86a3..70e7f6458 100644 --- a/lib/pleroma/web.ex +++ b/lib/pleroma/web.ex @@ -39,6 +39,15 @@ defmodule Pleroma.Web do alias Pleroma.Web.Router.Helpers, as: Routes + plug(:set_put_layout) + + defp set_put_layout(conn, _) do + case Pleroma.Config.get(:app_layout, "app.html") do + false -> put_layout(conn, false) + layout -> put_layout(conn, {Pleroma.Web.LayoutView, layout}) + end + end + # Marks plugs intentionally skipped and blocks their execution if present in plugs chain defp skip_plug(conn, plug_modules) do plug_modules diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex index 616f35912..2b698bd5d 100644 --- a/lib/pleroma/web/mastodon_api/websocket_handler.ex +++ b/lib/pleroma/web/mastodon_api/websocket_handler.ex @@ -245,14 +245,20 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do Plug.Conn.send_resp(conn, 404, "Not Found") end - defp find_access_token(%{params: %{"access_token" => token}}), do: token + defp find_access_token(%{connect_info: %{sec_websocket_headers: sec_headers}} = transport_info) do + find_sec_websocket_protocol(sec_headers) || find_access_token_from_params(transport_info) + end - defp find_access_token(%{connect_info: %{sec_websocket_headers: sec_headers}}), - do: - Enum.find_value(sec_headers, fn - {"sec-websocket-protocol", v} -> v - _ -> nil - end) + defp find_access_token(transport_info), do: find_access_token_from_params(transport_info) - defp find_access_token(_), do: nil + defp find_sec_websocket_protocol(sec_headers) do + Enum.find_value(sec_headers, fn + {"sec-websocket-protocol", token} -> token + _ -> nil + end) + end + + defp find_access_token_from_params(%{params: %{"access_token" => token}}), do: token + + defp find_access_token_from_params(_), do: nil end diff --git a/test/pleroma/integration/mastodon_websocket_test.exs b/test/pleroma/integration/mastodon_websocket_test.exs index 47f6f5f76..604382be2 100644 --- a/test/pleroma/integration/mastodon_websocket_test.exs +++ b/test/pleroma/integration/mastodon_websocket_test.exs @@ -279,6 +279,26 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do end) end + test "accepts Phoenix 1.8 sec-websocket headers connect info before query params", %{ + token: token, + user: user + } do + assert {:ok, state} = + Pleroma.Web.MastodonAPI.WebsocketHandler.connect(%{ + params: %{"stream" => "user", "access_token" => "invalid"}, + connect_info: %{ + sec_websocket_headers: [ + {"sec-websocket-version", "13"}, + {"sec-websocket-protocol", token.token} + ] + } + }) + + assert state.user.id == user.id + assert state.oauth_token.id == token.id + assert state.topics != [] + end + test "accepts valid token on client-sent event", %{token: token} do assert {:ok, pid} = start_socket() diff --git a/test/pleroma/web/static_fe/static_fe_controller_test.exs b/test/pleroma/web/static_fe/static_fe_controller_test.exs index 2fae83305..68ded6906 100644 --- a/test/pleroma/web/static_fe/static_fe_controller_test.exs +++ b/test/pleroma/web/static_fe/static_fe_controller_test.exs @@ -28,6 +28,15 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do assert html_response(conn, 200) =~ user.nickname end + test "renders profile HTML inside the default app layout", %{conn: conn, user: user} do + conn = get(conn, "/users/#{user.nickname}") + + html = html_response(conn, 200) + assert html =~ "" + assert html =~ ~s(class="instance-header") + assert html =~ ~s() + end + test "404 when user not found", %{conn: conn} do conn = get(conn, "/users/limpopo") From 8a56cf5c0fe58904ad2e6ae03ee7cddf7d2adc09 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Mon, 11 May 2026 22:19:06 +0400 Subject: [PATCH 4/4] Clarify websocket token precedence test --- test/pleroma/integration/mastodon_websocket_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pleroma/integration/mastodon_websocket_test.exs b/test/pleroma/integration/mastodon_websocket_test.exs index 604382be2..078bb643c 100644 --- a/test/pleroma/integration/mastodon_websocket_test.exs +++ b/test/pleroma/integration/mastodon_websocket_test.exs @@ -279,7 +279,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do end) end - test "accepts Phoenix 1.8 sec-websocket headers connect info before query params", %{ + test "prefers sec-websocket-protocol token over query access_token", %{ token: token, user: user } do