logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

config.ex (9732B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Mix.Tasks.Pleroma.Config do
  5. use Mix.Task
  6. import Ecto.Query
  7. import Mix.Pleroma
  8. alias Pleroma.ConfigDB
  9. alias Pleroma.Repo
  10. @shortdoc "Manages the location of the config"
  11. @moduledoc File.read!("docs/administration/CLI_tasks/config.md")
  12. def run(["migrate_to_db"]) do
  13. check_configdb(fn ->
  14. start_pleroma()
  15. migrate_to_db()
  16. end)
  17. end
  18. def run(["migrate_from_db" | options]) do
  19. check_configdb(fn ->
  20. start_pleroma()
  21. {opts, _} =
  22. OptionParser.parse!(options,
  23. strict: [env: :string, delete: :boolean, path: :string],
  24. aliases: [d: :delete]
  25. )
  26. migrate_from_db(opts)
  27. end)
  28. end
  29. def run(["dump"]) do
  30. check_configdb(fn ->
  31. start_pleroma()
  32. header = config_header()
  33. settings =
  34. ConfigDB
  35. |> Repo.all()
  36. |> Enum.sort()
  37. unless settings == [] do
  38. shell_info("#{header}")
  39. Enum.each(settings, &dump(&1))
  40. else
  41. shell_error("No settings in ConfigDB.")
  42. end
  43. end)
  44. end
  45. def run(["dump", group, key]) do
  46. check_configdb(fn ->
  47. start_pleroma()
  48. group = maybe_atomize(group)
  49. key = maybe_atomize(key)
  50. group
  51. |> ConfigDB.get_by_group_and_key(key)
  52. |> dump()
  53. end)
  54. end
  55. def run(["dump", group]) do
  56. check_configdb(fn ->
  57. start_pleroma()
  58. group = maybe_atomize(group)
  59. dump_group(group)
  60. end)
  61. end
  62. def run(["groups"]) do
  63. check_configdb(fn ->
  64. start_pleroma()
  65. groups =
  66. ConfigDB
  67. |> distinct([c], true)
  68. |> select([c], c.group)
  69. |> Repo.all()
  70. if length(groups) > 0 do
  71. shell_info("The following configuration groups are set in ConfigDB:\r\n")
  72. groups |> Enum.each(fn x -> shell_info("- #{x}") end)
  73. shell_info("\r\n")
  74. end
  75. end)
  76. end
  77. def run(["reset", "--force"]) do
  78. check_configdb(fn ->
  79. start_pleroma()
  80. truncatedb()
  81. shell_info("The ConfigDB settings have been removed from the database.")
  82. end)
  83. end
  84. def run(["reset"]) do
  85. check_configdb(fn ->
  86. start_pleroma()
  87. shell_info("The following settings will be permanently removed:")
  88. ConfigDB
  89. |> Repo.all()
  90. |> Enum.sort()
  91. |> Enum.each(&dump(&1))
  92. shell_error("\nTHIS CANNOT BE UNDONE!")
  93. if shell_prompt("Are you sure you want to continue?", "n") in ~w(Yn Y y) do
  94. truncatedb()
  95. shell_info("The ConfigDB settings have been removed from the database.")
  96. else
  97. shell_error("No changes made.")
  98. end
  99. end)
  100. end
  101. def run(["delete", "--force", group, key]) do
  102. start_pleroma()
  103. group = maybe_atomize(group)
  104. key = maybe_atomize(key)
  105. with true <- key_exists?(group, key) do
  106. shell_info("The following settings will be removed from ConfigDB:\n")
  107. group
  108. |> ConfigDB.get_by_group_and_key(key)
  109. |> dump()
  110. delete_key(group, key)
  111. else
  112. _ ->
  113. shell_error("No settings in ConfigDB for #{inspect(group)}, #{inspect(key)}. Aborting.")
  114. end
  115. end
  116. def run(["delete", "--force", group]) do
  117. start_pleroma()
  118. group = maybe_atomize(group)
  119. with true <- group_exists?(group) do
  120. shell_info("The following settings will be removed from ConfigDB:\n")
  121. dump_group(group)
  122. delete_group(group)
  123. else
  124. _ -> shell_error("No settings in ConfigDB for #{inspect(group)}. Aborting.")
  125. end
  126. end
  127. def run(["delete", group, key]) do
  128. start_pleroma()
  129. group = maybe_atomize(group)
  130. key = maybe_atomize(key)
  131. with true <- key_exists?(group, key) do
  132. shell_info("The following settings will be removed from ConfigDB:\n")
  133. group
  134. |> ConfigDB.get_by_group_and_key(key)
  135. |> dump()
  136. if shell_prompt("Are you sure you want to continue?", "n") in ~w(Yn Y y) do
  137. delete_key(group, key)
  138. else
  139. shell_error("No changes made.")
  140. end
  141. else
  142. _ ->
  143. shell_error("No settings in ConfigDB for #{inspect(group)}, #{inspect(key)}. Aborting.")
  144. end
  145. end
  146. def run(["delete", group]) do
  147. start_pleroma()
  148. group = maybe_atomize(group)
  149. with true <- group_exists?(group) do
  150. shell_info("The following settings will be removed from ConfigDB:\n")
  151. dump_group(group)
  152. if shell_prompt("Are you sure you want to continue?", "n") in ~w(Yn Y y) do
  153. delete_group(group)
  154. else
  155. shell_error("No changes made.")
  156. end
  157. else
  158. _ -> shell_error("No settings in ConfigDB for #{inspect(group)}. Aborting.")
  159. end
  160. end
  161. @spec migrate_to_db(Path.t() | nil) :: any()
  162. def migrate_to_db(file_path \\ nil) do
  163. with :ok <- Pleroma.Config.DeprecationWarnings.warn() do
  164. config_file =
  165. if file_path do
  166. file_path
  167. else
  168. if Pleroma.Config.get(:release) do
  169. Pleroma.Config.get(:config_path)
  170. else
  171. "config/#{Pleroma.Config.get(:env)}.secret.exs"
  172. end
  173. end
  174. do_migrate_to_db(config_file)
  175. else
  176. _ ->
  177. shell_error("Migration is not allowed until all deprecation warnings have been resolved.")
  178. end
  179. end
  180. defp do_migrate_to_db(config_file) do
  181. if File.exists?(config_file) do
  182. shell_info("Migrating settings from file: #{Path.expand(config_file)}")
  183. truncatedb()
  184. custom_config =
  185. config_file
  186. |> read_file()
  187. |> elem(0)
  188. custom_config
  189. |> Keyword.keys()
  190. |> Enum.each(&create(&1, custom_config))
  191. else
  192. shell_info("To migrate settings, you must define custom settings in #{config_file}.")
  193. end
  194. end
  195. defp create(group, settings) do
  196. group
  197. |> Pleroma.Config.Loader.filter_group(settings)
  198. |> Enum.each(fn {key, value} ->
  199. {:ok, _} = ConfigDB.update_or_create(%{group: group, key: key, value: value})
  200. shell_info("Settings for key #{key} migrated.")
  201. end)
  202. shell_info("Settings for group #{inspect(group)} migrated.")
  203. end
  204. defp migrate_from_db(opts) do
  205. env = opts[:env] || Pleroma.Config.get(:env)
  206. filename = "#{env}.exported_from_db.secret.exs"
  207. config_path =
  208. cond do
  209. opts[:path] ->
  210. opts[:path]
  211. Pleroma.Config.get(:release) ->
  212. :config_path
  213. |> Pleroma.Config.get()
  214. |> Path.dirname()
  215. true ->
  216. "config"
  217. end
  218. |> Path.join(filename)
  219. with {:ok, file} <- File.open(config_path, [:write, :utf8]) do
  220. write_config(file, config_path, opts)
  221. shell_info("Database configuration settings have been exported to #{config_path}")
  222. else
  223. _ ->
  224. shell_error("Impossible to save settings to this directory #{Path.dirname(config_path)}")
  225. tmp_config_path = Path.join(System.tmp_dir!(), filename)
  226. file = File.open!(tmp_config_path)
  227. shell_info(
  228. "Saving database configuration settings to #{tmp_config_path}. Copy it to the #{Path.dirname(config_path)} manually."
  229. )
  230. write_config(file, tmp_config_path, opts)
  231. end
  232. end
  233. defp write_config(file, path, opts) do
  234. IO.write(file, config_header())
  235. ConfigDB
  236. |> Repo.all()
  237. |> Enum.each(&write_and_delete(&1, file, opts[:delete]))
  238. :ok = File.close(file)
  239. System.cmd("mix", ["format", path])
  240. end
  241. defp config_header, do: "import Config\r\n\r\n"
  242. defp read_file(config_file), do: Config.Reader.read_imports!(config_file)
  243. defp write_and_delete(config, file, delete?) do
  244. config
  245. |> write(file)
  246. |> delete(delete?)
  247. end
  248. defp write(config, file) do
  249. value = inspect(config.value, limit: :infinity)
  250. IO.write(file, "config #{inspect(config.group)}, #{inspect(config.key)}, #{value}\r\n\r\n")
  251. config
  252. end
  253. defp delete(config, true) do
  254. {:ok, _} = Repo.delete(config)
  255. shell_info(
  256. "config #{inspect(config.group)}, #{inspect(config.key)} was deleted from the ConfigDB."
  257. )
  258. end
  259. defp delete(_config, _), do: :ok
  260. defp dump(%ConfigDB{} = config) do
  261. value = inspect(config.value, limit: :infinity)
  262. shell_info("config #{inspect(config.group)}, #{inspect(config.key)}, #{value}\r\n\r\n")
  263. end
  264. defp dump(_), do: :noop
  265. defp dump_group(group) when is_atom(group) do
  266. group
  267. |> ConfigDB.get_all_by_group()
  268. |> Enum.each(&dump/1)
  269. end
  270. defp group_exists?(group) do
  271. group
  272. |> ConfigDB.get_all_by_group()
  273. |> Enum.any?()
  274. end
  275. defp key_exists?(group, key) do
  276. group
  277. |> ConfigDB.get_by_group_and_key(key)
  278. |> is_nil
  279. |> Kernel.!()
  280. end
  281. defp maybe_atomize(arg) when is_atom(arg), do: arg
  282. defp maybe_atomize(":" <> arg), do: maybe_atomize(arg)
  283. defp maybe_atomize(arg) when is_binary(arg) do
  284. if ConfigDB.module_name?(arg) do
  285. String.to_existing_atom("Elixir." <> arg)
  286. else
  287. String.to_atom(arg)
  288. end
  289. end
  290. defp check_configdb(callback) do
  291. with true <- Pleroma.Config.get([:configurable_from_database]) do
  292. callback.()
  293. else
  294. _ ->
  295. shell_error(
  296. "ConfigDB not enabled. Please check the value of :configurable_from_database in your configuration."
  297. )
  298. end
  299. end
  300. defp delete_key(group, key) do
  301. check_configdb(fn ->
  302. ConfigDB.delete(%{group: group, key: key})
  303. end)
  304. end
  305. defp delete_group(group) do
  306. check_configdb(fn ->
  307. group
  308. |> ConfigDB.get_all_by_group()
  309. |> Enum.each(&ConfigDB.delete/1)
  310. end)
  311. end
  312. defp truncatedb do
  313. Ecto.Adapters.SQL.query!(Repo, "TRUNCATE config;")
  314. Ecto.Adapters.SQL.query!(Repo, "ALTER SEQUENCE config_id_seq RESTART;")
  315. end
  316. end