X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fconfig%2Ftransfer_task.ex;h=7c3449b5e0e06ac27f677dcc74dfca0477caa322;hb=193d67cde590efd9a75ac11da76657151f58afdd;hp=75c4aa7397d649c12ca32f3b61aede3d0cf30bc8;hpb=70c7a26de8135ddc089fc0d2e0766e2e793d505c;p=akkoma
diff --git a/lib/pleroma/config/transfer_task.ex b/lib/pleroma/config/transfer_task.ex
index 75c4aa739..7c3449b5e 100644
--- a/lib/pleroma/config/transfer_task.ex
+++ b/lib/pleroma/config/transfer_task.ex
@@ -1,14 +1,38 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Config.TransferTask do
use Task
+ alias Pleroma.ConfigDB
+ alias Pleroma.Repo
+
require Logger
- alias Pleroma.Repo
- alias Pleroma.Web.AdminAPI.Config
+ @type env() :: :test | :benchmark | :dev | :prod
+
+ @reboot_time_keys [
+ {:pleroma, :hackney_pools},
+ {:pleroma, :chat},
+ {:pleroma, Oban},
+ {:pleroma, :rate_limit},
+ {:pleroma, :markup},
+ {:plerome, :streamer}
+ ]
+
+ @reboot_time_subkeys [
+ {:pleroma, Pleroma.Captcha, [:seconds_valid]},
+ {:pleroma, Pleroma.Upload, [:proxy_remote]},
+ {:pleroma, :instance, [:upload_limit]},
+ {:pleroma, :email_notifications, [:digest]},
+ {:pleroma, :oauth2, [:clean_expired_tokens]},
+ {:pleroma, Pleroma.ActivityExpiration, [:enabled]},
+ {:pleroma, Pleroma.ScheduledActivity, [:enabled]},
+ {:pleroma, :gopher, [:enabled]}
+ ]
+
+ @reject [nil, :prometheus]
def start_link(_) do
load_and_update_env()
@@ -16,49 +40,136 @@ defmodule Pleroma.Config.TransferTask do
:ignore
end
- def load_and_update_env do
- with true <- Pleroma.Config.get([:configurable_from_database]),
+ @spec load_and_update_env([ConfigDB.t()]) :: :ok | false
+ def load_and_update_env(deleted \\ [], restart_pleroma? \\ true) do
+ with {:configurable, true} <-
+ {:configurable, Pleroma.Config.get(:configurable_from_database)},
true <- Ecto.Adapters.SQL.table_exists?(Repo, "config"),
started_applications <- Application.started_applications() do
# We need to restart applications for loaded settings take effect
- Config
- |> Repo.all()
- |> Enum.map(&update_env(&1))
- |> Enum.uniq()
- # TODO: some problem with prometheus after restart!
- |> Enum.reject(&(&1 in [:pleroma, nil, :prometheus]))
- |> Enum.each(&restart(started_applications, &1))
+
+ in_db = Repo.all(ConfigDB)
+
+ with_deleted = in_db ++ deleted
+
+ reject_for_restart = if restart_pleroma?, do: @reject, else: [:pleroma | @reject]
+
+ applications =
+ with_deleted
+ |> Enum.map(&merge_and_update(&1))
+ |> Enum.uniq()
+ # TODO: some problem with prometheus after restart!
+ |> Enum.reject(&(&1 in reject_for_restart))
+
+ # to be ensured that pleroma will be restarted last
+ applications =
+ if :pleroma in applications do
+ List.delete(applications, :pleroma) ++ [:pleroma]
+ else
+ Restarter.Pleroma.rebooted()
+ applications
+ end
+
+ Enum.each(applications, &restart(started_applications, &1, Pleroma.Config.get(:env)))
+
+ :ok
+ else
+ {:configurable, false} -> Restarter.Pleroma.rebooted()
end
end
- defp update_env(setting) do
+ defp merge_and_update(setting) do
try do
- key = Config.from_string(setting.key)
- group = Config.from_string(setting.group)
- value = Config.from_binary(setting.value)
+ key = ConfigDB.from_string(setting.key)
+ group = ConfigDB.from_string(setting.group)
- if group != :phoenix and key != :serve_endpoints do
- :ok = Application.put_env(group, key, value)
- end
+ default = Pleroma.Config.Holder.default_config(group, key)
+ value = ConfigDB.from_binary(setting.value)
+
+ merged_value =
+ if Ecto.get_meta(setting, :state) == :deleted do
+ default
+ else
+ if can_be_merged?(default, value) do
+ ConfigDB.merge_group(group, key, default, value)
+ else
+ value
+ end
+ end
+
+ :ok = update_env(group, key, merged_value)
- group
+ if group != :logger do
+ if group != :pleroma or pleroma_need_restart?(group, key, value) do
+ group
+ end
+ else
+ # change logger configuration in runtime, without restart
+ if Keyword.keyword?(merged_value) and
+ key not in [:compile_time_application, :backends, :compile_time_purge_matching] do
+ Logger.configure_backend(key, merged_value)
+ else
+ Logger.configure([{key, merged_value}])
+ end
+
+ nil
+ end
rescue
- e ->
- Logger.warn(
- "updating env causes error, key: #{inspect(setting.key)}, error: #{inspect(e)}"
- )
+ error ->
+ error_msg =
+ "updating env causes error, group: " <>
+ inspect(setting.group) <>
+ " key: " <>
+ inspect(setting.key) <>
+ " value: " <>
+ inspect(ConfigDB.from_binary(setting.value)) <> " error: " <> inspect(error)
+
+ Logger.warn(error_msg)
nil
end
end
- defp restart(started_applications, app) do
+ @spec pleroma_need_restart?(atom(), atom(), any()) :: boolean()
+ def pleroma_need_restart?(group, key, value) do
+ group_and_key_need_reboot?(group, key) or group_and_subkey_need_reboot?(group, key, value)
+ end
+
+ defp group_and_key_need_reboot?(group, key) do
+ Enum.any?(@reboot_time_keys, fn {g, k} -> g == group and k == key end)
+ end
+
+ defp group_and_subkey_need_reboot?(group, key, value) do
+ Keyword.keyword?(value) and
+ Enum.any?(@reboot_time_subkeys, fn {g, k, subkeys} ->
+ g == group and k == key and
+ Enum.any?(Keyword.keys(value), &(&1 in subkeys))
+ end)
+ end
+
+ defp update_env(group, key, nil), do: Application.delete_env(group, key)
+ defp update_env(group, key, value), do: Application.put_env(group, key, value)
+
+ defp restart(_, :pleroma, env), do: Restarter.Pleroma.restart_after_boot(env)
+
+ defp restart(started_applications, app, _) do
with {^app, _, _} <- List.keyfind(started_applications, app, 0),
:ok <- Application.stop(app) do
:ok = Application.start(app)
else
- nil -> Logger.warn("#{app} is not started.")
- error -> Logger.warn(inspect(error))
+ nil ->
+ Logger.warn("#{app} is not started.")
+
+ error ->
+ error
+ |> inspect()
+ |> Logger.warn()
end
end
+
+ defp can_be_merged?(val1, val2) when is_list(val1) and is_list(val2) do
+ Keyword.keyword?(val1) and Keyword.keyword?(val2)
+ end
+
+ defp can_be_merged?(_val1, _val2), do: false
end