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