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