2020-05-28 12:23:15 -06:00
|
|
|
# Pleroma: A lightweight social networking server
|
2021-01-12 23:49:20 -07:00
|
|
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
2020-05-28 12:23:15 -06:00
|
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
|
|
|
defmodule Pleroma.Web.AdminAPI.ConfigController do
|
|
|
|
use Pleroma.Web, :controller
|
|
|
|
|
|
|
|
alias Pleroma.Config
|
|
|
|
alias Pleroma.ConfigDB
|
2020-06-24 00:57:27 -06:00
|
|
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
2020-05-28 12:23:15 -06:00
|
|
|
|
2020-05-28 13:11:12 -06:00
|
|
|
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
|
|
|
plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action == :update)
|
|
|
|
|
2020-05-28 12:23:15 -06:00
|
|
|
plug(
|
|
|
|
OAuthScopesPlug,
|
|
|
|
%{scopes: ["read"], admin: true}
|
|
|
|
when action in [:show, :descriptions]
|
|
|
|
)
|
|
|
|
|
|
|
|
action_fallback(Pleroma.Web.AdminAPI.FallbackController)
|
|
|
|
|
2020-05-28 13:11:12 -06:00
|
|
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ConfigOperation
|
|
|
|
|
2020-05-28 12:23:15 -06:00
|
|
|
def descriptions(conn, _params) do
|
2020-07-12 09:23:33 -06:00
|
|
|
descriptions = Enum.filter(Pleroma.Docs.JSON.compiled_descriptions(), &whitelisted_config?/1)
|
2020-05-28 12:23:15 -06:00
|
|
|
|
|
|
|
json(conn, descriptions)
|
|
|
|
end
|
|
|
|
|
2020-05-28 13:11:12 -06:00
|
|
|
def show(conn, %{only_db: true}) do
|
2020-05-28 12:23:15 -06:00
|
|
|
with :ok <- configurable_from_database() do
|
|
|
|
configs = Pleroma.Repo.all(ConfigDB)
|
2020-05-31 01:46:02 -06:00
|
|
|
|
|
|
|
render(conn, "index.json", %{
|
|
|
|
configs: configs,
|
|
|
|
need_reboot: Restarter.Pleroma.need_reboot?()
|
|
|
|
})
|
2020-05-28 12:23:15 -06:00
|
|
|
end
|
|
|
|
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
|
|
|
|
|
|
|
|
db_value = configs[group][key]
|
|
|
|
|
|
|
|
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)
|
|
|
|
else
|
|
|
|
value
|
|
|
|
end
|
|
|
|
|
2020-05-31 01:46:02 -06:00
|
|
|
%ConfigDB{
|
|
|
|
group: group,
|
|
|
|
key: key,
|
|
|
|
value: merged_value
|
2020-05-28 12:23:15 -06:00
|
|
|
}
|
2020-06-05 08:48:02 -06:00
|
|
|
|> Pleroma.Maps.put_if_present(:db, db)
|
2020-05-28 12:23:15 -06:00
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|> List.flatten()
|
|
|
|
|
2020-05-31 01:46:02 -06:00
|
|
|
render(conn, "index.json", %{
|
|
|
|
configs: merged,
|
|
|
|
need_reboot: Restarter.Pleroma.need_reboot?()
|
|
|
|
})
|
2020-05-28 12:23:15 -06:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-28 13:11:12 -06:00
|
|
|
def update(%{body_params: %{configs: configs}} = conn, _) do
|
2020-05-28 12:23:15 -06:00
|
|
|
with :ok <- configurable_from_database() do
|
|
|
|
results =
|
|
|
|
configs
|
|
|
|
|> Enum.filter(&whitelisted_config?/1)
|
|
|
|
|> Enum.map(fn
|
2020-05-28 13:11:12 -06:00
|
|
|
%{group: group, key: key, delete: true} = params ->
|
|
|
|
ConfigDB.delete(%{group: group, key: key, subkeys: params[:subkeys]})
|
2020-05-28 12:23:15 -06:00
|
|
|
|
2020-05-28 13:11:12 -06:00
|
|
|
%{group: group, key: key, value: value} ->
|
2020-05-28 12:23:15 -06:00
|
|
|
ConfigDB.update_or_create(%{group: group, key: key, value: value})
|
|
|
|
end)
|
|
|
|
|> Enum.reject(fn {result, _} -> result == :error end)
|
|
|
|
|
|
|
|
{deleted, updated} =
|
|
|
|
results
|
2020-05-31 01:46:02 -06:00
|
|
|
|> Enum.map(fn {:ok, %{key: key, value: value} = config} ->
|
|
|
|
Map.put(config, :db, ConfigDB.get_db_keys(value, key))
|
2020-05-28 12:23:15 -06:00
|
|
|
end)
|
2020-05-31 01:46:02 -06:00
|
|
|
|> Enum.split_with(&(Ecto.get_meta(&1, :state) == :deleted))
|
2020-05-28 12:23:15 -06:00
|
|
|
|
|
|
|
Config.TransferTask.load_and_update_env(deleted, false)
|
|
|
|
|
|
|
|
if not Restarter.Pleroma.need_reboot?() do
|
|
|
|
changed_reboot_settings? =
|
|
|
|
(updated ++ deleted)
|
2020-05-31 01:46:02 -06:00
|
|
|
|> Enum.any?(&Config.TransferTask.pleroma_need_restart?(&1.group, &1.key, &1.value))
|
2020-05-28 12:23:15 -06:00
|
|
|
|
|
|
|
if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot()
|
|
|
|
end
|
|
|
|
|
|
|
|
render(conn, "index.json", %{
|
|
|
|
configs: updated,
|
|
|
|
need_reboot: Restarter.Pleroma.need_reboot?()
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defp configurable_from_database do
|
|
|
|
if Config.get(:configurable_from_database) do
|
|
|
|
:ok
|
|
|
|
else
|
|
|
|
{:error, "To use this endpoint you need to enable configuration from database."}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defp whitelisted_config?(group, key) do
|
|
|
|
if whitelisted_configs = Config.get(:database_config_whitelist) do
|
|
|
|
Enum.any?(whitelisted_configs, fn
|
|
|
|
{whitelisted_group} ->
|
|
|
|
group == inspect(whitelisted_group)
|
|
|
|
|
|
|
|
{whitelisted_group, whitelisted_key} ->
|
|
|
|
group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
|
|
|
|
end)
|
|
|
|
else
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-28 13:11:12 -06:00
|
|
|
defp whitelisted_config?(%{group: group, key: key}) do
|
2020-05-28 12:23:15 -06:00
|
|
|
whitelisted_config?(group, key)
|
|
|
|
end
|
|
|
|
|
2020-05-28 13:11:12 -06:00
|
|
|
defp whitelisted_config?(%{group: group} = config) do
|
2020-05-28 12:23:15 -06:00
|
|
|
whitelisted_config?(group, config[:key])
|
|
|
|
end
|
|
|
|
end
|