1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Mix.Tasks.Pleroma.Config do
10 alias Pleroma.ConfigDB
13 @shortdoc "Manages the location of the config"
14 @moduledoc File.read!("docs/administration/CLI_tasks/config.md")
16 def run(["migrate_to_db"]) do
21 def run(["migrate_from_db" | options]) do
25 OptionParser.parse!(options,
26 strict: [env: :string, delete: :boolean],
34 with true <- Pleroma.Config.get([:configurable_from_database]) do
37 header = config_header()
39 shell_info("#{header}")
44 |> Enum.each(&dump(&1))
46 _ -> configdb_not_enabled()
50 def run(["dump", group, key]) do
51 with true <- Pleroma.Config.get([:configurable_from_database]) do
56 _ -> configdb_not_enabled()
60 def run(["dump", group]) do
61 with true <- Pleroma.Config.get([:configurable_from_database]) do
66 _ -> configdb_not_enabled()
70 def run(["groups"]) do
71 with true <- Pleroma.Config.get([:configurable_from_database]) do
77 |> Enum.map(fn x -> x.group end)
81 if length(groups) > 0 do
82 shell_info("The following configuration groups are set in ConfigDB:\r\n")
83 groups |> Enum.each(fn x -> shell_info("- #{x}") end)
87 _ -> configdb_not_enabled()
91 def run(["keys" | group]) do
92 with true <- Pleroma.Config.get([:configurable_from_database]) do
99 if x.group == group do
105 |> Enum.reject(fn x -> x == nil end)
107 if length(keys) > 0 do
108 shell_info("The following configuration keys under :#{group} are set in ConfigDB:\r\n")
109 keys |> Enum.each(fn x -> shell_info("- #{x}") end)
113 _ -> configdb_not_enabled()
117 def run(["reset"]) do
118 with true <- Pleroma.Config.get([:configurable_from_database]) do
121 if shell_prompt("Are you sure you want to continue?", "n") in ~w(Yn Y y) do
122 Ecto.Adapters.SQL.query!(Repo, "TRUNCATE config;")
123 Ecto.Adapters.SQL.query!(Repo, "ALTER SEQUENCE config_id_seq RESTART;")
125 shell_info("The ConfigDB settings have been removed from the database.")
127 shell_info("No changes made.")
130 _ -> configdb_not_enabled()
134 def run(["delete", group]) do
135 with true <- Pleroma.Config.get([:configurable_from_database]) do
138 group = group |> String.to_atom()
140 if shell_prompt("Are you sure you want to continue?", "n") in ~w(Yn Y y) do
143 |> Enum.filter(fn x ->
144 if x.group == group do
149 shell_info("No changes made.")
152 _ -> configdb_not_enabled()
156 def run(["delete", group, key]) do
157 with true <- Pleroma.Config.get([:configurable_from_database]) do
160 group = group |> String.to_atom()
161 key = key |> String.to_atom()
163 if shell_prompt("Are you sure you want to continue?", "n") in ~w(Yn Y y) do
166 |> Enum.filter(fn x ->
167 if x.group == group and x.key == key do
172 shell_info("No changes made.")
175 _ -> configdb_not_enabled()
179 @spec migrate_to_db(Path.t() | nil) :: any()
180 def migrate_to_db(file_path \\ nil) do
181 with true <- Pleroma.Config.get([:configurable_from_database]),
182 :ok <- Pleroma.Config.DeprecationWarnings.warn() do
187 if Pleroma.Config.get(:release) do
188 Pleroma.Config.get(:config_path)
190 "config/#{Pleroma.Config.get(:env)}.secret.exs"
194 do_migrate_to_db(config_file)
196 :error -> deprecation_error()
197 _ -> migration_error()
201 defp do_migrate_to_db(config_file) do
202 if File.exists?(config_file) do
203 shell_info("Migrating settings from file: #{Path.expand(config_file)}")
204 Ecto.Adapters.SQL.query!(Repo, "TRUNCATE config;")
205 Ecto.Adapters.SQL.query!(Repo, "ALTER SEQUENCE config_id_seq RESTART;")
214 |> Enum.each(&create(&1, custom_config))
216 shell_info("To migrate settings, you must define custom settings in #{config_file}.")
220 defp create(group, settings) do
222 |> Pleroma.Config.Loader.filter_group(settings)
223 |> Enum.each(fn {key, value} ->
224 {:ok, _} = ConfigDB.update_or_create(%{group: group, key: key, value: value})
226 shell_info("Settings for key #{key} migrated.")
229 shell_info("Settings for group :#{group} migrated.")
232 defp migrate_from_db(opts) do
233 if Pleroma.Config.get([:configurable_from_database]) do
234 env = opts[:env] || Pleroma.Config.get(:env)
237 if Pleroma.Config.get(:release) do
239 |> Pleroma.Config.get()
244 |> Path.join("#{env}.exported_from_db.secret.exs")
246 file = File.open!(config_path, [:write, :utf8])
248 IO.write(file, config_header())
252 |> Enum.each(&write_and_delete(&1, file, opts[:delete]))
254 :ok = File.close(file)
255 System.cmd("mix", ["format", config_path])
258 "Database configuration settings have been exported to config/#{env}.exported_from_db.secret.exs"
265 defp migration_error do
267 "Migration is not allowed in config. You can change this behavior by setting `config :pleroma, configurable_from_database: true`"
271 defp deprecation_error do
272 shell_error("Migration is not allowed until all deprecation warnings have been resolved.")
275 if Code.ensure_loaded?(Config.Reader) do
276 defp config_header, do: "import Config\r\n\r\n"
277 defp read_file(config_file), do: Config.Reader.read_imports!(config_file)
279 defp config_header, do: "use Mix.Config\r\n\r\n"
280 defp read_file(config_file), do: Mix.Config.eval!(config_file)
283 defp write_and_delete(config, file, delete?) do
289 defp write(config, file) do
290 value = inspect(config.value, limit: :infinity)
292 IO.write(file, "config #{inspect(config.group)}, #{inspect(config.key)}, #{value}\r\n\r\n")
297 defp delete(config, true) do
298 {:ok, _} = Repo.delete(config)
299 shell_info(":#{config.group}, :#{config.key} deleted from the ConfigDB.")
302 defp delete(_config, _), do: :ok
304 defp dump(%Pleroma.ConfigDB{} = config) do
305 value = inspect(config.value, limit: :infinity)
307 shell_info("config #{inspect(config.group)}, #{inspect(config.key)}, #{value}\r\n\r\n")
310 defp configdb_not_enabled do
312 "ConfigDB not enabled. Please check the value of :configurable_from_database in your configuration."
316 defp dump_key(group, key) do
317 group = group |> String.to_atom()
318 key = key |> String.to_atom()
322 |> Enum.filter(fn x ->
323 if x.group == group && x.key == key do
329 defp dump_group(group) do
330 group = group |> String.to_atom()
334 |> Enum.filter(fn x ->
335 if x.group == group do