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