logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

config_controller_test.exs (48308B)


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