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