aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web/admin_api/controllers/config_controller.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web/admin_api/controllers/config_controller.ex')
-rw-r--r--lib/pleroma/web/admin_api/controllers/config_controller.ex169
1 files changed, 92 insertions, 77 deletions
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