logo

pleroma

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

config_controller_test.exs (48744B)


  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 Pleroma.Web.AdminAPI.ConfigControllerTest do
  5. use Pleroma.Web.ConnCase
  6. import ExUnit.CaptureLog
  7. import Pleroma.Factory
  8. alias Pleroma.ConfigDB
  9. setup do
  10. admin = insert(:user, is_admin: true)
  11. token = insert(:oauth_admin_token, user: admin)
  12. conn =
  13. build_conn()
  14. |> assign(:user, admin)
  15. |> assign(:token, token)
  16. {:ok, %{admin: admin, token: token, conn: conn}}
  17. end
  18. describe "GET /api/pleroma/admin/config" do
  19. setup do: clear_config(:configurable_from_database, true)
  20. test "when configuration from database is off", %{conn: conn} do
  21. clear_config(:configurable_from_database, false)
  22. conn = get(conn, "/api/pleroma/admin/config")
  23. assert json_response_and_validate_schema(conn, 400) ==
  24. %{
  25. "error" => "You must enable configurable_from_database in your config file."
  26. }
  27. end
  28. test "with settings only in db", %{conn: conn} do
  29. config1 = insert(:config)
  30. config2 = insert(:config)
  31. conn = get(conn, "/api/pleroma/admin/config?only_db=true")
  32. %{
  33. "configs" => [
  34. %{
  35. "group" => ":pleroma",
  36. "key" => key1,
  37. "value" => _
  38. },
  39. %{
  40. "group" => ":pleroma",
  41. "key" => key2,
  42. "value" => _
  43. }
  44. ]
  45. } = json_response_and_validate_schema(conn, 200)
  46. assert key1 == inspect(config1.key)
  47. assert key2 == inspect(config2.key)
  48. end
  49. test "db is added to settings that are in db", %{conn: conn} do
  50. _config = insert(:config, key: ":instance", value: [name: "Some name"])
  51. %{"configs" => configs} =
  52. conn
  53. |> get("/api/pleroma/admin/config")
  54. |> json_response_and_validate_schema(200)
  55. [instance_config] =
  56. Enum.filter(configs, fn %{"group" => group, "key" => key} ->
  57. group == ":pleroma" and key == ":instance"
  58. end)
  59. assert instance_config["db"] == [":name"]
  60. end
  61. test "merged default setting with db settings", %{conn: conn} do
  62. config1 = insert(:config)
  63. config2 = insert(:config)
  64. config3 =
  65. insert(:config,
  66. value: [k1: :v1, k2: :v2]
  67. )
  68. %{"configs" => configs} =
  69. conn
  70. |> get("/api/pleroma/admin/config")
  71. |> json_response_and_validate_schema(200)
  72. assert length(configs) > 3
  73. saved_configs = [config1, config2, config3]
  74. keys = Enum.map(saved_configs, &inspect(&1.key))
  75. received_configs =
  76. Enum.filter(configs, fn %{"group" => group, "key" => key} ->
  77. group == ":pleroma" and key in keys
  78. end)
  79. assert length(received_configs) == 3
  80. db_keys =
  81. config3.value
  82. |> Keyword.keys()
  83. |> ConfigDB.to_json_types()
  84. keys = Enum.map(saved_configs -- [config3], &inspect(&1.key))
  85. values = Enum.map(saved_configs, &ConfigDB.to_json_types(&1.value))
  86. mapset_keys = MapSet.new(keys ++ db_keys)
  87. Enum.each(received_configs, fn %{"value" => value, "db" => db} ->
  88. db = MapSet.new(db)
  89. assert MapSet.subset?(db, mapset_keys)
  90. assert value in values
  91. end)
  92. end
  93. test "subkeys with full update right merge", %{conn: conn} do
  94. insert(:config,
  95. key: ":emoji",
  96. value: [groups: [a: 1, b: 2], key: [a: 1]]
  97. )
  98. insert(:config,
  99. key: ":assets",
  100. value: [mascots: [a: 1, b: 2], key: [a: 1]]
  101. )
  102. %{"configs" => configs} =
  103. conn
  104. |> get("/api/pleroma/admin/config")
  105. |> json_response_and_validate_schema(200)
  106. vals =
  107. Enum.filter(configs, fn %{"group" => group, "key" => key} ->
  108. group == ":pleroma" and key in [":emoji", ":assets"]
  109. end)
  110. emoji = Enum.find(vals, fn %{"key" => key} -> key == ":emoji" end)
  111. assets = Enum.find(vals, fn %{"key" => key} -> key == ":assets" end)
  112. emoji_val = ConfigDB.to_elixir_types(emoji["value"])
  113. assets_val = ConfigDB.to_elixir_types(assets["value"])
  114. assert emoji_val[:groups] == [a: 1, b: 2]
  115. assert assets_val[:mascots] == [a: 1, b: 2]
  116. end
  117. test "with valid `admin_token` query parameter, skips OAuth scopes check" do
  118. clear_config([:admin_token], "password123")
  119. build_conn()
  120. |> get("/api/pleroma/admin/config?admin_token=password123")
  121. |> json_response_and_validate_schema(200)
  122. end
  123. end
  124. test "POST /api/pleroma/admin/config with configdb disabled", %{conn: conn} do
  125. clear_config(:configurable_from_database, false)
  126. conn =
  127. conn
  128. |> put_req_header("content-type", "application/json")
  129. |> post("/api/pleroma/admin/config", %{"configs" => []})
  130. assert json_response_and_validate_schema(conn, 400) ==
  131. %{"error" => "You must enable configurable_from_database in your config file."}
  132. end
  133. describe "POST /api/pleroma/admin/config" do
  134. setup do
  135. http = Application.get_env(:pleroma, :http)
  136. on_exit(fn ->
  137. Application.delete_env(:pleroma, :key1)
  138. Application.delete_env(:pleroma, :key2)
  139. Application.delete_env(:pleroma, :key3)
  140. Application.delete_env(:pleroma, :key4)
  141. Application.delete_env(:pleroma, :keyaa1)
  142. Application.delete_env(:pleroma, :keyaa2)
  143. Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
  144. Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
  145. Application.put_env(:pleroma, :http, http)
  146. Application.put_env(:tesla, :adapter, Tesla.Mock)
  147. Restarter.Pleroma.refresh()
  148. end)
  149. end
  150. setup do: clear_config(:configurable_from_database, true)
  151. test "create new config setting in db", %{conn: conn} do
  152. ueberauth = Application.get_env(:ueberauth, Ueberauth)
  153. on_exit(fn -> Application.put_env(:ueberauth, Ueberauth, ueberauth) end)
  154. conn =
  155. conn
  156. |> put_req_header("content-type", "application/json")
  157. |> post("/api/pleroma/admin/config", %{
  158. configs: [
  159. %{group: ":pleroma", key: ":key1", value: "value1"},
  160. %{
  161. group: ":ueberauth",
  162. key: "Ueberauth",
  163. value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
  164. },
  165. %{
  166. group: ":pleroma",
  167. key: ":key2",
  168. value: %{
  169. ":nested_1" => "nested_value1",
  170. ":nested_2" => [
  171. %{":nested_22" => "nested_value222"},
  172. %{":nested_33" => %{":nested_44" => "nested_444"}}
  173. ]
  174. }
  175. },
  176. %{
  177. group: ":pleroma",
  178. key: ":key3",
  179. value: [
  180. %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
  181. %{"nested_4" => true}
  182. ]
  183. },
  184. %{
  185. group: ":pleroma",
  186. key: ":key4",
  187. value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
  188. },
  189. %{
  190. group: ":idna",
  191. key: ":key5",
  192. value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
  193. }
  194. ]
  195. })
  196. assert json_response_and_validate_schema(conn, 200) == %{
  197. "configs" => [
  198. %{
  199. "group" => ":pleroma",
  200. "key" => ":key1",
  201. "value" => "value1",
  202. "db" => [":key1"]
  203. },
  204. %{
  205. "group" => ":ueberauth",
  206. "key" => "Ueberauth",
  207. "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}],
  208. "db" => [":consumer_secret"]
  209. },
  210. %{
  211. "group" => ":pleroma",
  212. "key" => ":key2",
  213. "value" => %{
  214. ":nested_1" => "nested_value1",
  215. ":nested_2" => [
  216. %{":nested_22" => "nested_value222"},
  217. %{":nested_33" => %{":nested_44" => "nested_444"}}
  218. ]
  219. },
  220. "db" => [":key2"]
  221. },
  222. %{
  223. "group" => ":pleroma",
  224. "key" => ":key3",
  225. "value" => [
  226. %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
  227. %{"nested_4" => true}
  228. ],
  229. "db" => [":key3"]
  230. },
  231. %{
  232. "group" => ":pleroma",
  233. "key" => ":key4",
  234. "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"},
  235. "db" => [":key4"]
  236. },
  237. %{
  238. "group" => ":idna",
  239. "key" => ":key5",
  240. "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]},
  241. "db" => [":key5"]
  242. }
  243. ],
  244. "need_reboot" => false
  245. }
  246. assert Application.get_env(:pleroma, :key1) == "value1"
  247. assert Application.get_env(:pleroma, :key2) == %{
  248. nested_1: "nested_value1",
  249. nested_2: [
  250. %{nested_22: "nested_value222"},
  251. %{nested_33: %{nested_44: "nested_444"}}
  252. ]
  253. }
  254. assert Application.get_env(:pleroma, :key3) == [
  255. %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
  256. %{"nested_4" => true}
  257. ]
  258. assert Application.get_env(:pleroma, :key4) == %{
  259. "endpoint" => "https://example.com",
  260. nested_5: :upload
  261. }
  262. assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
  263. end
  264. test "save configs setting without explicit key", %{conn: conn} do
  265. adapter = Application.get_env(:http, :adapter)
  266. send_user_agent = Application.get_env(:http, :send_user_agent)
  267. user_agent = Application.get_env(:http, :user_agent)
  268. on_exit(fn ->
  269. Application.put_env(:http, :adapter, adapter)
  270. Application.put_env(:http, :send_user_agent, send_user_agent)
  271. Application.put_env(:http, :user_agent, user_agent)
  272. end)
  273. conn =
  274. conn
  275. |> put_req_header("content-type", "application/json")
  276. |> post("/api/pleroma/admin/config", %{
  277. configs: [
  278. %{
  279. group: ":http",
  280. key: ":adapter",
  281. value: [":someval"]
  282. },
  283. %{
  284. group: ":http",
  285. key: ":send_user_agent",
  286. value: true
  287. },
  288. %{
  289. group: ":http",
  290. key: ":user_agent",
  291. value: [":default"]
  292. }
  293. ]
  294. })
  295. assert json_response_and_validate_schema(conn, 200) == %{
  296. "configs" => [
  297. %{
  298. "group" => ":http",
  299. "key" => ":adapter",
  300. "value" => [":someval"],
  301. "db" => [":adapter"]
  302. },
  303. %{
  304. "group" => ":http",
  305. "key" => ":send_user_agent",
  306. "value" => true,
  307. "db" => [":send_user_agent"]
  308. },
  309. %{
  310. "group" => ":http",
  311. "key" => ":user_agent",
  312. "value" => [":default"],
  313. "db" => [":user_agent"]
  314. }
  315. ],
  316. "need_reboot" => false
  317. }
  318. assert Application.get_env(:http, :adapter) == [:someval]
  319. assert Application.get_env(:http, :send_user_agent) == true
  320. assert Application.get_env(:http, :user_agent) == [:default]
  321. end
  322. test "saving config with partial update", %{conn: conn} do
  323. insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2))
  324. conn =
  325. conn
  326. |> put_req_header("content-type", "application/json")
  327. |> post("/api/pleroma/admin/config", %{
  328. configs: [
  329. %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
  330. ]
  331. })
  332. assert json_response_and_validate_schema(conn, 200) == %{
  333. "configs" => [
  334. %{
  335. "group" => ":pleroma",
  336. "key" => ":key1",
  337. "value" => [
  338. %{"tuple" => [":key1", 1]},
  339. %{"tuple" => [":key2", 2]},
  340. %{"tuple" => [":key3", 3]}
  341. ],
  342. "db" => [":key1", ":key2", ":key3"]
  343. }
  344. ],
  345. "need_reboot" => false
  346. }
  347. end
  348. test "saving config which need pleroma reboot", %{conn: conn} do
  349. clear_config([:shout, :enabled], true)
  350. assert conn
  351. |> put_req_header("content-type", "application/json")
  352. |> post(
  353. "/api/pleroma/admin/config",
  354. %{
  355. configs: [
  356. %{group: ":pleroma", key: ":shout", value: [%{"tuple" => [":enabled", true]}]}
  357. ]
  358. }
  359. )
  360. |> json_response_and_validate_schema(200) == %{
  361. "configs" => [
  362. %{
  363. "db" => [":enabled"],
  364. "group" => ":pleroma",
  365. "key" => ":shout",
  366. "value" => [%{"tuple" => [":enabled", true]}]
  367. }
  368. ],
  369. "need_reboot" => true
  370. }
  371. configs =
  372. conn
  373. |> get("/api/pleroma/admin/config")
  374. |> json_response_and_validate_schema(200)
  375. assert configs["need_reboot"]
  376. capture_log(fn ->
  377. assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) ==
  378. %{}
  379. end) =~ "pleroma restarted"
  380. configs =
  381. conn
  382. |> get("/api/pleroma/admin/config")
  383. |> json_response_and_validate_schema(200)
  384. assert configs["need_reboot"] == false
  385. end
  386. test "update setting which need reboot, don't change reboot flag until reboot", %{conn: conn} do
  387. clear_config([:shout, :enabled], true)
  388. assert conn
  389. |> put_req_header("content-type", "application/json")
  390. |> post(
  391. "/api/pleroma/admin/config",
  392. %{
  393. configs: [
  394. %{group: ":pleroma", key: ":shout", value: [%{"tuple" => [":enabled", true]}]}
  395. ]
  396. }
  397. )
  398. |> json_response_and_validate_schema(200) == %{
  399. "configs" => [
  400. %{
  401. "db" => [":enabled"],
  402. "group" => ":pleroma",
  403. "key" => ":shout",
  404. "value" => [%{"tuple" => [":enabled", true]}]
  405. }
  406. ],
  407. "need_reboot" => true
  408. }
  409. assert conn
  410. |> put_req_header("content-type", "application/json")
  411. |> post("/api/pleroma/admin/config", %{
  412. configs: [
  413. %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
  414. ]
  415. })
  416. |> json_response_and_validate_schema(200) == %{
  417. "configs" => [
  418. %{
  419. "group" => ":pleroma",
  420. "key" => ":key1",
  421. "value" => [
  422. %{"tuple" => [":key3", 3]}
  423. ],
  424. "db" => [":key3"]
  425. }
  426. ],
  427. "need_reboot" => true
  428. }
  429. capture_log(fn ->
  430. assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) ==
  431. %{}
  432. end) =~ "pleroma restarted"
  433. configs =
  434. conn
  435. |> get("/api/pleroma/admin/config")
  436. |> json_response_and_validate_schema(200)
  437. assert configs["need_reboot"] == false
  438. end
  439. test "saving config with nested merge", %{conn: conn} do
  440. insert(:config, key: :key1, value: [key1: 1, key2: [k1: 1, k2: 2]])
  441. conn =
  442. conn
  443. |> put_req_header("content-type", "application/json")
  444. |> post("/api/pleroma/admin/config", %{
  445. configs: [
  446. %{
  447. group: ":pleroma",
  448. key: ":key1",
  449. value: [
  450. %{"tuple" => [":key3", 3]},
  451. %{
  452. "tuple" => [
  453. ":key2",
  454. [
  455. %{"tuple" => [":k2", 1]},
  456. %{"tuple" => [":k3", 3]}
  457. ]
  458. ]
  459. }
  460. ]
  461. }
  462. ]
  463. })
  464. assert json_response_and_validate_schema(conn, 200) == %{
  465. "configs" => [
  466. %{
  467. "group" => ":pleroma",
  468. "key" => ":key1",
  469. "value" => [
  470. %{"tuple" => [":key1", 1]},
  471. %{"tuple" => [":key3", 3]},
  472. %{
  473. "tuple" => [
  474. ":key2",
  475. [
  476. %{"tuple" => [":k1", 1]},
  477. %{"tuple" => [":k2", 1]},
  478. %{"tuple" => [":k3", 3]}
  479. ]
  480. ]
  481. }
  482. ],
  483. "db" => [":key1", ":key3", ":key2"]
  484. }
  485. ],
  486. "need_reboot" => false
  487. }
  488. end
  489. test "saving special atoms", %{conn: conn} do
  490. conn =
  491. conn
  492. |> put_req_header("content-type", "application/json")
  493. |> post("/api/pleroma/admin/config", %{
  494. "configs" => [
  495. %{
  496. "group" => ":pleroma",
  497. "key" => ":key1",
  498. "value" => [
  499. %{
  500. "tuple" => [
  501. ":ssl_options",
  502. [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
  503. ]
  504. }
  505. ]
  506. }
  507. ]
  508. })
  509. assert json_response_and_validate_schema(conn, 200) == %{
  510. "configs" => [
  511. %{
  512. "group" => ":pleroma",
  513. "key" => ":key1",
  514. "value" => [
  515. %{
  516. "tuple" => [
  517. ":ssl_options",
  518. [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
  519. ]
  520. }
  521. ],
  522. "db" => [":ssl_options"]
  523. }
  524. ],
  525. "need_reboot" => false
  526. }
  527. assert Application.get_env(:pleroma, :key1) == [
  528. ssl_options: [versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]]
  529. ]
  530. end
  531. test "saving full setting if value is not keyword", %{conn: conn} do
  532. insert(:config,
  533. group: :tesla,
  534. key: :adapter,
  535. value: Tesla.Adapter.Hackey
  536. )
  537. conn =
  538. conn
  539. |> put_req_header("content-type", "application/json")
  540. |> post("/api/pleroma/admin/config", %{
  541. configs: [
  542. %{group: ":tesla", key: ":adapter", value: "Tesla.Adapter.Httpc"}
  543. ]
  544. })
  545. assert json_response_and_validate_schema(conn, 200) == %{
  546. "configs" => [
  547. %{
  548. "group" => ":tesla",
  549. "key" => ":adapter",
  550. "value" => "Tesla.Adapter.Httpc",
  551. "db" => [":adapter"]
  552. }
  553. ],
  554. "need_reboot" => false
  555. }
  556. end
  557. test "update config setting & delete with fallback to default value", %{
  558. conn: conn,
  559. admin: admin,
  560. token: token
  561. } do
  562. ueberauth = Application.get_env(:ueberauth, Ueberauth)
  563. insert(:config, key: :keyaa1)
  564. insert(:config, key: :keyaa2)
  565. config3 =
  566. insert(:config,
  567. group: :ueberauth,
  568. key: Ueberauth
  569. )
  570. conn =
  571. conn
  572. |> put_req_header("content-type", "application/json")
  573. |> post("/api/pleroma/admin/config", %{
  574. configs: [
  575. %{group: ":pleroma", key: ":keyaa1", value: "another_value"},
  576. %{group: ":pleroma", key: ":keyaa2", value: "another_value"}
  577. ]
  578. })
  579. assert json_response_and_validate_schema(conn, 200) == %{
  580. "configs" => [
  581. %{
  582. "group" => ":pleroma",
  583. "key" => ":keyaa1",
  584. "value" => "another_value",
  585. "db" => [":keyaa1"]
  586. },
  587. %{
  588. "group" => ":pleroma",
  589. "key" => ":keyaa2",
  590. "value" => "another_value",
  591. "db" => [":keyaa2"]
  592. }
  593. ],
  594. "need_reboot" => false
  595. }
  596. assert Application.get_env(:pleroma, :keyaa1) == "another_value"
  597. assert Application.get_env(:pleroma, :keyaa2) == "another_value"
  598. assert Application.get_env(:ueberauth, Ueberauth) == config3.value
  599. conn =
  600. build_conn()
  601. |> assign(:user, admin)
  602. |> assign(:token, token)
  603. |> put_req_header("content-type", "application/json")
  604. |> post("/api/pleroma/admin/config", %{
  605. configs: [
  606. %{group: ":pleroma", key: ":keyaa2", delete: true},
  607. %{
  608. group: ":ueberauth",
  609. key: "Ueberauth",
  610. delete: true
  611. }
  612. ]
  613. })
  614. assert json_response_and_validate_schema(conn, 200) == %{
  615. "configs" => [],
  616. "need_reboot" => false
  617. }
  618. assert Application.get_env(:ueberauth, Ueberauth) == ueberauth
  619. refute Keyword.has_key?(Application.get_all_env(:pleroma), :keyaa2)
  620. end
  621. test "common config example", %{conn: conn} do
  622. conn =
  623. conn
  624. |> put_req_header("content-type", "application/json")
  625. |> post("/api/pleroma/admin/config", %{
  626. configs: [
  627. %{
  628. "group" => ":pleroma",
  629. "key" => "Pleroma.Captcha.NotReal",
  630. "value" => [
  631. %{"tuple" => [":enabled", false]},
  632. %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
  633. %{"tuple" => [":seconds_valid", 60]},
  634. %{"tuple" => [":path", ""]},
  635. %{"tuple" => [":key1", nil]},
  636. %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
  637. %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
  638. %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
  639. %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
  640. %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},
  641. %{"tuple" => [":name", "Pleroma"]}
  642. ]
  643. }
  644. ]
  645. })
  646. assert Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"
  647. assert json_response_and_validate_schema(conn, 200) == %{
  648. "configs" => [
  649. %{
  650. "group" => ":pleroma",
  651. "key" => "Pleroma.Captcha.NotReal",
  652. "value" => [
  653. %{"tuple" => [":enabled", false]},
  654. %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
  655. %{"tuple" => [":seconds_valid", 60]},
  656. %{"tuple" => [":path", ""]},
  657. %{"tuple" => [":key1", nil]},
  658. %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
  659. %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
  660. %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
  661. %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
  662. %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]},
  663. %{"tuple" => [":name", "Pleroma"]}
  664. ],
  665. "db" => [
  666. ":enabled",
  667. ":method",
  668. ":seconds_valid",
  669. ":path",
  670. ":key1",
  671. ":partial_chain",
  672. ":regex1",
  673. ":regex2",
  674. ":regex3",
  675. ":regex4",
  676. ":name"
  677. ]
  678. }
  679. ],
  680. "need_reboot" => false
  681. }
  682. end
  683. test "tuples with more than two values", %{conn: conn} do
  684. conn =
  685. conn
  686. |> put_req_header("content-type", "application/json")
  687. |> post("/api/pleroma/admin/config", %{
  688. configs: [
  689. %{
  690. "group" => ":pleroma",
  691. "key" => "Pleroma.Web.Endpoint.NotReal",
  692. "value" => [
  693. %{
  694. "tuple" => [
  695. ":http",
  696. [
  697. %{
  698. "tuple" => [
  699. ":key2",
  700. [
  701. %{
  702. "tuple" => [
  703. ":_",
  704. [
  705. %{
  706. "tuple" => [
  707. "/api/v1/streaming",
  708. "Pleroma.Web.MastodonAPI.WebsocketHandler",
  709. []
  710. ]
  711. },
  712. %{
  713. "tuple" => [
  714. "/websocket",
  715. "Phoenix.Endpoint.CowboyWebSocket",
  716. %{
  717. "tuple" => [
  718. "Phoenix.Transports.WebSocket",
  719. %{
  720. "tuple" => [
  721. "Pleroma.Web.Endpoint",
  722. "Pleroma.Web.UserSocket",
  723. []
  724. ]
  725. }
  726. ]
  727. }
  728. ]
  729. },
  730. %{
  731. "tuple" => [
  732. ":_",
  733. "Plug.Cowboy.Handler",
  734. %{"tuple" => ["Pleroma.Web.Endpoint", []]}
  735. ]
  736. }
  737. ]
  738. ]
  739. }
  740. ]
  741. ]
  742. }
  743. ]
  744. ]
  745. }
  746. ]
  747. }
  748. ]
  749. })
  750. assert json_response_and_validate_schema(conn, 200) == %{
  751. "configs" => [
  752. %{
  753. "group" => ":pleroma",
  754. "key" => "Pleroma.Web.Endpoint.NotReal",
  755. "value" => [
  756. %{
  757. "tuple" => [
  758. ":http",
  759. [
  760. %{
  761. "tuple" => [
  762. ":key2",
  763. [
  764. %{
  765. "tuple" => [
  766. ":_",
  767. [
  768. %{
  769. "tuple" => [
  770. "/api/v1/streaming",
  771. "Pleroma.Web.MastodonAPI.WebsocketHandler",
  772. []
  773. ]
  774. },
  775. %{
  776. "tuple" => [
  777. "/websocket",
  778. "Phoenix.Endpoint.CowboyWebSocket",
  779. %{
  780. "tuple" => [
  781. "Phoenix.Transports.WebSocket",
  782. %{
  783. "tuple" => [
  784. "Pleroma.Web.Endpoint",
  785. "Pleroma.Web.UserSocket",
  786. []
  787. ]
  788. }
  789. ]
  790. }
  791. ]
  792. },
  793. %{
  794. "tuple" => [
  795. ":_",
  796. "Plug.Cowboy.Handler",
  797. %{"tuple" => ["Pleroma.Web.Endpoint", []]}
  798. ]
  799. }
  800. ]
  801. ]
  802. }
  803. ]
  804. ]
  805. }
  806. ]
  807. ]
  808. }
  809. ],
  810. "db" => [":http"]
  811. }
  812. ],
  813. "need_reboot" => false
  814. }
  815. end
  816. test "settings with nesting map", %{conn: conn} do
  817. conn =
  818. conn
  819. |> put_req_header("content-type", "application/json")
  820. |> post("/api/pleroma/admin/config", %{
  821. configs: [
  822. %{
  823. "group" => ":pleroma",
  824. "key" => ":key1",
  825. "value" => [
  826. %{"tuple" => [":key2", "some_val"]},
  827. %{
  828. "tuple" => [
  829. ":key3",
  830. %{
  831. ":max_options" => 20,
  832. ":max_option_chars" => 200,
  833. ":min_expiration" => 0,
  834. ":max_expiration" => 31_536_000,
  835. "nested" => %{
  836. ":max_options" => 20,
  837. ":max_option_chars" => 200,
  838. ":min_expiration" => 0,
  839. ":max_expiration" => 31_536_000
  840. }
  841. }
  842. ]
  843. }
  844. ]
  845. }
  846. ]
  847. })
  848. assert json_response_and_validate_schema(conn, 200) ==
  849. %{
  850. "configs" => [
  851. %{
  852. "group" => ":pleroma",
  853. "key" => ":key1",
  854. "value" => [
  855. %{"tuple" => [":key2", "some_val"]},
  856. %{
  857. "tuple" => [
  858. ":key3",
  859. %{
  860. ":max_expiration" => 31_536_000,
  861. ":max_option_chars" => 200,
  862. ":max_options" => 20,
  863. ":min_expiration" => 0,
  864. "nested" => %{
  865. ":max_expiration" => 31_536_000,
  866. ":max_option_chars" => 200,
  867. ":max_options" => 20,
  868. ":min_expiration" => 0
  869. }
  870. }
  871. ]
  872. }
  873. ],
  874. "db" => [":key2", ":key3"]
  875. }
  876. ],
  877. "need_reboot" => false
  878. }
  879. end
  880. test "value as map", %{conn: conn} do
  881. conn =
  882. conn
  883. |> put_req_header("content-type", "application/json")
  884. |> post("/api/pleroma/admin/config", %{
  885. configs: [
  886. %{
  887. "group" => ":pleroma",
  888. "key" => ":key1",
  889. "value" => %{"key" => "some_val"}
  890. }
  891. ]
  892. })
  893. assert json_response_and_validate_schema(conn, 200) ==
  894. %{
  895. "configs" => [
  896. %{
  897. "group" => ":pleroma",
  898. "key" => ":key1",
  899. "value" => %{"key" => "some_val"},
  900. "db" => [":key1"]
  901. }
  902. ],
  903. "need_reboot" => false
  904. }
  905. end
  906. test "queues key as atom", %{conn: conn} do
  907. conn =
  908. conn
  909. |> put_req_header("content-type", "application/json")
  910. |> post("/api/pleroma/admin/config", %{
  911. configs: [
  912. %{
  913. "group" => ":oban",
  914. "key" => ":queues",
  915. "value" => [
  916. %{"tuple" => [":federator_incoming", 50]},
  917. %{"tuple" => [":federator_outgoing", 50]},
  918. %{"tuple" => [":web_push", 50]},
  919. %{"tuple" => [":mailer", 10]},
  920. %{"tuple" => [":transmogrifier", 20]},
  921. %{"tuple" => [":scheduled_activities", 10]},
  922. %{"tuple" => [":background", 5]}
  923. ]
  924. }
  925. ]
  926. })
  927. assert json_response_and_validate_schema(conn, 200) == %{
  928. "configs" => [
  929. %{
  930. "group" => ":oban",
  931. "key" => ":queues",
  932. "value" => [
  933. %{"tuple" => [":federator_incoming", 50]},
  934. %{"tuple" => [":federator_outgoing", 50]},
  935. %{"tuple" => [":web_push", 50]},
  936. %{"tuple" => [":mailer", 10]},
  937. %{"tuple" => [":transmogrifier", 20]},
  938. %{"tuple" => [":scheduled_activities", 10]},
  939. %{"tuple" => [":background", 5]}
  940. ],
  941. "db" => [
  942. ":federator_incoming",
  943. ":federator_outgoing",
  944. ":web_push",
  945. ":mailer",
  946. ":transmogrifier",
  947. ":scheduled_activities",
  948. ":background"
  949. ]
  950. }
  951. ],
  952. "need_reboot" => false
  953. }
  954. end
  955. test "delete part of settings by atom subkeys", %{conn: conn} do
  956. insert(:config,
  957. key: :keyaa1,
  958. value: [subkey1: "val1", subkey2: "val2", subkey3: "val3"]
  959. )
  960. conn =
  961. conn
  962. |> put_req_header("content-type", "application/json")
  963. |> post("/api/pleroma/admin/config", %{
  964. configs: [
  965. %{
  966. group: ":pleroma",
  967. key: ":keyaa1",
  968. subkeys: [":subkey1", ":subkey3"],
  969. delete: true
  970. }
  971. ]
  972. })
  973. assert json_response_and_validate_schema(conn, 200) == %{
  974. "configs" => [
  975. %{
  976. "group" => ":pleroma",
  977. "key" => ":keyaa1",
  978. "value" => [%{"tuple" => [":subkey2", "val2"]}],
  979. "db" => [":subkey2"]
  980. }
  981. ],
  982. "need_reboot" => false
  983. }
  984. end
  985. test "proxy tuple localhost", %{conn: conn} do
  986. conn =
  987. conn
  988. |> put_req_header("content-type", "application/json")
  989. |> post("/api/pleroma/admin/config", %{
  990. configs: [
  991. %{
  992. group: ":pleroma",
  993. key: ":http",
  994. value: [
  995. %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]}
  996. ]
  997. }
  998. ]
  999. })
  1000. assert %{
  1001. "configs" => [
  1002. %{
  1003. "group" => ":pleroma",
  1004. "key" => ":http",
  1005. "value" => value,
  1006. "db" => db
  1007. }
  1008. ]
  1009. } = json_response_and_validate_schema(conn, 200)
  1010. assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]} in value
  1011. assert ":proxy_url" in db
  1012. end
  1013. test "proxy tuple domain", %{conn: conn} do
  1014. conn =
  1015. conn
  1016. |> put_req_header("content-type", "application/json")
  1017. |> post("/api/pleroma/admin/config", %{
  1018. configs: [
  1019. %{
  1020. group: ":pleroma",
  1021. key: ":http",
  1022. value: [
  1023. %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]}
  1024. ]
  1025. }
  1026. ]
  1027. })
  1028. assert %{
  1029. "configs" => [
  1030. %{
  1031. "group" => ":pleroma",
  1032. "key" => ":http",
  1033. "value" => value,
  1034. "db" => db
  1035. }
  1036. ]
  1037. } = json_response_and_validate_schema(conn, 200)
  1038. assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]} in value
  1039. assert ":proxy_url" in db
  1040. end
  1041. test "proxy tuple ip", %{conn: conn} do
  1042. conn =
  1043. conn
  1044. |> put_req_header("content-type", "application/json")
  1045. |> post("/api/pleroma/admin/config", %{
  1046. configs: [
  1047. %{
  1048. group: ":pleroma",
  1049. key: ":http",
  1050. value: [
  1051. %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]}
  1052. ]
  1053. }
  1054. ]
  1055. })
  1056. assert %{
  1057. "configs" => [
  1058. %{
  1059. "group" => ":pleroma",
  1060. "key" => ":http",
  1061. "value" => value,
  1062. "db" => db
  1063. }
  1064. ]
  1065. } = json_response_and_validate_schema(conn, 200)
  1066. assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]} in value
  1067. assert ":proxy_url" in db
  1068. end
  1069. test "doesn't set keys not in the whitelist", %{conn: conn} do
  1070. clear_config(:database_config_whitelist, [
  1071. {:pleroma, :key1},
  1072. {:pleroma, :key2},
  1073. {:pleroma, Pleroma.Captcha.NotReal},
  1074. {:not_real}
  1075. ])
  1076. conn
  1077. |> put_req_header("content-type", "application/json")
  1078. |> post("/api/pleroma/admin/config", %{
  1079. configs: [
  1080. %{group: ":pleroma", key: ":key1", value: "value1"},
  1081. %{group: ":pleroma", key: ":key2", value: "value2"},
  1082. %{group: ":pleroma", key: ":key3", value: "value3"},
  1083. %{group: ":pleroma", key: "Pleroma.Web.Endpoint.NotReal", value: "value4"},
  1084. %{group: ":pleroma", key: "Pleroma.Captcha.NotReal", value: "value5"},
  1085. %{group: ":not_real", key: ":anything", value: "value6"}
  1086. ]
  1087. })
  1088. assert Application.get_env(:pleroma, :key1) == "value1"
  1089. assert Application.get_env(:pleroma, :key2) == "value2"
  1090. assert Application.get_env(:pleroma, :key3) == nil
  1091. assert Application.get_env(:pleroma, Pleroma.Web.Endpoint.NotReal) == nil
  1092. assert Application.get_env(:pleroma, Pleroma.Captcha.NotReal) == "value5"
  1093. assert Application.get_env(:not_real, :anything) == "value6"
  1094. end
  1095. test "args for Pleroma.Upload.Filter.Mogrify with custom tuples", %{conn: conn} do
  1096. assert conn
  1097. |> put_req_header("content-type", "application/json")
  1098. |> post("/api/pleroma/admin/config", %{
  1099. configs: [
  1100. %{
  1101. group: ":pleroma",
  1102. key: "Pleroma.Upload.Filter.Mogrify",
  1103. value: [
  1104. %{"tuple" => [":args", ["auto-orient", "strip"]]}
  1105. ]
  1106. }
  1107. ]
  1108. })
  1109. |> json_response_and_validate_schema(200) == %{
  1110. "configs" => [
  1111. %{
  1112. "group" => ":pleroma",
  1113. "key" => "Pleroma.Upload.Filter.Mogrify",
  1114. "value" => [
  1115. %{"tuple" => [":args", ["auto-orient", "strip"]]}
  1116. ],
  1117. "db" => [":args"]
  1118. }
  1119. ],
  1120. "need_reboot" => false
  1121. }
  1122. config = Config.get(Pleroma.Upload.Filter.Mogrify)
  1123. assert {:args, ["auto-orient", "strip"]} in config
  1124. assert conn
  1125. |> put_req_header("content-type", "application/json")
  1126. |> post("/api/pleroma/admin/config", %{
  1127. configs: [
  1128. %{
  1129. group: ":pleroma",
  1130. key: "Pleroma.Upload.Filter.Mogrify",
  1131. value: [
  1132. %{
  1133. "tuple" => [
  1134. ":args",
  1135. [
  1136. "auto-orient",
  1137. "strip",
  1138. "{\"implode\", \"1\"}",
  1139. "{\"resize\", \"3840x1080>\"}"
  1140. ]
  1141. ]
  1142. }
  1143. ]
  1144. }
  1145. ]
  1146. })
  1147. |> json_response(200) == %{
  1148. "configs" => [
  1149. %{
  1150. "group" => ":pleroma",
  1151. "key" => "Pleroma.Upload.Filter.Mogrify",
  1152. "value" => [
  1153. %{
  1154. "tuple" => [
  1155. ":args",
  1156. [
  1157. "auto-orient",
  1158. "strip",
  1159. "{\"implode\", \"1\"}",
  1160. "{\"resize\", \"3840x1080>\"}"
  1161. ]
  1162. ]
  1163. }
  1164. ],
  1165. "db" => [":args"]
  1166. }
  1167. ],
  1168. "need_reboot" => false
  1169. }
  1170. config = Config.get(Pleroma.Upload.Filter.Mogrify)
  1171. assert {:args, ["auto-orient", "strip", {"implode", "1"}, {"resize", "3840x1080>"}]} in config
  1172. end
  1173. test "enables the welcome messages", %{conn: conn} do
  1174. clear_config([:welcome])
  1175. params = %{
  1176. "group" => ":pleroma",
  1177. "key" => ":welcome",
  1178. "value" => [
  1179. %{
  1180. "tuple" => [
  1181. ":direct_message",
  1182. [
  1183. %{"tuple" => [":enabled", true]},
  1184. %{"tuple" => [":message", "Welcome to Pleroma!"]},
  1185. %{"tuple" => [":sender_nickname", "pleroma"]}
  1186. ]
  1187. ]
  1188. },
  1189. %{
  1190. "tuple" => [
  1191. ":chat_message",
  1192. [
  1193. %{"tuple" => [":enabled", true]},
  1194. %{"tuple" => [":message", "Welcome to Pleroma!"]},
  1195. %{"tuple" => [":sender_nickname", "pleroma"]}
  1196. ]
  1197. ]
  1198. },
  1199. %{
  1200. "tuple" => [
  1201. ":email",
  1202. [
  1203. %{"tuple" => [":enabled", true]},
  1204. %{"tuple" => [":sender", %{"tuple" => ["pleroma@dev.dev", "Pleroma"]}]},
  1205. %{"tuple" => [":subject", "Welcome to <%= instance_name %>!"]},
  1206. %{"tuple" => [":html", "Welcome to <%= instance_name %>!"]},
  1207. %{"tuple" => [":text", "Welcome to <%= instance_name %>!"]}
  1208. ]
  1209. ]
  1210. }
  1211. ]
  1212. }
  1213. refute Pleroma.User.WelcomeEmail.enabled?()
  1214. refute Pleroma.User.WelcomeMessage.enabled?()
  1215. refute Pleroma.User.WelcomeChatMessage.enabled?()
  1216. res =
  1217. assert conn
  1218. |> put_req_header("content-type", "application/json")
  1219. |> post("/api/pleroma/admin/config", %{"configs" => [params]})
  1220. |> json_response_and_validate_schema(200)
  1221. assert Pleroma.User.WelcomeEmail.enabled?()
  1222. assert Pleroma.User.WelcomeMessage.enabled?()
  1223. assert Pleroma.User.WelcomeChatMessage.enabled?()
  1224. assert res == %{
  1225. "configs" => [
  1226. %{
  1227. "db" => [":direct_message", ":chat_message", ":email"],
  1228. "group" => ":pleroma",
  1229. "key" => ":welcome",
  1230. "value" => params["value"]
  1231. }
  1232. ],
  1233. "need_reboot" => false
  1234. }
  1235. end
  1236. test "custom instance thumbnail", %{conn: conn} do
  1237. clear_config([:instance])
  1238. params = %{
  1239. "group" => ":pleroma",
  1240. "key" => ":instance",
  1241. "value" => [
  1242. %{
  1243. "tuple" => [
  1244. ":instance_thumbnail",
  1245. "https://example.com/media/new_thumbnail.jpg"
  1246. ]
  1247. }
  1248. ]
  1249. }
  1250. assert conn
  1251. |> put_req_header("content-type", "application/json")
  1252. |> post("/api/pleroma/admin/config", %{"configs" => [params]})
  1253. |> json_response_and_validate_schema(200) ==
  1254. %{
  1255. "configs" => [
  1256. %{
  1257. "db" => [":instance_thumbnail"],
  1258. "group" => ":pleroma",
  1259. "key" => ":instance",
  1260. "value" => params["value"]
  1261. }
  1262. ],
  1263. "need_reboot" => false
  1264. }
  1265. assert conn
  1266. |> get("/api/v1/instance")
  1267. |> json_response_and_validate_schema(200)
  1268. |> Map.take(["thumbnail"]) ==
  1269. %{"thumbnail" => "https://example.com/media/new_thumbnail.jpg"}
  1270. end
  1271. test "Concurrent Limiter", %{conn: conn} do
  1272. clear_config([ConcurrentLimiter])
  1273. params = %{
  1274. "group" => ":pleroma",
  1275. "key" => "ConcurrentLimiter",
  1276. "value" => [
  1277. %{
  1278. "tuple" => [
  1279. "Pleroma.Web.RichMedia.Helpers",
  1280. [
  1281. %{"tuple" => [":max_running", 6]},
  1282. %{"tuple" => [":max_waiting", 6]}
  1283. ]
  1284. ]
  1285. },
  1286. %{
  1287. "tuple" => [
  1288. "Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy",
  1289. [
  1290. %{"tuple" => [":max_running", 7]},
  1291. %{"tuple" => [":max_waiting", 7]}
  1292. ]
  1293. ]
  1294. }
  1295. ]
  1296. }
  1297. assert conn
  1298. |> put_req_header("content-type", "application/json")
  1299. |> post("/api/pleroma/admin/config", %{"configs" => [params]})
  1300. |> json_response_and_validate_schema(200)
  1301. end
  1302. end
  1303. describe "GET /api/pleroma/admin/config/descriptions" do
  1304. test "structure", %{conn: conn} do
  1305. conn = get(conn, "/api/pleroma/admin/config/descriptions")
  1306. assert [child | _others] = json_response_and_validate_schema(conn, 200)
  1307. assert child["children"]
  1308. assert child["key"]
  1309. assert String.starts_with?(child["group"], ":")
  1310. assert child["description"]
  1311. end
  1312. test "filters by database configuration whitelist", %{conn: conn} do
  1313. clear_config(:database_config_whitelist, [
  1314. {:pleroma, :instance},
  1315. {:pleroma, :activitypub},
  1316. {:pleroma, Pleroma.Upload}
  1317. ])
  1318. conn = get(conn, "/api/pleroma/admin/config/descriptions")
  1319. children = json_response_and_validate_schema(conn, 200)
  1320. assert length(children) == 3
  1321. assert Enum.count(children, fn c -> c["group"] == ":pleroma" end) == 3
  1322. instance = Enum.find(children, fn c -> c["key"] == ":instance" end)
  1323. assert instance["children"]
  1324. activitypub = Enum.find(children, fn c -> c["key"] == ":activitypub" end)
  1325. assert activitypub["children"]
  1326. web_endpoint = Enum.find(children, fn c -> c["key"] == "Pleroma.Upload" end)
  1327. assert web_endpoint["children"]
  1328. end
  1329. end
  1330. end