logo

pleroma

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

config_controller_test.exs (50128B)


  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. @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. @tag capture_log: true
  266. test "save configs setting without explicit key", %{conn: conn} do
  267. adapter = Application.get_env(:http, :adapter)
  268. send_user_agent = Application.get_env(:http, :send_user_agent)
  269. user_agent = Application.get_env(:http, :user_agent)
  270. on_exit(fn ->
  271. Application.put_env(:http, :adapter, adapter)
  272. Application.put_env(:http, :send_user_agent, send_user_agent)
  273. Application.put_env(:http, :user_agent, user_agent)
  274. end)
  275. conn =
  276. conn
  277. |> put_req_header("content-type", "application/json")
  278. |> post("/api/pleroma/admin/config", %{
  279. configs: [
  280. %{
  281. group: ":http",
  282. key: ":adapter",
  283. value: [":someval"]
  284. },
  285. %{
  286. group: ":http",
  287. key: ":send_user_agent",
  288. value: true
  289. },
  290. %{
  291. group: ":http",
  292. key: ":user_agent",
  293. value: [":default"]
  294. }
  295. ]
  296. })
  297. assert json_response_and_validate_schema(conn, 200) == %{
  298. "configs" => [
  299. %{
  300. "group" => ":http",
  301. "key" => ":adapter",
  302. "value" => [":someval"],
  303. "db" => [":adapter"]
  304. },
  305. %{
  306. "group" => ":http",
  307. "key" => ":send_user_agent",
  308. "value" => true,
  309. "db" => [":send_user_agent"]
  310. },
  311. %{
  312. "group" => ":http",
  313. "key" => ":user_agent",
  314. "value" => [":default"],
  315. "db" => [":user_agent"]
  316. }
  317. ],
  318. "need_reboot" => false
  319. }
  320. assert Application.get_env(:http, :adapter) == [:someval]
  321. assert Application.get_env(:http, :send_user_agent) == true
  322. assert Application.get_env(:http, :user_agent) == [:default]
  323. end
  324. test "saving config with partial update", %{conn: conn} do
  325. insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2))
  326. conn =
  327. conn
  328. |> put_req_header("content-type", "application/json")
  329. |> post("/api/pleroma/admin/config", %{
  330. configs: [
  331. %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
  332. ]
  333. })
  334. assert json_response_and_validate_schema(conn, 200) == %{
  335. "configs" => [
  336. %{
  337. "group" => ":pleroma",
  338. "key" => ":key1",
  339. "value" => [
  340. %{"tuple" => [":key1", 1]},
  341. %{"tuple" => [":key2", 2]},
  342. %{"tuple" => [":key3", 3]}
  343. ],
  344. "db" => [":key1", ":key2", ":key3"]
  345. }
  346. ],
  347. "need_reboot" => false
  348. }
  349. end
  350. test "saving config which need pleroma reboot", %{conn: conn} do
  351. clear_config([:shout, :enabled], true)
  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: ":shout", 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" => ":shout",
  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. clear_config([:shout, :enabled], true)
  390. assert conn
  391. |> put_req_header("content-type", "application/json")
  392. |> post(
  393. "/api/pleroma/admin/config",
  394. %{
  395. configs: [
  396. %{group: ":pleroma", key: ":shout", value: [%{"tuple" => [":enabled", true]}]}
  397. ]
  398. }
  399. )
  400. |> json_response_and_validate_schema(200) == %{
  401. "configs" => [
  402. %{
  403. "db" => [":enabled"],
  404. "group" => ":pleroma",
  405. "key" => ":shout",
  406. "value" => [%{"tuple" => [":enabled", true]}]
  407. }
  408. ],
  409. "need_reboot" => true
  410. }
  411. assert conn
  412. |> put_req_header("content-type", "application/json")
  413. |> post("/api/pleroma/admin/config", %{
  414. configs: [
  415. %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
  416. ]
  417. })
  418. |> json_response_and_validate_schema(200) == %{
  419. "configs" => [
  420. %{
  421. "group" => ":pleroma",
  422. "key" => ":key1",
  423. "value" => [
  424. %{"tuple" => [":key3", 3]}
  425. ],
  426. "db" => [":key3"]
  427. }
  428. ],
  429. "need_reboot" => true
  430. }
  431. capture_log(fn ->
  432. assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) ==
  433. %{}
  434. end) =~ "pleroma restarted"
  435. configs =
  436. conn
  437. |> get("/api/pleroma/admin/config")
  438. |> json_response_and_validate_schema(200)
  439. assert configs["need_reboot"] == false
  440. end
  441. test "saving config with nested merge", %{conn: conn} do
  442. insert(:config, key: :key1, value: [key1: 1, key2: [k1: 1, k2: 2]])
  443. conn =
  444. conn
  445. |> put_req_header("content-type", "application/json")
  446. |> post("/api/pleroma/admin/config", %{
  447. configs: [
  448. %{
  449. group: ":pleroma",
  450. key: ":key1",
  451. value: [
  452. %{"tuple" => [":key3", 3]},
  453. %{
  454. "tuple" => [
  455. ":key2",
  456. [
  457. %{"tuple" => [":k2", 1]},
  458. %{"tuple" => [":k3", 3]}
  459. ]
  460. ]
  461. }
  462. ]
  463. }
  464. ]
  465. })
  466. assert json_response_and_validate_schema(conn, 200) == %{
  467. "configs" => [
  468. %{
  469. "group" => ":pleroma",
  470. "key" => ":key1",
  471. "value" => [
  472. %{"tuple" => [":key1", 1]},
  473. %{"tuple" => [":key3", 3]},
  474. %{
  475. "tuple" => [
  476. ":key2",
  477. [
  478. %{"tuple" => [":k1", 1]},
  479. %{"tuple" => [":k2", 1]},
  480. %{"tuple" => [":k3", 3]}
  481. ]
  482. ]
  483. }
  484. ],
  485. "db" => [":key1", ":key3", ":key2"]
  486. }
  487. ],
  488. "need_reboot" => false
  489. }
  490. end
  491. test "saving special atoms", %{conn: conn} do
  492. conn =
  493. conn
  494. |> put_req_header("content-type", "application/json")
  495. |> post("/api/pleroma/admin/config", %{
  496. "configs" => [
  497. %{
  498. "group" => ":pleroma",
  499. "key" => ":key1",
  500. "value" => [
  501. %{
  502. "tuple" => [
  503. ":ssl_options",
  504. [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
  505. ]
  506. }
  507. ]
  508. }
  509. ]
  510. })
  511. assert json_response_and_validate_schema(conn, 200) == %{
  512. "configs" => [
  513. %{
  514. "group" => ":pleroma",
  515. "key" => ":key1",
  516. "value" => [
  517. %{
  518. "tuple" => [
  519. ":ssl_options",
  520. [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
  521. ]
  522. }
  523. ],
  524. "db" => [":ssl_options"]
  525. }
  526. ],
  527. "need_reboot" => false
  528. }
  529. assert Application.get_env(:pleroma, :key1) == [
  530. ssl_options: [versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]]
  531. ]
  532. end
  533. test "saving full setting if value is in full_key_update list", %{conn: conn} do
  534. backends = Application.get_env(:logger, :backends)
  535. on_exit(fn -> Application.put_env(:logger, :backends, backends) end)
  536. insert(:config,
  537. group: :logger,
  538. key: :backends,
  539. value: []
  540. )
  541. Pleroma.Config.TransferTask.load_and_update_env([], false)
  542. assert Application.get_env(:logger, :backends) == []
  543. conn =
  544. conn
  545. |> put_req_header("content-type", "application/json")
  546. |> post("/api/pleroma/admin/config", %{
  547. configs: [
  548. %{
  549. group: ":logger",
  550. key: ":backends",
  551. value: [":console"]
  552. }
  553. ]
  554. })
  555. assert json_response_and_validate_schema(conn, 200) == %{
  556. "configs" => [
  557. %{
  558. "group" => ":logger",
  559. "key" => ":backends",
  560. "value" => [
  561. ":console"
  562. ],
  563. "db" => [":backends"]
  564. }
  565. ],
  566. "need_reboot" => false
  567. }
  568. assert Application.get_env(:logger, :backends) == [
  569. :console
  570. ]
  571. end
  572. test "saving full setting if value is not keyword", %{conn: conn} do
  573. insert(:config,
  574. group: :tesla,
  575. key: :adapter,
  576. value: Tesla.Adapter.Hackey
  577. )
  578. conn =
  579. conn
  580. |> put_req_header("content-type", "application/json")
  581. |> post("/api/pleroma/admin/config", %{
  582. configs: [
  583. %{group: ":tesla", key: ":adapter", value: "Tesla.Adapter.Httpc"}
  584. ]
  585. })
  586. assert json_response_and_validate_schema(conn, 200) == %{
  587. "configs" => [
  588. %{
  589. "group" => ":tesla",
  590. "key" => ":adapter",
  591. "value" => "Tesla.Adapter.Httpc",
  592. "db" => [":adapter"]
  593. }
  594. ],
  595. "need_reboot" => false
  596. }
  597. end
  598. test "update config setting & delete with fallback to default value", %{
  599. conn: conn,
  600. admin: admin,
  601. token: token
  602. } do
  603. ueberauth = Application.get_env(:ueberauth, Ueberauth)
  604. insert(:config, key: :keyaa1)
  605. insert(:config, key: :keyaa2)
  606. config3 =
  607. insert(:config,
  608. group: :ueberauth,
  609. key: Ueberauth
  610. )
  611. conn =
  612. conn
  613. |> put_req_header("content-type", "application/json")
  614. |> post("/api/pleroma/admin/config", %{
  615. configs: [
  616. %{group: ":pleroma", key: ":keyaa1", value: "another_value"},
  617. %{group: ":pleroma", key: ":keyaa2", value: "another_value"}
  618. ]
  619. })
  620. assert json_response_and_validate_schema(conn, 200) == %{
  621. "configs" => [
  622. %{
  623. "group" => ":pleroma",
  624. "key" => ":keyaa1",
  625. "value" => "another_value",
  626. "db" => [":keyaa1"]
  627. },
  628. %{
  629. "group" => ":pleroma",
  630. "key" => ":keyaa2",
  631. "value" => "another_value",
  632. "db" => [":keyaa2"]
  633. }
  634. ],
  635. "need_reboot" => false
  636. }
  637. assert Application.get_env(:pleroma, :keyaa1) == "another_value"
  638. assert Application.get_env(:pleroma, :keyaa2) == "another_value"
  639. assert Application.get_env(:ueberauth, Ueberauth) == config3.value
  640. conn =
  641. build_conn()
  642. |> assign(:user, admin)
  643. |> assign(:token, token)
  644. |> put_req_header("content-type", "application/json")
  645. |> post("/api/pleroma/admin/config", %{
  646. configs: [
  647. %{group: ":pleroma", key: ":keyaa2", delete: true},
  648. %{
  649. group: ":ueberauth",
  650. key: "Ueberauth",
  651. delete: true
  652. }
  653. ]
  654. })
  655. assert json_response_and_validate_schema(conn, 200) == %{
  656. "configs" => [],
  657. "need_reboot" => false
  658. }
  659. assert Application.get_env(:ueberauth, Ueberauth) == ueberauth
  660. refute Keyword.has_key?(Application.get_all_env(:pleroma), :keyaa2)
  661. end
  662. test "common config example", %{conn: conn} do
  663. conn =
  664. conn
  665. |> put_req_header("content-type", "application/json")
  666. |> post("/api/pleroma/admin/config", %{
  667. configs: [
  668. %{
  669. "group" => ":pleroma",
  670. "key" => "Pleroma.Captcha.NotReal",
  671. "value" => [
  672. %{"tuple" => [":enabled", false]},
  673. %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
  674. %{"tuple" => [":seconds_valid", 60]},
  675. %{"tuple" => [":path", ""]},
  676. %{"tuple" => [":key1", nil]},
  677. %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
  678. %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
  679. %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
  680. %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
  681. %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},
  682. %{"tuple" => [":name", "Pleroma"]}
  683. ]
  684. }
  685. ]
  686. })
  687. assert Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"
  688. assert json_response_and_validate_schema(conn, 200) == %{
  689. "configs" => [
  690. %{
  691. "group" => ":pleroma",
  692. "key" => "Pleroma.Captcha.NotReal",
  693. "value" => [
  694. %{"tuple" => [":enabled", false]},
  695. %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
  696. %{"tuple" => [":seconds_valid", 60]},
  697. %{"tuple" => [":path", ""]},
  698. %{"tuple" => [":key1", nil]},
  699. %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
  700. %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
  701. %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
  702. %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
  703. %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]},
  704. %{"tuple" => [":name", "Pleroma"]}
  705. ],
  706. "db" => [
  707. ":enabled",
  708. ":method",
  709. ":seconds_valid",
  710. ":path",
  711. ":key1",
  712. ":partial_chain",
  713. ":regex1",
  714. ":regex2",
  715. ":regex3",
  716. ":regex4",
  717. ":name"
  718. ]
  719. }
  720. ],
  721. "need_reboot" => false
  722. }
  723. end
  724. test "tuples with more than two values", %{conn: conn} do
  725. conn =
  726. conn
  727. |> put_req_header("content-type", "application/json")
  728. |> post("/api/pleroma/admin/config", %{
  729. configs: [
  730. %{
  731. "group" => ":pleroma",
  732. "key" => "Pleroma.Web.Endpoint.NotReal",
  733. "value" => [
  734. %{
  735. "tuple" => [
  736. ":http",
  737. [
  738. %{
  739. "tuple" => [
  740. ":key2",
  741. [
  742. %{
  743. "tuple" => [
  744. ":_",
  745. [
  746. %{
  747. "tuple" => [
  748. "/api/v1/streaming",
  749. "Pleroma.Web.MastodonAPI.WebsocketHandler",
  750. []
  751. ]
  752. },
  753. %{
  754. "tuple" => [
  755. "/websocket",
  756. "Phoenix.Endpoint.CowboyWebSocket",
  757. %{
  758. "tuple" => [
  759. "Phoenix.Transports.WebSocket",
  760. %{
  761. "tuple" => [
  762. "Pleroma.Web.Endpoint",
  763. "Pleroma.Web.UserSocket",
  764. []
  765. ]
  766. }
  767. ]
  768. }
  769. ]
  770. },
  771. %{
  772. "tuple" => [
  773. ":_",
  774. "Plug.Cowboy.Handler",
  775. %{"tuple" => ["Pleroma.Web.Endpoint", []]}
  776. ]
  777. }
  778. ]
  779. ]
  780. }
  781. ]
  782. ]
  783. }
  784. ]
  785. ]
  786. }
  787. ]
  788. }
  789. ]
  790. })
  791. assert json_response_and_validate_schema(conn, 200) == %{
  792. "configs" => [
  793. %{
  794. "group" => ":pleroma",
  795. "key" => "Pleroma.Web.Endpoint.NotReal",
  796. "value" => [
  797. %{
  798. "tuple" => [
  799. ":http",
  800. [
  801. %{
  802. "tuple" => [
  803. ":key2",
  804. [
  805. %{
  806. "tuple" => [
  807. ":_",
  808. [
  809. %{
  810. "tuple" => [
  811. "/api/v1/streaming",
  812. "Pleroma.Web.MastodonAPI.WebsocketHandler",
  813. []
  814. ]
  815. },
  816. %{
  817. "tuple" => [
  818. "/websocket",
  819. "Phoenix.Endpoint.CowboyWebSocket",
  820. %{
  821. "tuple" => [
  822. "Phoenix.Transports.WebSocket",
  823. %{
  824. "tuple" => [
  825. "Pleroma.Web.Endpoint",
  826. "Pleroma.Web.UserSocket",
  827. []
  828. ]
  829. }
  830. ]
  831. }
  832. ]
  833. },
  834. %{
  835. "tuple" => [
  836. ":_",
  837. "Plug.Cowboy.Handler",
  838. %{"tuple" => ["Pleroma.Web.Endpoint", []]}
  839. ]
  840. }
  841. ]
  842. ]
  843. }
  844. ]
  845. ]
  846. }
  847. ]
  848. ]
  849. }
  850. ],
  851. "db" => [":http"]
  852. }
  853. ],
  854. "need_reboot" => false
  855. }
  856. end
  857. test "settings with nesting map", %{conn: conn} do
  858. conn =
  859. conn
  860. |> put_req_header("content-type", "application/json")
  861. |> post("/api/pleroma/admin/config", %{
  862. configs: [
  863. %{
  864. "group" => ":pleroma",
  865. "key" => ":key1",
  866. "value" => [
  867. %{"tuple" => [":key2", "some_val"]},
  868. %{
  869. "tuple" => [
  870. ":key3",
  871. %{
  872. ":max_options" => 20,
  873. ":max_option_chars" => 200,
  874. ":min_expiration" => 0,
  875. ":max_expiration" => 31_536_000,
  876. "nested" => %{
  877. ":max_options" => 20,
  878. ":max_option_chars" => 200,
  879. ":min_expiration" => 0,
  880. ":max_expiration" => 31_536_000
  881. }
  882. }
  883. ]
  884. }
  885. ]
  886. }
  887. ]
  888. })
  889. assert json_response_and_validate_schema(conn, 200) ==
  890. %{
  891. "configs" => [
  892. %{
  893. "group" => ":pleroma",
  894. "key" => ":key1",
  895. "value" => [
  896. %{"tuple" => [":key2", "some_val"]},
  897. %{
  898. "tuple" => [
  899. ":key3",
  900. %{
  901. ":max_expiration" => 31_536_000,
  902. ":max_option_chars" => 200,
  903. ":max_options" => 20,
  904. ":min_expiration" => 0,
  905. "nested" => %{
  906. ":max_expiration" => 31_536_000,
  907. ":max_option_chars" => 200,
  908. ":max_options" => 20,
  909. ":min_expiration" => 0
  910. }
  911. }
  912. ]
  913. }
  914. ],
  915. "db" => [":key2", ":key3"]
  916. }
  917. ],
  918. "need_reboot" => false
  919. }
  920. end
  921. test "value as map", %{conn: conn} do
  922. conn =
  923. conn
  924. |> put_req_header("content-type", "application/json")
  925. |> post("/api/pleroma/admin/config", %{
  926. configs: [
  927. %{
  928. "group" => ":pleroma",
  929. "key" => ":key1",
  930. "value" => %{"key" => "some_val"}
  931. }
  932. ]
  933. })
  934. assert json_response_and_validate_schema(conn, 200) ==
  935. %{
  936. "configs" => [
  937. %{
  938. "group" => ":pleroma",
  939. "key" => ":key1",
  940. "value" => %{"key" => "some_val"},
  941. "db" => [":key1"]
  942. }
  943. ],
  944. "need_reboot" => false
  945. }
  946. end
  947. test "queues key as atom", %{conn: conn} do
  948. conn =
  949. conn
  950. |> put_req_header("content-type", "application/json")
  951. |> post("/api/pleroma/admin/config", %{
  952. configs: [
  953. %{
  954. "group" => ":oban",
  955. "key" => ":queues",
  956. "value" => [
  957. %{"tuple" => [":federator_incoming", 50]},
  958. %{"tuple" => [":federator_outgoing", 50]},
  959. %{"tuple" => [":web_push", 50]},
  960. %{"tuple" => [":mailer", 10]},
  961. %{"tuple" => [":transmogrifier", 20]},
  962. %{"tuple" => [":scheduled_activities", 10]},
  963. %{"tuple" => [":background", 5]}
  964. ]
  965. }
  966. ]
  967. })
  968. assert json_response_and_validate_schema(conn, 200) == %{
  969. "configs" => [
  970. %{
  971. "group" => ":oban",
  972. "key" => ":queues",
  973. "value" => [
  974. %{"tuple" => [":federator_incoming", 50]},
  975. %{"tuple" => [":federator_outgoing", 50]},
  976. %{"tuple" => [":web_push", 50]},
  977. %{"tuple" => [":mailer", 10]},
  978. %{"tuple" => [":transmogrifier", 20]},
  979. %{"tuple" => [":scheduled_activities", 10]},
  980. %{"tuple" => [":background", 5]}
  981. ],
  982. "db" => [
  983. ":federator_incoming",
  984. ":federator_outgoing",
  985. ":web_push",
  986. ":mailer",
  987. ":transmogrifier",
  988. ":scheduled_activities",
  989. ":background"
  990. ]
  991. }
  992. ],
  993. "need_reboot" => false
  994. }
  995. end
  996. test "delete part of settings by atom subkeys", %{conn: conn} do
  997. insert(:config,
  998. key: :keyaa1,
  999. value: [subkey1: "val1", subkey2: "val2", subkey3: "val3"]
  1000. )
  1001. conn =
  1002. conn
  1003. |> put_req_header("content-type", "application/json")
  1004. |> post("/api/pleroma/admin/config", %{
  1005. configs: [
  1006. %{
  1007. group: ":pleroma",
  1008. key: ":keyaa1",
  1009. subkeys: [":subkey1", ":subkey3"],
  1010. delete: true
  1011. }
  1012. ]
  1013. })
  1014. assert json_response_and_validate_schema(conn, 200) == %{
  1015. "configs" => [
  1016. %{
  1017. "group" => ":pleroma",
  1018. "key" => ":keyaa1",
  1019. "value" => [%{"tuple" => [":subkey2", "val2"]}],
  1020. "db" => [":subkey2"]
  1021. }
  1022. ],
  1023. "need_reboot" => false
  1024. }
  1025. end
  1026. test "proxy tuple localhost", %{conn: conn} do
  1027. conn =
  1028. conn
  1029. |> put_req_header("content-type", "application/json")
  1030. |> post("/api/pleroma/admin/config", %{
  1031. configs: [
  1032. %{
  1033. group: ":pleroma",
  1034. key: ":http",
  1035. value: [
  1036. %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]}
  1037. ]
  1038. }
  1039. ]
  1040. })
  1041. assert %{
  1042. "configs" => [
  1043. %{
  1044. "group" => ":pleroma",
  1045. "key" => ":http",
  1046. "value" => value,
  1047. "db" => db
  1048. }
  1049. ]
  1050. } = json_response_and_validate_schema(conn, 200)
  1051. assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]} in value
  1052. assert ":proxy_url" in db
  1053. end
  1054. test "proxy tuple domain", %{conn: conn} do
  1055. conn =
  1056. conn
  1057. |> put_req_header("content-type", "application/json")
  1058. |> post("/api/pleroma/admin/config", %{
  1059. configs: [
  1060. %{
  1061. group: ":pleroma",
  1062. key: ":http",
  1063. value: [
  1064. %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]}
  1065. ]
  1066. }
  1067. ]
  1068. })
  1069. assert %{
  1070. "configs" => [
  1071. %{
  1072. "group" => ":pleroma",
  1073. "key" => ":http",
  1074. "value" => value,
  1075. "db" => db
  1076. }
  1077. ]
  1078. } = json_response_and_validate_schema(conn, 200)
  1079. assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]} in value
  1080. assert ":proxy_url" in db
  1081. end
  1082. test "proxy tuple ip", %{conn: conn} do
  1083. conn =
  1084. conn
  1085. |> put_req_header("content-type", "application/json")
  1086. |> post("/api/pleroma/admin/config", %{
  1087. configs: [
  1088. %{
  1089. group: ":pleroma",
  1090. key: ":http",
  1091. value: [
  1092. %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]}
  1093. ]
  1094. }
  1095. ]
  1096. })
  1097. assert %{
  1098. "configs" => [
  1099. %{
  1100. "group" => ":pleroma",
  1101. "key" => ":http",
  1102. "value" => value,
  1103. "db" => db
  1104. }
  1105. ]
  1106. } = json_response_and_validate_schema(conn, 200)
  1107. assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]} in value
  1108. assert ":proxy_url" in db
  1109. end
  1110. @tag capture_log: true
  1111. test "doesn't set keys not in the whitelist", %{conn: conn} do
  1112. clear_config(:database_config_whitelist, [
  1113. {:pleroma, :key1},
  1114. {:pleroma, :key2},
  1115. {:pleroma, Pleroma.Captcha.NotReal},
  1116. {:not_real}
  1117. ])
  1118. conn
  1119. |> put_req_header("content-type", "application/json")
  1120. |> post("/api/pleroma/admin/config", %{
  1121. configs: [
  1122. %{group: ":pleroma", key: ":key1", value: "value1"},
  1123. %{group: ":pleroma", key: ":key2", value: "value2"},
  1124. %{group: ":pleroma", key: ":key3", value: "value3"},
  1125. %{group: ":pleroma", key: "Pleroma.Web.Endpoint.NotReal", value: "value4"},
  1126. %{group: ":pleroma", key: "Pleroma.Captcha.NotReal", value: "value5"},
  1127. %{group: ":not_real", key: ":anything", value: "value6"}
  1128. ]
  1129. })
  1130. assert Application.get_env(:pleroma, :key1) == "value1"
  1131. assert Application.get_env(:pleroma, :key2) == "value2"
  1132. assert Application.get_env(:pleroma, :key3) == nil
  1133. assert Application.get_env(:pleroma, Pleroma.Web.Endpoint.NotReal) == nil
  1134. assert Application.get_env(:pleroma, Pleroma.Captcha.NotReal) == "value5"
  1135. assert Application.get_env(:not_real, :anything) == "value6"
  1136. end
  1137. test "args for Pleroma.Upload.Filter.Mogrify with custom tuples", %{conn: conn} do
  1138. clear_config(Pleroma.Upload.Filter.Mogrify)
  1139. assert conn
  1140. |> put_req_header("content-type", "application/json")
  1141. |> post("/api/pleroma/admin/config", %{
  1142. configs: [
  1143. %{
  1144. group: ":pleroma",
  1145. key: "Pleroma.Upload.Filter.Mogrify",
  1146. value: [
  1147. %{"tuple" => [":args", ["auto-orient", "strip"]]}
  1148. ]
  1149. }
  1150. ]
  1151. })
  1152. |> json_response_and_validate_schema(200) == %{
  1153. "configs" => [
  1154. %{
  1155. "group" => ":pleroma",
  1156. "key" => "Pleroma.Upload.Filter.Mogrify",
  1157. "value" => [
  1158. %{"tuple" => [":args", ["auto-orient", "strip"]]}
  1159. ],
  1160. "db" => [":args"]
  1161. }
  1162. ],
  1163. "need_reboot" => false
  1164. }
  1165. assert Config.get(Pleroma.Upload.Filter.Mogrify) == [args: ["auto-orient", "strip"]]
  1166. assert conn
  1167. |> put_req_header("content-type", "application/json")
  1168. |> post("/api/pleroma/admin/config", %{
  1169. configs: [
  1170. %{
  1171. group: ":pleroma",
  1172. key: "Pleroma.Upload.Filter.Mogrify",
  1173. value: [
  1174. %{
  1175. "tuple" => [
  1176. ":args",
  1177. [
  1178. "auto-orient",
  1179. "strip",
  1180. "{\"implode\", \"1\"}",
  1181. "{\"resize\", \"3840x1080>\"}"
  1182. ]
  1183. ]
  1184. }
  1185. ]
  1186. }
  1187. ]
  1188. })
  1189. |> json_response(200) == %{
  1190. "configs" => [
  1191. %{
  1192. "group" => ":pleroma",
  1193. "key" => "Pleroma.Upload.Filter.Mogrify",
  1194. "value" => [
  1195. %{
  1196. "tuple" => [
  1197. ":args",
  1198. [
  1199. "auto-orient",
  1200. "strip",
  1201. "{\"implode\", \"1\"}",
  1202. "{\"resize\", \"3840x1080>\"}"
  1203. ]
  1204. ]
  1205. }
  1206. ],
  1207. "db" => [":args"]
  1208. }
  1209. ],
  1210. "need_reboot" => false
  1211. }
  1212. assert Config.get(Pleroma.Upload.Filter.Mogrify) == [
  1213. args: ["auto-orient", "strip", {"implode", "1"}, {"resize", "3840x1080>"}]
  1214. ]
  1215. end
  1216. test "enables the welcome messages", %{conn: conn} do
  1217. clear_config([:welcome])
  1218. params = %{
  1219. "group" => ":pleroma",
  1220. "key" => ":welcome",
  1221. "value" => [
  1222. %{
  1223. "tuple" => [
  1224. ":direct_message",
  1225. [
  1226. %{"tuple" => [":enabled", true]},
  1227. %{"tuple" => [":message", "Welcome to Pleroma!"]},
  1228. %{"tuple" => [":sender_nickname", "pleroma"]}
  1229. ]
  1230. ]
  1231. },
  1232. %{
  1233. "tuple" => [
  1234. ":chat_message",
  1235. [
  1236. %{"tuple" => [":enabled", true]},
  1237. %{"tuple" => [":message", "Welcome to Pleroma!"]},
  1238. %{"tuple" => [":sender_nickname", "pleroma"]}
  1239. ]
  1240. ]
  1241. },
  1242. %{
  1243. "tuple" => [
  1244. ":email",
  1245. [
  1246. %{"tuple" => [":enabled", true]},
  1247. %{"tuple" => [":sender", %{"tuple" => ["pleroma@dev.dev", "Pleroma"]}]},
  1248. %{"tuple" => [":subject", "Welcome to <%= instance_name %>!"]},
  1249. %{"tuple" => [":html", "Welcome to <%= instance_name %>!"]},
  1250. %{"tuple" => [":text", "Welcome to <%= instance_name %>!"]}
  1251. ]
  1252. ]
  1253. }
  1254. ]
  1255. }
  1256. refute Pleroma.User.WelcomeEmail.enabled?()
  1257. refute Pleroma.User.WelcomeMessage.enabled?()
  1258. refute Pleroma.User.WelcomeChatMessage.enabled?()
  1259. res =
  1260. assert conn
  1261. |> put_req_header("content-type", "application/json")
  1262. |> post("/api/pleroma/admin/config", %{"configs" => [params]})
  1263. |> json_response_and_validate_schema(200)
  1264. assert Pleroma.User.WelcomeEmail.enabled?()
  1265. assert Pleroma.User.WelcomeMessage.enabled?()
  1266. assert Pleroma.User.WelcomeChatMessage.enabled?()
  1267. assert res == %{
  1268. "configs" => [
  1269. %{
  1270. "db" => [":direct_message", ":chat_message", ":email"],
  1271. "group" => ":pleroma",
  1272. "key" => ":welcome",
  1273. "value" => params["value"]
  1274. }
  1275. ],
  1276. "need_reboot" => false
  1277. }
  1278. end
  1279. test "custom instance thumbnail", %{conn: conn} do
  1280. clear_config([:instance])
  1281. params = %{
  1282. "group" => ":pleroma",
  1283. "key" => ":instance",
  1284. "value" => [
  1285. %{
  1286. "tuple" => [
  1287. ":instance_thumbnail",
  1288. "https://example.com/media/new_thumbnail.jpg"
  1289. ]
  1290. }
  1291. ]
  1292. }
  1293. assert conn
  1294. |> put_req_header("content-type", "application/json")
  1295. |> post("/api/pleroma/admin/config", %{"configs" => [params]})
  1296. |> json_response_and_validate_schema(200) ==
  1297. %{
  1298. "configs" => [
  1299. %{
  1300. "db" => [":instance_thumbnail"],
  1301. "group" => ":pleroma",
  1302. "key" => ":instance",
  1303. "value" => params["value"]
  1304. }
  1305. ],
  1306. "need_reboot" => false
  1307. }
  1308. assert conn
  1309. |> get("/api/v1/instance")
  1310. |> json_response_and_validate_schema(200)
  1311. |> Map.take(["thumbnail"]) ==
  1312. %{"thumbnail" => "https://example.com/media/new_thumbnail.jpg"}
  1313. end
  1314. test "Concurrent Limiter", %{conn: conn} do
  1315. clear_config([ConcurrentLimiter])
  1316. params = %{
  1317. "group" => ":pleroma",
  1318. "key" => "ConcurrentLimiter",
  1319. "value" => [
  1320. %{
  1321. "tuple" => [
  1322. "Pleroma.Web.RichMedia.Helpers",
  1323. [
  1324. %{"tuple" => [":max_running", 6]},
  1325. %{"tuple" => [":max_waiting", 6]}
  1326. ]
  1327. ]
  1328. },
  1329. %{
  1330. "tuple" => [
  1331. "Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy",
  1332. [
  1333. %{"tuple" => [":max_running", 7]},
  1334. %{"tuple" => [":max_waiting", 7]}
  1335. ]
  1336. ]
  1337. }
  1338. ]
  1339. }
  1340. assert conn
  1341. |> put_req_header("content-type", "application/json")
  1342. |> post("/api/pleroma/admin/config", %{"configs" => [params]})
  1343. |> json_response_and_validate_schema(200)
  1344. end
  1345. end
  1346. describe "GET /api/pleroma/admin/config/descriptions" do
  1347. test "structure", %{conn: conn} do
  1348. conn = get(conn, "/api/pleroma/admin/config/descriptions")
  1349. assert [child | _others] = json_response_and_validate_schema(conn, 200)
  1350. assert child["children"]
  1351. assert child["key"]
  1352. assert String.starts_with?(child["group"], ":")
  1353. assert child["description"]
  1354. end
  1355. test "filters by database configuration whitelist", %{conn: conn} do
  1356. clear_config(:database_config_whitelist, [
  1357. {:pleroma, :instance},
  1358. {:pleroma, :activitypub},
  1359. {:pleroma, Pleroma.Upload}
  1360. ])
  1361. conn = get(conn, "/api/pleroma/admin/config/descriptions")
  1362. children = json_response_and_validate_schema(conn, 200)
  1363. assert length(children) == 3
  1364. assert Enum.count(children, fn c -> c["group"] == ":pleroma" end) == 3
  1365. instance = Enum.find(children, fn c -> c["key"] == ":instance" end)
  1366. assert instance["children"]
  1367. activitypub = Enum.find(children, fn c -> c["key"] == ":activitypub" end)
  1368. assert activitypub["children"]
  1369. web_endpoint = Enum.find(children, fn c -> c["key"] == "Pleroma.Upload" end)
  1370. assert web_endpoint["children"]
  1371. end
  1372. end
  1373. end