diff options
Diffstat (limited to 'lib/pleroma/web/admin_api')
3 files changed, 110 insertions, 91 deletions
diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex index 839ac1a8d..daa4c451c 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -392,14 +392,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do def restart(conn, _params) do with :ok <- configurable_from_database() do - Restarter.Pleroma.restart(Config.get(:env), 50) + Task.start(Pleroma.Application.ConfigDependentDeps, :restart_dependencies, []) json(conn, %{}) end end def need_reboot(conn, _params) do - json(conn, %{need_reboot: Restarter.Pleroma.need_reboot?()}) + json(conn, %{need_reboot: Pleroma.Application.ConfigDependentDeps.need_reboot?()}) end defp configurable_from_database do diff --git a/lib/pleroma/web/admin_api/controllers/config_controller.ex b/lib/pleroma/web/admin_api/controllers/config_controller.ex index a718d7b8d..88ae9ed99 100644 --- a/lib/pleroma/web/admin_api/controllers/config_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/config_controller.ex @@ -5,19 +5,24 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do use Pleroma.Web, :controller + import Pleroma.Web.ControllerHelper, only: [json_response: 3] + + alias Pleroma.Application alias Pleroma.Config alias Pleroma.ConfigDB alias Pleroma.Web.Plugs.OAuthScopesPlug plug(Pleroma.Web.ApiSpec.CastAndValidate) - plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update) + plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action in [:update, :rollback]) plug( OAuthScopesPlug, %{scopes: ["admin:read"]} - when action in [:show, :descriptions] + when action in [:show, :descriptions, :versions] ) + plug(:check_possibility_configuration_from_database when action != :descriptions) + action_fallback(Pleroma.Web.AdminAPI.FallbackController) defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ConfigOperation @@ -29,100 +34,110 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do end def show(conn, %{only_db: true}) do - with :ok <- configurable_from_database() do - configs = Pleroma.Repo.all(ConfigDB) + configs = ConfigDB.all_with_db() - render(conn, "index.json", %{ - configs: configs, - need_reboot: Restarter.Pleroma.need_reboot?() - }) - end + render(conn, "index.json", %{ + configs: configs, + need_reboot: Application.ConfigDependentDeps.need_reboot?() + }) end def show(conn, _params) do - with :ok <- configurable_from_database() do - configs = ConfigDB.get_all_as_keyword() - - merged = - Config.Holder.default_config() - |> ConfigDB.merge(configs) - |> Enum.map(fn {group, values} -> - Enum.map(values, fn {key, value} -> - db = - if configs[group][key] do - ConfigDB.get_db_keys(configs[group][key], key) - end + defaults = Config.Holder.default_config() + changes = ConfigDB.all_with_db() + + {changes_values_merged_with_defaults, remaining_defaults} = + ConfigDB.reduce_defaults_and_merge_with_changes(changes, defaults) - db_value = configs[group][key] + changes_merged_with_defaults = + ConfigDB.from_keyword_to_structs(remaining_defaults, changes_values_merged_with_defaults) - merged_value = - if not is_nil(db_value) and Keyword.keyword?(db_value) and - ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do - ConfigDB.merge_group(group, key, value, db_value) + render(conn, "index.json", %{ + configs: changes_merged_with_defaults, + need_reboot: Application.ConfigDependentDeps.need_reboot?() + }) + end + + def update(%{body_params: %{configs: configs}} = conn, _) do + result = + configs + |> Enum.filter(&whitelisted_config?/1) + |> Enum.map(&Config.Converter.to_elixir_types/1) + |> Config.Versioning.new_version() + + case result do + {:ok, changes} -> + inserts_and_deletions = + Enum.reduce(changes, [], fn + {{operation, _, _}, %ConfigDB{} = change}, acc + when operation in [:insert_or_update, :delete_or_update] -> + if Ecto.get_meta(change, :state) == :deleted do + [change | acc] else - value + if change.group == :pleroma and + change.key in ConfigDB.pleroma_not_keyword_values() do + [%{change | db: [change.key]} | acc] + else + [%{change | db: Keyword.keys(change.value)} | acc] + end end - %ConfigDB{ - group: group, - key: key, - value: merged_value - } - |> Pleroma.Maps.put_if_present(:db, db) + _, acc -> + acc end) - end) - |> List.flatten() - render(conn, "index.json", %{ - configs: merged, - need_reboot: Restarter.Pleroma.need_reboot?() - }) + Application.Environment.update(inserts_and_deletions, only_update: true) + + render(conn, "index.json", %{ + configs: Enum.reject(inserts_and_deletions, &(Ecto.get_meta(&1, :state) == :deleted)), + need_reboot: Application.ConfigDependentDeps.need_reboot?() + }) + + {:error, error} -> + {:error, "Updating config failed: #{inspect(error)}"} + + {:error, _, {error, operation}, _} -> + {:error, + "Updating config failed: #{inspect(error)}, group: #{operation[:group]}, key: #{ + operation[:key] + }, value: #{inspect(operation[:value])}"} end end - def update(%{body_params: %{configs: configs}} = conn, _) do - with :ok <- configurable_from_database() do - results = - configs - |> Enum.filter(&whitelisted_config?/1) - |> Enum.map(fn - %{group: group, key: key, delete: true} = params -> - ConfigDB.delete(%{group: group, key: key, subkeys: params[:subkeys]}) - - %{group: group, key: key, value: value} -> - ConfigDB.update_or_create(%{group: group, key: key, value: value}) - end) - |> Enum.reject(fn {result, _} -> result == :error end) - - {deleted, updated} = - results - |> Enum.map(fn {:ok, %{key: key, value: value} = config} -> - Map.put(config, :db, ConfigDB.get_db_keys(value, key)) - end) - |> Enum.split_with(&(Ecto.get_meta(&1, :state) == :deleted)) - - Config.TransferTask.load_and_update_env(deleted, false) - - if not Restarter.Pleroma.need_reboot?() do - changed_reboot_settings? = - (updated ++ deleted) - |> Enum.any?(&Config.TransferTask.pleroma_need_restart?(&1.group, &1.key, &1.value)) - - if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot() - end - - render(conn, "index.json", %{ - configs: updated, - need_reboot: Restarter.Pleroma.need_reboot?() - }) + def rollback(conn, %{id: id}) do + case Config.Versioning.rollback_by_id(id) do + {:ok, _} -> + json_response(conn, :no_content, "") + + {:error, :not_found} -> + {:error, :not_found} + + {:error, error} -> + {:error, "Rollback is not possible: #{inspect(error)}"} + + {:error, _, {error, operation}, _} -> + {:error, + "Rollback is not possible, backup restore error: #{inspect(error)}, operation error: #{ + inspect(operation) + }"} end end - defp configurable_from_database do + def versions(conn, _) do + versions = Pleroma.Config.Version.all() + + render(conn, "index.json", %{versions: versions}) + end + + defp check_possibility_configuration_from_database(conn, _) do if Config.get(:configurable_from_database) do - :ok + conn else - {:error, "You must enable configurable_from_database in your config file."} + Pleroma.Web.AdminAPI.FallbackController.call( + conn, + {:error, "You must enable configurable_from_database in your config file."} + ) + |> halt() end end diff --git a/lib/pleroma/web/admin_api/views/config_view.ex b/lib/pleroma/web/admin_api/views/config_view.ex index d29b4963d..6115c3405 100644 --- a/lib/pleroma/web/admin_api/views/config_view.ex +++ b/lib/pleroma/web/admin_api/views/config_view.ex @@ -5,8 +5,6 @@ defmodule Pleroma.Web.AdminAPI.ConfigView do use Pleroma.Web, :view - alias Pleroma.ConfigDB - def render("index.json", %{configs: configs} = params) do %{ configs: render_many(configs, __MODULE__, "show.json", as: :config), @@ -14,17 +12,23 @@ defmodule Pleroma.Web.AdminAPI.ConfigView do } end - def render("show.json", %{config: config}) do - map = %{ - key: ConfigDB.to_json_types(config.key), - group: ConfigDB.to_json_types(config.group), - value: ConfigDB.to_json_types(config.value) + def render("index.json", %{versions: versions}) do + %{ + versions: render_many(versions, __MODULE__, "show.json", as: :version) } + end + + def render("show.json", %{config: config}) do + config + |> Map.take([:group, :key, :value, :db]) + |> Map.new(fn + {k, v} -> {k, Pleroma.Config.Converter.to_json_types(v)} + end) + end - if config.db != [] do - Map.put(map, :db, config.db) - else - map - end + def render("show.json", %{version: version}) do + version + |> Map.take([:id, :current]) + |> Map.put(:inserted_at, Pleroma.Web.CommonAPI.Utils.to_masto_date(version.inserted_at)) end end |