Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into develop
[akkoma] / lib / pleroma / web / admin_api / controllers / config_controller.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.AdminAPI.ConfigController do
6 use Pleroma.Web, :controller
7
8 alias Pleroma.Config
9 alias Pleroma.ConfigDB
10 alias Pleroma.Web.Plugs.OAuthScopesPlug
11
12 plug(Pleroma.Web.ApiSpec.CastAndValidate)
13 plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update)
14
15 plug(
16 OAuthScopesPlug,
17 %{scopes: ["admin:read"]}
18 when action in [:show, :descriptions]
19 )
20
21 action_fallback(Pleroma.Web.AdminAPI.FallbackController)
22
23 defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ConfigOperation
24
25 def descriptions(conn, _params) do
26 descriptions = Enum.filter(Pleroma.Docs.JSON.compiled_descriptions(), &whitelisted_config?/1)
27
28 json(conn, descriptions)
29 end
30
31 def show(conn, %{only_db: true}) do
32 with :ok <- configurable_from_database() do
33 configs = Pleroma.Repo.all(ConfigDB)
34
35 render(conn, "index.json", %{
36 configs: configs,
37 need_reboot: Restarter.Pleroma.need_reboot?()
38 })
39 end
40 end
41
42 def show(conn, _params) do
43 with :ok <- configurable_from_database() do
44 configs = ConfigDB.get_all_as_keyword()
45
46 merged =
47 Config.Holder.default_config()
48 |> ConfigDB.merge(configs)
49 |> Enum.map(fn {group, values} ->
50 Enum.map(values, fn {key, value} ->
51 db =
52 if configs[group][key] do
53 ConfigDB.get_db_keys(configs[group][key], key)
54 end
55
56 db_value = configs[group][key]
57
58 merged_value =
59 if not is_nil(db_value) and Keyword.keyword?(db_value) and
60 ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
61 ConfigDB.merge_group(group, key, value, db_value)
62 else
63 value
64 end
65
66 %ConfigDB{
67 group: group,
68 key: key,
69 value: merged_value
70 }
71 |> Pleroma.Maps.put_if_present(:db, db)
72 end)
73 end)
74 |> List.flatten()
75
76 render(conn, "index.json", %{
77 configs: merged,
78 need_reboot: Restarter.Pleroma.need_reboot?()
79 })
80 end
81 end
82
83 def update(%{body_params: %{configs: configs}} = conn, _) do
84 with :ok <- configurable_from_database() do
85 results =
86 configs
87 |> Enum.filter(&whitelisted_config?/1)
88 |> Enum.map(fn
89 %{group: group, key: key, delete: true} = params ->
90 ConfigDB.delete(%{group: group, key: key, subkeys: params[:subkeys]})
91
92 %{group: group, key: key, value: value} ->
93 ConfigDB.update_or_create(%{group: group, key: key, value: value})
94 end)
95 |> Enum.reject(fn {result, _} -> result == :error end)
96
97 {deleted, updated} =
98 results
99 |> Enum.map(fn {:ok, %{key: key, value: value} = config} ->
100 Map.put(config, :db, ConfigDB.get_db_keys(value, key))
101 end)
102 |> Enum.split_with(&(Ecto.get_meta(&1, :state) == :deleted))
103
104 Config.TransferTask.load_and_update_env(deleted, false)
105
106 if not Restarter.Pleroma.need_reboot?() do
107 changed_reboot_settings? =
108 (updated ++ deleted)
109 |> Enum.any?(&Config.TransferTask.pleroma_need_restart?(&1.group, &1.key, &1.value))
110
111 if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot()
112 end
113
114 render(conn, "index.json", %{
115 configs: updated,
116 need_reboot: Restarter.Pleroma.need_reboot?()
117 })
118 end
119 end
120
121 defp configurable_from_database do
122 if Config.get(:configurable_from_database) do
123 :ok
124 else
125 {:error, "You must enable configurable_from_database in your config file."}
126 end
127 end
128
129 defp whitelisted_config?(group, key) do
130 if whitelisted_configs = Config.get(:database_config_whitelist) do
131 Enum.any?(whitelisted_configs, fn
132 {whitelisted_group} ->
133 group == inspect(whitelisted_group)
134
135 {whitelisted_group, whitelisted_key} ->
136 group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
137 end)
138 else
139 true
140 end
141 end
142
143 defp whitelisted_config?(%{group: group, key: key}) do
144 whitelisted_config?(group, key)
145 end
146
147 defp whitelisted_config?(%{group: group} = config) do
148 whitelisted_config?(group, config[:key])
149 end
150 end