From 271c3a3dd8a22fad2fa4cd6d034c98e1ffc91fb4 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Sun, 26 Jul 2026 11:58:31 +0400 Subject: [PATCH] fix(config): keep search startup settings static --- lib/mix/tasks/pleroma/config.ex | 9 ++++--- lib/pleroma/config/transfer_task.ex | 1 + lib/pleroma/config_db.ex | 26 +++++++++++++++++-- .../controllers/config_controller.ex | 5 +++- test/fixtures/config/static_search.secret.exs | 5 ++++ test/mix/tasks/pleroma/config_test.exs | 8 ++++++ test/pleroma/config/transfer_task_test.exs | 25 ++++++++++++++++++ test/pleroma/config_db_test.exs | 14 ++++++++++ .../controllers/config_controller_test.exs | 20 ++++++++++++-- 9 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 test/fixtures/config/static_search.secret.exs diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex index a10506236..81c41d967 100644 --- a/lib/mix/tasks/pleroma/config.ex +++ b/lib/mix/tasks/pleroma/config.ex @@ -335,9 +335,12 @@ defmodule Mix.Tasks.Pleroma.Config do group |> Pleroma.Config.Loader.filter_group(settings) |> Enum.each(fn {key, value} -> - {:ok, _} = ConfigDB.update_or_create(%{group: group, key: key, value: value}) - - shell_info("Settings for key #{key} migrated.") + if ConfigDB.static?(group, key) do + shell_info("Settings for key #{key} must remain in static configuration; skipping.") + else + {:ok, _} = ConfigDB.update_or_create(%{group: group, key: key, value: value}) + shell_info("Settings for key #{key} migrated.") + end end) shell_info("Settings for group #{inspect(group)} migrated.") diff --git a/lib/pleroma/config/transfer_task.ex b/lib/pleroma/config/transfer_task.ex index 3e59dc4e0..48cb158ca 100644 --- a/lib/pleroma/config/transfer_task.ex +++ b/lib/pleroma/config/transfer_task.ex @@ -47,6 +47,7 @@ defmodule Pleroma.Config.TransferTask do settings = (Repo.all(ConfigDB) ++ deleted_settings) + |> Enum.reject(&ConfigDB.static?/1) |> Enum.map(&merge_with_default/1) started_applications = Application.started_applications() diff --git a/lib/pleroma/config_db.ex b/lib/pleroma/config_db.ex index 2c3df773b..9aa52f7d6 100644 --- a/lib/pleroma/config_db.ex +++ b/lib/pleroma/config_db.ex @@ -23,6 +23,12 @@ defmodule Pleroma.ConfigDB do {:pleroma, :mrf_keyword, :replace} ] + @static_config [ + {:pleroma, Pleroma.Search}, + {:pleroma, Pleroma.Search.ParadeDB}, + {:pleroma, Pleroma.Search.ParadeDB.Repo} + ] + schema "config" do field(:key, Pleroma.EctoType.Config.Atom) field(:group, Pleroma.EctoType.Config.Atom) @@ -32,16 +38,32 @@ defmodule Pleroma.ConfigDB do timestamps() end - @spec get_all_as_keyword() :: keyword() - def get_all_as_keyword do + @spec get_all_as_keyword(keyword()) :: keyword() + def get_all_as_keyword(options \\ []) do ConfigDB |> select([c], {c.group, c.key, c.value}) |> Repo.all() + |> maybe_reject_static(options) |> Enum.reduce([], fn {group, key, value}, acc -> Keyword.update(acc, group, [{key, value}], &Keyword.merge(&1, [{key, value}])) end) end + def static?(%{group: group, key: key}), do: static?(group, key) + def static?(_config), do: false + + def static?(group, key) do + Enum.any?(@static_config, fn {static_group, static_key} -> + group in [static_group, inspect(static_group)] and key in [static_key, inspect(static_key)] + end) + end + + defp maybe_reject_static(configs, exclude_static: true) do + Enum.reject(configs, fn {group, key, _value} -> static?(group, key) end) + end + + defp maybe_reject_static(configs, _options), do: configs + @spec get_all_by_group(atom() | String.t()) :: [t()] def get_all_by_group(group) do from(c in ConfigDB, where: c.group == ^group) |> Repo.all() diff --git a/lib/pleroma/web/admin_api/controllers/config_controller.ex b/lib/pleroma/web/admin_api/controllers/config_controller.ex index 753690d45..4c76d808d 100644 --- a/lib/pleroma/web/admin_api/controllers/config_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/config_controller.ex @@ -75,6 +75,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do Pleroma.Docs.JSON.compiled_descriptions() |> Enum.filter(&allowed_config?(&1, :whitelist)) |> Enum.reject(&allowed_config?(&1, :blacklist)) + |> Enum.reject(&ConfigDB.static?/1) json(conn, translate_descriptions(descriptions)) end @@ -92,7 +93,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do def show(conn, _params) do with :ok <- configurable_from_database() do - configs = ConfigDB.get_all_as_keyword() + configs = ConfigDB.get_all_as_keyword(exclude_static: true) merged = Config.Holder.default_config() @@ -123,6 +124,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do end) end) |> List.flatten() + |> Enum.reject(&ConfigDB.static?/1) render(conn, "index.json", %{ configs: merged, @@ -137,6 +139,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do configs |> Enum.filter(&allowed_config?(&1, :whitelist)) |> Enum.reject(&allowed_config?(&1, :blacklist)) + |> Enum.reject(&(ConfigDB.static?(&1) and not &1[:delete])) |> Enum.map(fn %{group: group, key: key, delete: true} = params -> ConfigDB.delete(%{group: group, key: key, subkeys: params[:subkeys]}) diff --git a/test/fixtures/config/static_search.secret.exs b/test/fixtures/config/static_search.secret.exs new file mode 100644 index 000000000..13f744184 --- /dev/null +++ b/test/fixtures/config/static_search.secret.exs @@ -0,0 +1,5 @@ +import Config + +config :pleroma, Pleroma.Search, module: Pleroma.Search.ParadeDB +config :pleroma, Pleroma.Search.ParadeDB, url: "postgres://localhost/paradedb" +config :pleroma, Pleroma.Search.ParadeDB.Repo, pool_size: 2 diff --git a/test/mix/tasks/pleroma/config_test.exs b/test/mix/tasks/pleroma/config_test.exs index 7513e958e..620bf8662 100644 --- a/test/mix/tasks/pleroma/config_test.exs +++ b/test/mix/tasks/pleroma/config_test.exs @@ -87,6 +87,14 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do config = ConfigDB.get_by_params(%{group: ":pleroma", key: ":first_setting"}) assert config.value == [key: "value", key2: [Repo]] end + + test "static search settings remain in the config file" do + MixTask.migrate_to_db("test/fixtures/config/static_search.secret.exs") + + refute ConfigDB.get_by_group_and_key(:pleroma, Pleroma.Search) + refute ConfigDB.get_by_group_and_key(:pleroma, Pleroma.Search.ParadeDB) + refute ConfigDB.get_by_group_and_key(:pleroma, Pleroma.Search.ParadeDB.Repo) + end end describe "with deletion of temp file" do diff --git a/test/pleroma/config/transfer_task_test.exs b/test/pleroma/config/transfer_task_test.exs index 6295fa888..ea5378ffd 100644 --- a/test/pleroma/config/transfer_task_test.exs +++ b/test/pleroma/config/transfer_task_test.exs @@ -71,6 +71,31 @@ defmodule Pleroma.Config.TransferTaskTest do assert assets_env[:mascots] == [a: 1, b: 2] end + test "does not transfer static search configuration" do + search_config = Application.get_env(:pleroma, Pleroma.Search) + parade_config = Application.get_env(:pleroma, Pleroma.Search.ParadeDB) + + clear_config(:database_config_blacklist, []) + + insert(:config, key: Pleroma.Search, value: [module: Pleroma.Search.ParadeDB]) + + insert(:config, + key: Pleroma.Search.ParadeDB, + value: [url: "postgres://localhost/paradedb"] + ) + + insert(:config, + key: Pleroma.Search.ParadeDB.Repo, + value: [pool_size: 50] + ) + + TransferTask.start_link([]) + + assert Application.get_env(:pleroma, Pleroma.Search) == search_config + assert Application.get_env(:pleroma, Pleroma.Search.ParadeDB) == parade_config + assert Application.get_env(:pleroma, Pleroma.Search.ParadeDB.Repo)[:pool_size] == 2 + end + describe "pleroma restart" do setup do on_exit(fn -> diff --git a/test/pleroma/config_db_test.exs b/test/pleroma/config_db_test.exs index 9d70e6d54..ae17a9d34 100644 --- a/test/pleroma/config_db_test.exs +++ b/test/pleroma/config_db_test.exs @@ -36,6 +36,20 @@ defmodule Pleroma.ConfigDBTest do assert config[:goose][:webhook_url] == "https://gander.com/" end + test "get_all_as_keyword/1 excludes static search configuration" do + insert(:config, key: Pleroma.Search, value: [module: Pleroma.Search.ParadeDB]) + insert(:config, key: Pleroma.Search.ParadeDB, value: [url: "postgres://example/db"]) + insert(:config, key: Pleroma.Search.ParadeDB.Repo, value: [pool_size: 50]) + insert(:config, key: :instance, value: [name: "Pleroma"]) + + config = ConfigDB.get_all_as_keyword(exclude_static: true) + + refute config[:pleroma][Pleroma.Search] + refute config[:pleroma][Pleroma.Search.ParadeDB] + refute config[:pleroma][Pleroma.Search.ParadeDB.Repo] + assert config[:pleroma][:instance] == [name: "Pleroma"] + end + describe "update_or_create/1" do test "common" do config = insert(:config) diff --git a/test/pleroma/web/admin_api/controllers/config_controller_test.exs b/test/pleroma/web/admin_api/controllers/config_controller_test.exs index c11ece10d..e4c8d866f 100644 --- a/test/pleroma/web/admin_api/controllers/config_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/config_controller_test.exs @@ -121,6 +121,19 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do end) end + test "effective configuration omits static search settings", %{conn: conn} do + insert(:config, key: Pleroma.Search, value: [module: Pleroma.Search.ParadeDB]) + insert(:config, key: Pleroma.Search.ParadeDB, value: [url: "postgres://example/db"]) + + %{"configs" => configs} = + conn + |> get("/api/pleroma/admin/config") + |> json_response_and_validate_schema(200) + + refute Enum.any?(configs, &(&1["key"] == "Pleroma.Search")) + refute Enum.any?(configs, &(&1["key"] == "Pleroma.Search.ParadeDB")) + end + test "subkeys with full update right merge", %{conn: conn} do insert(:config, key: ":emoji", @@ -1552,12 +1565,15 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do assert web_endpoint["children"] end - test "all keys from description are whitelisted", %{conn: conn} do + test "descriptions exclude blacklisted keys", %{conn: conn} do conn = get(conn, "/api/pleroma/admin/config/descriptions") assert response = json_response_and_validate_schema(conn, 200) - assert length(response) == length(Pleroma.Docs.JSON.compiled_descriptions()) + refute Enum.any?(response, &(&1["key"] == "Pleroma.Search")) + refute Enum.any?(response, &(&1["key"] == "Pleroma.Search.ParadeDB")) + + assert length(response) == length(Pleroma.Docs.JSON.compiled_descriptions()) - 2 end test "filters by database configuration blacklist and whitelist", %{conn: conn} do