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