From 3a5e8e5e07deee1dfced1f32298d07a2bf3cfcf7 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Sun, 12 Mar 2023 23:59:10 +0000 Subject: [PATCH 01/11] ensure we send the right files for preferred fe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../web/fallback/redirect_controller.ex | 12 ++--- lib/pleroma/web/plugs/frontend_static.ex | 45 ++++++++++++++++--- lib/pleroma/web/plugs/instance_static.ex | 4 +- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/lib/pleroma/web/fallback/redirect_controller.ex b/lib/pleroma/web/fallback/redirect_controller.ex index 6637848a9..60fc15b9e 100644 --- a/lib/pleroma/web/fallback/redirect_controller.ex +++ b/lib/pleroma/web/fallback/redirect_controller.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Web.Fallback.RedirectController do end def redirector(conn, _params, code \\ 200) do - {:ok, index_content} = File.read(index_file_path()) + {:ok, index_content} = File.read(index_file_path(conn)) response = index_content @@ -51,7 +51,7 @@ defmodule Pleroma.Web.Fallback.RedirectController do end def redirector_with_meta(conn, params) do - {:ok, index_content} = File.read(index_file_path()) + {:ok, index_content} = File.read(index_file_path(conn)) tags = build_tags(conn, params) preloads = preload_data(conn, params) @@ -69,7 +69,7 @@ defmodule Pleroma.Web.Fallback.RedirectController do end def redirector_with_preload(conn, params) do - {:ok, index_content} = File.read(index_file_path()) + {:ok, index_content} = File.read(index_file_path(conn)) preloads = preload_data(conn, params) response = @@ -91,8 +91,10 @@ defmodule Pleroma.Web.Fallback.RedirectController do |> text("") end - defp index_file_path do - Pleroma.Web.Plugs.InstanceStatic.file_path("index.html") + defp index_file_path(conn) do + frontend_type = Pleroma.Web.Plugs.FrontendStatic.preferred_or_fallback(conn, :primary) + + Pleroma.Web.Plugs.InstanceStatic.file_path("index.html", frontend_type) end defp build_tags(conn, params) do diff --git a/lib/pleroma/web/plugs/frontend_static.ex b/lib/pleroma/web/plugs/frontend_static.ex index 6ab8e4667..179f2bd47 100644 --- a/lib/pleroma/web/plugs/frontend_static.ex +++ b/lib/pleroma/web/plugs/frontend_static.ex @@ -5,17 +5,23 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do require Pleroma.Constants + @frontend_cookie_name "preferred_frontend" + @moduledoc """ This is a shim to call `Plug.Static` but with runtime `from` configuration`. It dispatches to the different frontends. """ @behaviour Plug - def file_path(path, frontend_type \\ :primary) do - if configuration = Pleroma.Config.get([:frontends, frontend_type]) do - instance_static_path = Pleroma.Config.get([:instance, :static_dir], "instance/static") + defp instance_static_path do + Pleroma.Config.get([:instance, :static_dir], "instance/static") + end + def file_path(path, frontend_type \\ :primary) + + def file_path(path, frontend_type) when is_atom(frontend_type) do + if configuration = Pleroma.Config.get([:frontends, frontend_type]) do Path.join([ - instance_static_path, + instance_static_path(), "frontends", configuration["name"], configuration["ref"], @@ -26,6 +32,15 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do end end + def file_path(path, frontend_type) when is_binary(frontend_type) do + Path.join([ + instance_static_path(), + "frontends", + frontend_type, + path + ]) + end + def init(opts) do opts |> Keyword.put(:from, "__unconfigured_frontend_static_plug") @@ -36,7 +51,8 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do def call(conn, opts) do with false <- api_route?(conn.path_info), false <- invalid_path?(conn.path_info), - frontend_type <- Map.get(opts, :frontend_type, :primary), + fallback_frontend_type <- Map.get(opts, :frontend_type, :primary), + frontend_type <- preferred_or_fallback(conn, fallback_frontend_type), path when not is_nil(path) <- file_path("", frontend_type) do call_static(conn, opts, path) else @@ -45,6 +61,24 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do end end + def preferred_frontend(conn) do + %{req_cookies: cookies} = + conn + |> Plug.Conn.fetch_cookies() + + Map.get(cookies, @frontend_cookie_name) + end + + def preferred_or_fallback(conn, fallback) do + case preferred_frontend(conn) do + nil -> + fallback + + frontend -> + frontend + end + end + defp invalid_path?(list) do invalid_path?(list, :binary.compile_pattern(["/", "\\", ":", "\0"])) end @@ -62,6 +96,7 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do defp call_static(conn, opts, from) do opts = Map.put(opts, :from, from) + IO.inspect(opts, label: "opts") Plug.Static.call(conn, opts) end end diff --git a/lib/pleroma/web/plugs/instance_static.ex b/lib/pleroma/web/plugs/instance_static.ex index f82b9a098..d2a674d39 100644 --- a/lib/pleroma/web/plugs/instance_static.ex +++ b/lib/pleroma/web/plugs/instance_static.ex @@ -13,11 +13,11 @@ defmodule Pleroma.Web.Plugs.InstanceStatic do """ @behaviour Plug - def file_path(path) do + def file_path(path, frontend_type \\ :primary) do instance_path = Path.join(Pleroma.Config.get([:instance, :static_dir], "instance/static/"), path) - frontend_path = Pleroma.Web.Plugs.FrontendStatic.file_path(path, :primary) + frontend_path = Pleroma.Web.Plugs.FrontendStatic.file_path(path, frontend_type) (File.exists?(instance_path) && instance_path) || (frontend_path && File.exists?(frontend_path) && frontend_path) || From 004f9fa69b406ffff211cbcefd2871302462a39c Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Tue, 28 Mar 2023 12:44:52 +0100 Subject: [PATCH 02/11] add selection UI --- config/description.exs | 6 ++++++ .../frontend_switcher_controller.ex | 20 +++++++++++++++++++ .../frontend_switcher_view.ex | 3 +++ lib/pleroma/web/plugs/frontend_static.ex | 15 ++++++++++++-- lib/pleroma/web/router.ex | 9 ++++----- .../frontend_switcher/switch.html.eex | 7 +++++++ 6 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 lib/pleroma/web/frontend_switcher/frontend_switcher_controller.ex create mode 100644 lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex create mode 100644 lib/pleroma/web/templates/frontend_switcher/switch.html.eex diff --git a/config/description.exs b/config/description.exs index 2755c36f9..e5e7160d4 100644 --- a/config/description.exs +++ b/config/description.exs @@ -3328,6 +3328,12 @@ config :pleroma, :config_description, [ description: "A map containing available frontends and parameters for their installation.", children: frontend_options + }, + %{ + key: :pickable, + type: {:list, :string}, + description: + "A list containing all frontends users can pick as their preference, format is :name/:ref, e.g pleroma-fe/stable." } ] }, diff --git a/lib/pleroma/web/frontend_switcher/frontend_switcher_controller.ex b/lib/pleroma/web/frontend_switcher/frontend_switcher_controller.ex new file mode 100644 index 000000000..4f3efb3aa --- /dev/null +++ b/lib/pleroma/web/frontend_switcher/frontend_switcher_controller.ex @@ -0,0 +1,20 @@ +defmodule Pleroma.Web.FrontendSwitcher.FrontendSwitcherController do + use Pleroma.Web, :controller + alias Pleroma.Config + + @doc "GET /frontend_switcher" + def switch(conn, _params) do + pickable = Config.get([:frontends, :pickable], []) + + conn + |> put_view(Pleroma.Web.FrontendSwitcher.FrontendSwitcherView) + |> render("switch.html", choices: pickable) + end + + @doc "POST /frontend_switcher" + def do_switch(conn, params) do + conn + |> put_resp_cookie("preferred_frontend", params["frontend"]) + |> html("") + end +end diff --git a/lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex b/lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex new file mode 100644 index 000000000..e57e4e10b --- /dev/null +++ b/lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex @@ -0,0 +1,3 @@ +defmodule Pleroma.Web.FrontendSwitcher.FrontendSwitcherView do + use Pleroma.Web, :view +end diff --git a/lib/pleroma/web/plugs/frontend_static.ex b/lib/pleroma/web/plugs/frontend_static.ex index 179f2bd47..3708e9e4a 100644 --- a/lib/pleroma/web/plugs/frontend_static.ex +++ b/lib/pleroma/web/plugs/frontend_static.ex @@ -49,6 +49,7 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do end def call(conn, opts) do + IO.inspect("OPTS: #{inspect(opts)}") with false <- api_route?(conn.path_info), false <- invalid_path?(conn.path_info), fallback_frontend_type <- Map.get(opts, :frontend_type, :primary), @@ -69,16 +70,26 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do Map.get(cookies, @frontend_cookie_name) end - def preferred_or_fallback(conn, fallback) do + # Only override primary frontend + def preferred_or_fallback(conn, :primary) do case preferred_frontend(conn) do nil -> - fallback + :primary frontend -> frontend end end +<<<<<<< HEAD +======= + def preferred_or_fallback(conn, fallback), do: fallback + + defp enabled?(if_opt) when is_function(if_opt), do: if_opt.() + defp enabled?(true), do: true + defp enabled?(_), do: false + +>>>>>>> de64c6c54a (add selection UI) defp invalid_path?(list) do invalid_path?(list, :binary.compile_pattern(["/", "\\", ":", "\0"])) end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index a8636cfba..7658f8509 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -637,11 +637,6 @@ defmodule Pleroma.Web.Router do end scope "/api/v1/pleroma", Pleroma.Web.MastodonAPI do - pipe_through(:api) - get("/accounts/:id/endorsements", AccountController, :endorsements) - end - - scope "/api/v2/pleroma", Pleroma.Web.PleromaAPI do scope [] do pipe_through(:authenticated_api) get("/chats", ChatController, :index2) @@ -901,7 +896,11 @@ defmodule Pleroma.Web.Router do scope "/", Pleroma.Web do pipe_through(:browser) + get("/mailer/unsubscribe/:token", Mailer.SubscriptionController, :unsubscribe) + + get("/frontend_switcher", FrontendSwitcher.FrontendSwitcherController, :switch) + post("/frontend_switcher", FrontendSwitcher.FrontendSwitcherController, :do_switch) end pipeline :ap_service_actor do diff --git a/lib/pleroma/web/templates/frontend_switcher/switch.html.eex b/lib/pleroma/web/templates/frontend_switcher/switch.html.eex new file mode 100644 index 000000000..0692ddfb8 --- /dev/null +++ b/lib/pleroma/web/templates/frontend_switcher/switch.html.eex @@ -0,0 +1,7 @@ +

Switch Frontend

+ +<%= form_for @conn, Routes.frontend_switcher_path(@conn, :do_switch), fn f -> %> + <%= select(f, :frontend, @choices) %> + + <%= submit do: "submit" %> +<% end %> From bb44501a9eb9c2ba95d362de47f23b0963689b43 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Sun, 12 Mar 2023 23:24:07 +0000 Subject: [PATCH 03/11] Add frontend preference route --- .../pleroma_frontend_settings_operation.ex | 62 +++++++++++++++++++ .../frontend_settings_controller.ex | 37 +++++++++++ lib/pleroma/web/router.ex | 12 ++++ 3 files changed, 111 insertions(+) create mode 100644 lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex create mode 100644 lib/pleroma/web/pleroma_api/controllers/frontend_settings_controller.ex diff --git a/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex new file mode 100644 index 000000000..6d1e23277 --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex @@ -0,0 +1,62 @@ +defmodule Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Schema + import Pleroma.Web.ApiSpec.Helpers + + @spec open_api_operation(atom) :: Operation.t() + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def available_frontends_operation() do + %Operation{ + tags: ["Frontends"], + summary: "Frontend Settings Profiles", + description: "List frontend setting profiles", + operationId: "PleromaAPI.FrontendSettingsController.available_frontends", + responses: %{ + 200 => + Operation.response("Frontends", "application/json", %Schema{ + type: :array, + items: %Schema{ + type: :string + } + }) + } + } + end + + def update_preferred_frontend_operation() do + %Operation{ + tags: ["Frontends"], + summary: "Frontend Settings Profiles", + description: "List frontend setting profiles", + operationId: "PleromaAPI.FrontendSettingsController.available_frontends", + requestBody: + request_body( + "Frontend", + %Schema{ + type: :object, + required: [:frontend_name], + properties: %{ + frontend_name: %Schema{ + type: :string, + description: "Frontend name" + } + } + }, + required: true + ), + responses: %{ + 200 => + Operation.response("Frontends", "application/json", %Schema{ + type: :array, + items: %Schema{ + type: :string + } + }) + } + } + end +end diff --git a/lib/pleroma/web/pleroma_api/controllers/frontend_settings_controller.ex b/lib/pleroma/web/pleroma_api/controllers/frontend_settings_controller.ex new file mode 100644 index 000000000..41531c97e --- /dev/null +++ b/lib/pleroma/web/pleroma_api/controllers/frontend_settings_controller.ex @@ -0,0 +1,37 @@ +defmodule Pleroma.Web.PleromaAPI.FrontendSettingsController do + use Pleroma.Web, :controller + + alias Pleroma.Web.Plugs.OAuthScopesPlug + + plug( + OAuthScopesPlug, + %{fallback: :proceed_unauthenticated, scopes: []} + when action in [ + :available_frontends, + :update_preferred_frontend + ] + ) + + plug(Pleroma.Web.ApiSpec.CastAndValidate) + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation + + action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + + @doc "GET /api/v1/pleroma/preferred_frontend/available" + def available_frontends(conn, _params) do + available = Pleroma.Config.get([:frontends, :pickable]) + + conn + |> json(available) + end + + @doc "PUT /api/v1/pleroma/preferred_frontend" + def update_preferred_frontend( + %{body_params: %{frontend_name: preferred_frontend}} = conn, + _params + ) do + conn + |> put_resp_cookie("preferred_frontend", preferred_frontend) + |> json(%{frontend_name: preferred_frontend}) + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 7658f8509..46cb3a409 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -561,6 +561,18 @@ defmodule Pleroma.Web.Router do get("/apps", AppController, :index) get("/statuses/:id/reactions/:emoji", EmojiReactionController, :index) get("/statuses/:id/reactions", EmojiReactionController, :index) + + get( + "/preferred_frontend/available", + FrontendSettingsController, + :available_frontends + ) + + put( + "/preferred_frontend", + FrontendSettingsController, + :update_preferred_frontend + ) end scope "/api/v0/pleroma", Pleroma.Web.PleromaAPI do From 8827e511704b97ee84fa61c68bdfcb5868518dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20=C5=9Awi=C4=85tkowski?= Date: Sat, 3 Feb 2024 14:24:03 +0100 Subject: [PATCH 04/11] Fix OpenAPI spec for preferred_frontend endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec was copied from another endpoint, including the operation id, leading to scrubbing the valid parameters from the request and simply not working. Signed-off-by: nicole mikołajczyk --- .../pleroma_frontend_settings_operation.ex | 6 +++--- lib/pleroma/web/plugs/frontend_static.ex | 7 ------- .../frontend_settings_controller_test.exs | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 test/pleroma/web/pleroma_api/controllers/frontend_settings_controller_test.exs diff --git a/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex index 6d1e23277..812b40e14 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex @@ -30,9 +30,9 @@ defmodule Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation do def update_preferred_frontend_operation() do %Operation{ tags: ["Frontends"], - summary: "Frontend Settings Profiles", - description: "List frontend setting profiles", - operationId: "PleromaAPI.FrontendSettingsController.available_frontends", + summary: "Update preferred frontend setting", + description: "Store preferred frontend in cookies", + operationId: "PleromaAPI.FrontendSettingsController.update_preferred_frontend", requestBody: request_body( "Frontend", diff --git a/lib/pleroma/web/plugs/frontend_static.ex b/lib/pleroma/web/plugs/frontend_static.ex index 3708e9e4a..2808f96fc 100644 --- a/lib/pleroma/web/plugs/frontend_static.ex +++ b/lib/pleroma/web/plugs/frontend_static.ex @@ -81,15 +81,8 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do end end -<<<<<<< HEAD -======= def preferred_or_fallback(conn, fallback), do: fallback - defp enabled?(if_opt) when is_function(if_opt), do: if_opt.() - defp enabled?(true), do: true - defp enabled?(_), do: false - ->>>>>>> de64c6c54a (add selection UI) defp invalid_path?(list) do invalid_path?(list, :binary.compile_pattern(["/", "\\", ":", "\0"])) end diff --git a/test/pleroma/web/pleroma_api/controllers/frontend_settings_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/frontend_settings_controller_test.exs new file mode 100644 index 000000000..8c62a5463 --- /dev/null +++ b/test/pleroma/web/pleroma_api/controllers/frontend_settings_controller_test.exs @@ -0,0 +1,19 @@ +defmodule Pleroma.Web.PleromaAPI.FrontendSettingsControllerTest do + use Pleroma.Web.ConnCase, async: false + + import Pleroma.Factory + + describe "PUT /api/v1/pleroma/preferred_frontend" do + test "sets a cookie with selected frontend" do + %{conn: conn} = oauth_access(["read"]) + + response = + conn + |> put_req_header("content-type", "application/json") + |> put("/api/v1/pleroma/preferred_frontend", %{"frontend_name" => "pleroma-fe/stable"}) + + json_response_and_validate_schema(response, 200) + assert %{"preferred_frontend" => %{value: "pleroma-fe/stable"}} = response.resp_cookies + end + end +end From fd177a363be9fbaac11bc37893ad8a2acbe9bd02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 28 Nov 2025 15:59:07 +0100 Subject: [PATCH 05/11] cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- config/description.exs | 8 ++++---- lib/pleroma/web/plugs/frontend_static.ex | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/config/description.exs b/config/description.exs index e5e7160d4..a8a201e33 100644 --- a/config/description.exs +++ b/config/description.exs @@ -3330,10 +3330,10 @@ config :pleroma, :config_description, [ children: frontend_options }, %{ - key: :pickable, - type: {:list, :string}, - description: - "A list containing all frontends users can pick as their preference, format is :name/:ref, e.g pleroma-fe/stable." + key: :pickable, + type: {:list, :string}, + description: + "A list containing all frontends users can pick as their preference, format is :name/:ref, e.g pleroma-fe/stable." } ] }, diff --git a/lib/pleroma/web/plugs/frontend_static.ex b/lib/pleroma/web/plugs/frontend_static.ex index 2808f96fc..6c0186f14 100644 --- a/lib/pleroma/web/plugs/frontend_static.ex +++ b/lib/pleroma/web/plugs/frontend_static.ex @@ -49,7 +49,6 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do end def call(conn, opts) do - IO.inspect("OPTS: #{inspect(opts)}") with false <- api_route?(conn.path_info), false <- invalid_path?(conn.path_info), fallback_frontend_type <- Map.get(opts, :frontend_type, :primary), @@ -81,7 +80,7 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do end end - def preferred_or_fallback(conn, fallback), do: fallback + def preferred_or_fallback(_conn, fallback), do: fallback defp invalid_path?(list) do invalid_path?(list, :binary.compile_pattern(["/", "\\", ":", "\0"])) @@ -100,7 +99,6 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do defp call_static(conn, opts, from) do opts = Map.put(opts, :from, from) - IO.inspect(opts, label: "opts") Plug.Static.call(conn, opts) end end From 1fd94ed001c6413301b4c1cd1fb4c8f7bf5f4867 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Fri, 14 Apr 2023 17:42:40 +0100 Subject: [PATCH 06/11] ensure only pickable frontends can be returned --- lib/pleroma/web/plugs/frontend_static.ex | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/plugs/frontend_static.ex b/lib/pleroma/web/plugs/frontend_static.ex index 6c0186f14..f1df185e3 100644 --- a/lib/pleroma/web/plugs/frontend_static.ex +++ b/lib/pleroma/web/plugs/frontend_static.ex @@ -76,7 +76,11 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do :primary frontend -> - frontend + if Enum.member?(Pleroma.Config.get([:frontends, :pickable], []), frontend) do + frontend + else + :primary + end end end From f1586f023050ff071713a63ee9c5e5eb1d135093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 28 Nov 2025 16:01:00 +0100 Subject: [PATCH 07/11] im bad at merge conflicts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- lib/pleroma/web/router.ex | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 46cb3a409..acf8df538 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -649,6 +649,11 @@ defmodule Pleroma.Web.Router do end scope "/api/v1/pleroma", Pleroma.Web.MastodonAPI do + pipe_through(:api) + get("/accounts/:id/endorsements", AccountController, :endorsements) + end + + scope "/api/v2/pleroma", Pleroma.Web.PleromaAPI do scope [] do pipe_through(:authenticated_api) get("/chats", ChatController, :index2) From a80776b2607bbfdab888d2939c1597b1ad31f220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 28 Nov 2025 16:10:02 +0100 Subject: [PATCH 08/11] make it work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex | 2 ++ .../frontend_switcher/{ => frontend_switcher}/switch.html.eex | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) rename lib/pleroma/web/templates/frontend_switcher/{ => frontend_switcher}/switch.html.eex (86%) diff --git a/lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex b/lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex index e57e4e10b..284477431 100644 --- a/lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex +++ b/lib/pleroma/web/frontend_switcher/frontend_switcher_view.ex @@ -1,3 +1,5 @@ defmodule Pleroma.Web.FrontendSwitcher.FrontendSwitcherView do use Pleroma.Web, :view + + import Phoenix.HTML.Form end diff --git a/lib/pleroma/web/templates/frontend_switcher/switch.html.eex b/lib/pleroma/web/templates/frontend_switcher/frontend_switcher/switch.html.eex similarity index 86% rename from lib/pleroma/web/templates/frontend_switcher/switch.html.eex rename to lib/pleroma/web/templates/frontend_switcher/frontend_switcher/switch.html.eex index 0692ddfb8..c801c8ee8 100644 --- a/lib/pleroma/web/templates/frontend_switcher/switch.html.eex +++ b/lib/pleroma/web/templates/frontend_switcher/frontend_switcher/switch.html.eex @@ -1,4 +1,4 @@ -

Switch Frontend

+

Switch frontend

<%= form_for @conn, Routes.frontend_switcher_path(@conn, :do_switch), fn f -> %> <%= select(f, :frontend, @choices) %> From 5c139be42e46bef5ec37d974804fc21c704fcec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 28 Nov 2025 16:30:03 +0100 Subject: [PATCH 09/11] Add tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../web/plugs/frontend_static_plug_test.exs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/pleroma/web/plugs/frontend_static_plug_test.exs b/test/pleroma/web/plugs/frontend_static_plug_test.exs index a7af3e74e..cbe200738 100644 --- a/test/pleroma/web/plugs/frontend_static_plug_test.exs +++ b/test/pleroma/web/plugs/frontend_static_plug_test.exs @@ -97,6 +97,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do "users", "tags", "mailer", + "frontend_switcher", "inbox", "relay", "internal", @@ -113,4 +114,36 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do assert expected_routes == Pleroma.Web.Router.get_api_routes() end + + describe "preferred frontend cookie handling" do + test "returns preferred frontend file", %{conn: conn} do + name = "test-fe" + ref = "develop" + + clear_config([:frontends, :pickable], ["#{name}/#{ref}"]) + path = "#{@dir}/frontends/#{name}/#{ref}" + + Pleroma.Backports.mkdir_p!(path) + File.write!("#{path}/index.html", "from frontend plug") + + index = + conn + |> put_req_cookie("preferred_frontend", "#{name}/#{ref}") + |> get("/") + + assert html_response(index, 200) == "from frontend plug" + end + + test "only returns content from pickable frontends", %{conn: conn} do + clear_config([:instance, :static_dir], "instance/static") + clear_config([:frontends, :pickable], ["pleroma-fe/develop", "pl-fe/develop"]) + + config_file = + conn + |> put_req_cookie("preferred_frontend", "../../../config") + |> get("/config.exs") + + refute response(config_file, 200) =~ "import Config" + end + end end From 78c4332218a755ae81055d6ecd1ddf4fa68e8fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 28 Nov 2025 16:32:51 +0100 Subject: [PATCH 10/11] spec, changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- changelog.d/preferred-frontend.add | 1 + lib/pleroma/web/api_spec.ex | 3 ++- .../operations/pleroma_frontend_settings_operation.ex | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 changelog.d/preferred-frontend.add diff --git a/changelog.d/preferred-frontend.add b/changelog.d/preferred-frontend.add new file mode 100644 index 000000000..145e9451b --- /dev/null +++ b/changelog.d/preferred-frontend.add @@ -0,0 +1 @@ +Allow users to select preferred frontend diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex index 3e0ac3704..5006167ea 100644 --- a/lib/pleroma/web/api_spec.ex +++ b/lib/pleroma/web/api_spec.ex @@ -151,7 +151,8 @@ defmodule Pleroma.Web.ApiSpec do "Suggestions", "Announcements", "Remote interaction", - "Others" + "Others", + "Preferred frontends" ] } ] diff --git a/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex index 812b40e14..8b74fe02c 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex @@ -11,8 +11,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation do def available_frontends_operation() do %Operation{ - tags: ["Frontends"], - summary: "Frontend Settings Profiles", + tags: ["Preferred frontends"], + summary: "Frontend settings profiles", description: "List frontend setting profiles", operationId: "PleromaAPI.FrontendSettingsController.available_frontends", responses: %{ @@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation do def update_preferred_frontend_operation() do %Operation{ - tags: ["Frontends"], + tags: ["Preferred frontends"], summary: "Update preferred frontend setting", description: "Store preferred frontend in cookies", operationId: "PleromaAPI.FrontendSettingsController.update_preferred_frontend", From cc51ee8662a4ed47f6305c4b41f62469b188a8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 29 Nov 2025 15:53:10 +0100 Subject: [PATCH 11/11] analysis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../pleroma_frontend_settings_operation.ex | 15 +++++++++------ .../frontend_switcher_controller.ex | 2 +- .../frontend_settings_controller_test.exs | 2 -- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex index 8b74fe02c..923e4fcc9 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_frontend_settings_operation.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation do apply(__MODULE__, operation, []) end - def available_frontends_operation() do + def available_frontends_operation do %Operation{ tags: ["Preferred frontends"], summary: "Frontend settings profiles", @@ -27,7 +27,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation do } end - def update_preferred_frontend_operation() do + def update_preferred_frontend_operation do %Operation{ tags: ["Preferred frontends"], summary: "Update preferred frontend setting", @@ -50,10 +50,13 @@ defmodule Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation do ), responses: %{ 200 => - Operation.response("Frontends", "application/json", %Schema{ - type: :array, - items: %Schema{ - type: :string + Operation.response("Preferred frontend", "application/json", %Schema{ + type: :object, + properties: %{ + frontend_name: %Schema{ + type: :string, + description: "Frontend name" + } } }) } diff --git a/lib/pleroma/web/frontend_switcher/frontend_switcher_controller.ex b/lib/pleroma/web/frontend_switcher/frontend_switcher_controller.ex index 4f3efb3aa..18752c63c 100644 --- a/lib/pleroma/web/frontend_switcher/frontend_switcher_controller.ex +++ b/lib/pleroma/web/frontend_switcher/frontend_switcher_controller.ex @@ -15,6 +15,6 @@ defmodule Pleroma.Web.FrontendSwitcher.FrontendSwitcherController do def do_switch(conn, params) do conn |> put_resp_cookie("preferred_frontend", params["frontend"]) - |> html("") + |> html(~s()) end end diff --git a/test/pleroma/web/pleroma_api/controllers/frontend_settings_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/frontend_settings_controller_test.exs index 8c62a5463..1f14c102f 100644 --- a/test/pleroma/web/pleroma_api/controllers/frontend_settings_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/frontend_settings_controller_test.exs @@ -1,8 +1,6 @@ defmodule Pleroma.Web.PleromaAPI.FrontendSettingsControllerTest do use Pleroma.Web.ConnCase, async: false - import Pleroma.Factory - describe "PUT /api/v1/pleroma/preferred_frontend" do test "sets a cookie with selected frontend" do %{conn: conn} = oauth_access(["read"])