saving to DB only added by user settings
[akkoma] / test / config / config_db_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.ConfigDBTest do
6 use Pleroma.DataCase, async: true
7 import Pleroma.Factory
8 alias Pleroma.ConfigDB
9
10 test "get_by_key/1" do
11 config = insert(:config)
12 insert(:config)
13
14 assert config == ConfigDB.get_by_params(%{group: config.group, key: config.key})
15 end
16
17 test "create/1" do
18 {:ok, config} = ConfigDB.create(%{group: ":pleroma", key: ":some_key", value: "some_value"})
19 assert config == ConfigDB.get_by_params(%{group: ":pleroma", key: ":some_key"})
20 end
21
22 test "update/1" do
23 config = insert(:config)
24 {:ok, updated} = ConfigDB.update(config, %{value: "some_value"})
25 loaded = ConfigDB.get_by_params(%{group: config.group, key: config.key})
26 assert loaded == updated
27 end
28
29 test "get_all_as_keyword/0" do
30 insert(:config)
31 insert(:config, group: ":quack", key: ":level", value: ConfigDB.to_binary(:info))
32 insert(:config, group: ":quack", key: ":meta", value: ConfigDB.to_binary([:none]))
33
34 insert(:config,
35 group: ":quack",
36 key: ":webhook_url",
37 value: ConfigDB.to_binary("https://hooks.slack.com/services/KEY/some_val")
38 )
39
40 assert [
41 pleroma: [{_, %{another: _, another_key: _}}],
42 quack: [
43 level: :info,
44 meta: [:none],
45 webhook_url: "https://hooks.slack.com/services/KEY/some_val"
46 ]
47 ] = ConfigDB.get_all_as_keyword()
48 end
49
50 describe "update_or_create/1" do
51 test "common" do
52 config = insert(:config)
53 key2 = "another_key"
54
55 params = [
56 %{group: "pleroma", key: key2, value: "another_value"},
57 %{group: config.group, key: config.key, value: "new_value"}
58 ]
59
60 assert Repo.all(ConfigDB) |> length() == 1
61
62 Enum.each(params, &ConfigDB.update_or_create(&1))
63
64 assert Repo.all(ConfigDB) |> length() == 2
65
66 config1 = ConfigDB.get_by_params(%{group: config.group, key: config.key})
67 config2 = ConfigDB.get_by_params(%{group: "pleroma", key: key2})
68
69 assert config1.value == ConfigDB.transform("new_value")
70 assert config2.value == ConfigDB.transform("another_value")
71 end
72
73 test "partial update" do
74 config = insert(:config, value: ConfigDB.to_binary(key1: "val1", key2: :val2))
75
76 {:ok, _config} =
77 ConfigDB.update_or_create(%{
78 group: config.group,
79 key: config.key,
80 value: [key1: :val1, key3: :val3]
81 })
82
83 updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
84
85 value = ConfigDB.from_binary(updated.value)
86 assert length(value) == 3
87 assert value[:key1] == :val1
88 assert value[:key2] == :val2
89 assert value[:key3] == :val3
90 end
91
92 test "deep merge" do
93 config = insert(:config, value: ConfigDB.to_binary(key1: "val1", key2: [k1: :v1, k2: "v2"]))
94
95 {:ok, config} =
96 ConfigDB.update_or_create(%{
97 group: config.group,
98 key: config.key,
99 value: [key1: :val1, key2: [k2: :v2, k3: :v3], key3: :val3]
100 })
101
102 updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
103
104 assert config.value == updated.value
105
106 value = ConfigDB.from_binary(updated.value)
107 assert value[:key1] == :val1
108 assert value[:key2] == [k1: :v1, k2: :v2, k3: :v3]
109 assert value[:key3] == :val3
110 end
111
112 test "only full update for some keys" do
113 config1 = insert(:config, key: ":ecto_repos", value: ConfigDB.to_binary(repo: Pleroma.Repo))
114
115 config2 =
116 insert(:config, group: ":cors_plug", key: ":max_age", value: ConfigDB.to_binary(18))
117
118 {:ok, _config} =
119 ConfigDB.update_or_create(%{
120 group: config1.group,
121 key: config1.key,
122 value: [another_repo: [Pleroma.Repo]]
123 })
124
125 {:ok, _config} =
126 ConfigDB.update_or_create(%{
127 group: config2.group,
128 key: config2.key,
129 value: 777
130 })
131
132 updated1 = ConfigDB.get_by_params(%{group: config1.group, key: config1.key})
133 updated2 = ConfigDB.get_by_params(%{group: config2.group, key: config2.key})
134
135 assert ConfigDB.from_binary(updated1.value) == [another_repo: [Pleroma.Repo]]
136 assert ConfigDB.from_binary(updated2.value) == 777
137 end
138
139 test "full update if value is not keyword" do
140 config =
141 insert(:config,
142 group: ":tesla",
143 key: ":adapter",
144 value: ConfigDB.to_binary(Tesla.Adapter.Hackney)
145 )
146
147 {:ok, _config} =
148 ConfigDB.update_or_create(%{
149 group: config.group,
150 key: config.key,
151 value: Tesla.Adapter.Httpc
152 })
153
154 updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
155
156 assert ConfigDB.from_binary(updated.value) == Tesla.Adapter.Httpc
157 end
158 end
159
160 test "delete/1" do
161 config = insert(:config)
162 {:ok, _} = ConfigDB.delete(%{key: config.key, group: config.group})
163 refute ConfigDB.get_by_params(%{key: config.key, group: config.group})
164 end
165
166 describe "transform/1" do
167 test "string" do
168 binary = ConfigDB.transform("value as string")
169 assert binary == :erlang.term_to_binary("value as string")
170 assert ConfigDB.from_binary(binary) == "value as string"
171 end
172
173 test "boolean" do
174 binary = ConfigDB.transform(false)
175 assert binary == :erlang.term_to_binary(false)
176 assert ConfigDB.from_binary(binary) == false
177 end
178
179 test "nil" do
180 binary = ConfigDB.transform(nil)
181 assert binary == :erlang.term_to_binary(nil)
182 assert ConfigDB.from_binary(binary) == nil
183 end
184
185 test "integer" do
186 binary = ConfigDB.transform(150)
187 assert binary == :erlang.term_to_binary(150)
188 assert ConfigDB.from_binary(binary) == 150
189 end
190
191 test "atom" do
192 binary = ConfigDB.transform(":atom")
193 assert binary == :erlang.term_to_binary(:atom)
194 assert ConfigDB.from_binary(binary) == :atom
195 end
196
197 test "ssl options" do
198 binary = ConfigDB.transform([":tlsv1", ":tlsv1.1", ":tlsv1.2"])
199 assert binary == :erlang.term_to_binary([:tlsv1, :"tlsv1.1", :"tlsv1.2"])
200 assert ConfigDB.from_binary(binary) == [:tlsv1, :"tlsv1.1", :"tlsv1.2"]
201 end
202
203 test "pleroma module" do
204 binary = ConfigDB.transform("Pleroma.Bookmark")
205 assert binary == :erlang.term_to_binary(Pleroma.Bookmark)
206 assert ConfigDB.from_binary(binary) == Pleroma.Bookmark
207 end
208
209 test "pleroma string" do
210 binary = ConfigDB.transform("Pleroma")
211 assert binary == :erlang.term_to_binary("Pleroma")
212 assert ConfigDB.from_binary(binary) == "Pleroma"
213 end
214
215 test "phoenix module" do
216 binary = ConfigDB.transform("Phoenix.Socket.V1.JSONSerializer")
217 assert binary == :erlang.term_to_binary(Phoenix.Socket.V1.JSONSerializer)
218 assert ConfigDB.from_binary(binary) == Phoenix.Socket.V1.JSONSerializer
219 end
220
221 test "tesla module" do
222 binary = ConfigDB.transform("Tesla.Adapter.Hackney")
223 assert binary == :erlang.term_to_binary(Tesla.Adapter.Hackney)
224 assert ConfigDB.from_binary(binary) == Tesla.Adapter.Hackney
225 end
226
227 test "ExSyslogger module" do
228 binary = ConfigDB.transform("ExSyslogger")
229 assert binary == :erlang.term_to_binary(ExSyslogger)
230 assert ConfigDB.from_binary(binary) == ExSyslogger
231 end
232
233 test "Quack.Logger module" do
234 binary = ConfigDB.transform("Quack.Logger")
235 assert binary == :erlang.term_to_binary(Quack.Logger)
236 assert ConfigDB.from_binary(binary) == Quack.Logger
237 end
238
239 test "sigil" do
240 binary = ConfigDB.transform("~r[comp[lL][aA][iI][nN]er]")
241 assert binary == :erlang.term_to_binary(~r/comp[lL][aA][iI][nN]er/)
242 assert ConfigDB.from_binary(binary) == ~r/comp[lL][aA][iI][nN]er/
243 end
244
245 test "link sigil" do
246 binary = ConfigDB.transform("~r/https:\/\/example.com/")
247 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/)
248 assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/
249 end
250
251 test "link sigil with um modifiers" do
252 binary = ConfigDB.transform("~r/https:\/\/example.com/um")
253 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/um)
254 assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/um
255 end
256
257 test "link sigil with i modifier" do
258 binary = ConfigDB.transform("~r/https:\/\/example.com/i")
259 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/i)
260 assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/i
261 end
262
263 test "link sigil with s modifier" do
264 binary = ConfigDB.transform("~r/https:\/\/example.com/s")
265 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/s)
266 assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/s
267 end
268
269 test "raise if valid delimiter not found" do
270 assert_raise ArgumentError, "valid delimiter for Regex expression not found", fn ->
271 ConfigDB.transform("~r/https://[]{}<>\"'()|example.com/s")
272 end
273 end
274
275 test "2 child tuple" do
276 binary = ConfigDB.transform(%{"tuple" => ["v1", ":v2"]})
277 assert binary == :erlang.term_to_binary({"v1", :v2})
278 assert ConfigDB.from_binary(binary) == {"v1", :v2}
279 end
280
281 test "proxy tuple with localhost" do
282 binary =
283 ConfigDB.transform(%{
284 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]
285 })
286
287 assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, :localhost, 1234}})
288 assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, :localhost, 1234}}
289 end
290
291 test "proxy tuple with domain" do
292 binary =
293 ConfigDB.transform(%{
294 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]
295 })
296
297 assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, 'domain.com', 1234}})
298 assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, 'domain.com', 1234}}
299 end
300
301 test "proxy tuple with ip" do
302 binary =
303 ConfigDB.transform(%{
304 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]
305 })
306
307 assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}})
308 assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}}
309 end
310
311 test "tuple with n childs" do
312 binary =
313 ConfigDB.transform(%{
314 "tuple" => [
315 "v1",
316 ":v2",
317 "Pleroma.Bookmark",
318 150,
319 false,
320 "Phoenix.Socket.V1.JSONSerializer"
321 ]
322 })
323
324 assert binary ==
325 :erlang.term_to_binary(
326 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
327 )
328
329 assert ConfigDB.from_binary(binary) ==
330 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
331 end
332
333 test "tuple with dispatch key" do
334 binary = ConfigDB.transform(%{"tuple" => [":dispatch", ["{:_,
335 [
336 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
337 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
338 {Phoenix.Transports.WebSocket,
339 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
340 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
341 ]}"]]})
342
343 assert binary ==
344 :erlang.term_to_binary(
345 {:dispatch,
346 [
347 {:_,
348 [
349 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
350 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
351 {Phoenix.Transports.WebSocket,
352 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: "/websocket"]}}},
353 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
354 ]}
355 ]}
356 )
357
358 assert ConfigDB.from_binary(binary) ==
359 {:dispatch,
360 [
361 {:_,
362 [
363 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
364 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
365 {Phoenix.Transports.WebSocket,
366 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: "/websocket"]}}},
367 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
368 ]}
369 ]}
370 end
371
372 test "map with string key" do
373 binary = ConfigDB.transform(%{"key" => "value"})
374 assert binary == :erlang.term_to_binary(%{"key" => "value"})
375 assert ConfigDB.from_binary(binary) == %{"key" => "value"}
376 end
377
378 test "map with atom key" do
379 binary = ConfigDB.transform(%{":key" => "value"})
380 assert binary == :erlang.term_to_binary(%{key: "value"})
381 assert ConfigDB.from_binary(binary) == %{key: "value"}
382 end
383
384 test "list of strings" do
385 binary = ConfigDB.transform(["v1", "v2", "v3"])
386 assert binary == :erlang.term_to_binary(["v1", "v2", "v3"])
387 assert ConfigDB.from_binary(binary) == ["v1", "v2", "v3"]
388 end
389
390 test "list of modules" do
391 binary = ConfigDB.transform(["Pleroma.Repo", "Pleroma.Activity"])
392 assert binary == :erlang.term_to_binary([Pleroma.Repo, Pleroma.Activity])
393 assert ConfigDB.from_binary(binary) == [Pleroma.Repo, Pleroma.Activity]
394 end
395
396 test "list of atoms" do
397 binary = ConfigDB.transform([":v1", ":v2", ":v3"])
398 assert binary == :erlang.term_to_binary([:v1, :v2, :v3])
399 assert ConfigDB.from_binary(binary) == [:v1, :v2, :v3]
400 end
401
402 test "list of mixed values" do
403 binary =
404 ConfigDB.transform([
405 "v1",
406 ":v2",
407 "Pleroma.Repo",
408 "Phoenix.Socket.V1.JSONSerializer",
409 15,
410 false
411 ])
412
413 assert binary ==
414 :erlang.term_to_binary([
415 "v1",
416 :v2,
417 Pleroma.Repo,
418 Phoenix.Socket.V1.JSONSerializer,
419 15,
420 false
421 ])
422
423 assert ConfigDB.from_binary(binary) == [
424 "v1",
425 :v2,
426 Pleroma.Repo,
427 Phoenix.Socket.V1.JSONSerializer,
428 15,
429 false
430 ]
431 end
432
433 test "simple keyword" do
434 binary = ConfigDB.transform([%{"tuple" => [":key", "value"]}])
435 assert binary == :erlang.term_to_binary([{:key, "value"}])
436 assert ConfigDB.from_binary(binary) == [{:key, "value"}]
437 assert ConfigDB.from_binary(binary) == [key: "value"]
438 end
439
440 test "keyword with partial_chain key" do
441 binary =
442 ConfigDB.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}])
443
444 assert binary == :erlang.term_to_binary(partial_chain: &:hackney_connect.partial_chain/1)
445 assert ConfigDB.from_binary(binary) == [partial_chain: &:hackney_connect.partial_chain/1]
446 end
447
448 test "keyword" do
449 binary =
450 ConfigDB.transform([
451 %{"tuple" => [":types", "Pleroma.PostgresTypes"]},
452 %{"tuple" => [":telemetry_event", ["Pleroma.Repo.Instrumenter"]]},
453 %{"tuple" => [":migration_lock", nil]},
454 %{"tuple" => [":key1", 150]},
455 %{"tuple" => [":key2", "string"]}
456 ])
457
458 assert binary ==
459 :erlang.term_to_binary(
460 types: Pleroma.PostgresTypes,
461 telemetry_event: [Pleroma.Repo.Instrumenter],
462 migration_lock: nil,
463 key1: 150,
464 key2: "string"
465 )
466
467 assert ConfigDB.from_binary(binary) == [
468 types: Pleroma.PostgresTypes,
469 telemetry_event: [Pleroma.Repo.Instrumenter],
470 migration_lock: nil,
471 key1: 150,
472 key2: "string"
473 ]
474 end
475
476 test "complex keyword with nested mixed childs" do
477 binary =
478 ConfigDB.transform([
479 %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]},
480 %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]},
481 %{"tuple" => [":link_name", true]},
482 %{"tuple" => [":proxy_remote", false]},
483 %{"tuple" => [":common_map", %{":key" => "value"}]},
484 %{
485 "tuple" => [
486 ":proxy_opts",
487 [
488 %{"tuple" => [":redirect_on_failure", false]},
489 %{"tuple" => [":max_body_length", 1_048_576]},
490 %{
491 "tuple" => [
492 ":http",
493 [%{"tuple" => [":follow_redirect", true]}, %{"tuple" => [":pool", ":upload"]}]
494 ]
495 }
496 ]
497 ]
498 }
499 ])
500
501 assert binary ==
502 :erlang.term_to_binary(
503 uploader: Pleroma.Uploaders.Local,
504 filters: [Pleroma.Upload.Filter.Dedupe],
505 link_name: true,
506 proxy_remote: false,
507 common_map: %{key: "value"},
508 proxy_opts: [
509 redirect_on_failure: false,
510 max_body_length: 1_048_576,
511 http: [
512 follow_redirect: true,
513 pool: :upload
514 ]
515 ]
516 )
517
518 assert ConfigDB.from_binary(binary) ==
519 [
520 uploader: Pleroma.Uploaders.Local,
521 filters: [Pleroma.Upload.Filter.Dedupe],
522 link_name: true,
523 proxy_remote: false,
524 common_map: %{key: "value"},
525 proxy_opts: [
526 redirect_on_failure: false,
527 max_body_length: 1_048_576,
528 http: [
529 follow_redirect: true,
530 pool: :upload
531 ]
532 ]
533 ]
534 end
535
536 test "common keyword" do
537 binary =
538 ConfigDB.transform([
539 %{"tuple" => [":level", ":warn"]},
540 %{"tuple" => [":meta", [":all"]]},
541 %{"tuple" => [":path", ""]},
542 %{"tuple" => [":val", nil]},
543 %{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]}
544 ])
545
546 assert binary ==
547 :erlang.term_to_binary(
548 level: :warn,
549 meta: [:all],
550 path: "",
551 val: nil,
552 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
553 )
554
555 assert ConfigDB.from_binary(binary) == [
556 level: :warn,
557 meta: [:all],
558 path: "",
559 val: nil,
560 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
561 ]
562 end
563
564 test "complex keyword with sigil" do
565 binary =
566 ConfigDB.transform([
567 %{"tuple" => [":federated_timeline_removal", []]},
568 %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]},
569 %{"tuple" => [":replace", []]}
570 ])
571
572 assert binary ==
573 :erlang.term_to_binary(
574 federated_timeline_removal: [],
575 reject: [~r/comp[lL][aA][iI][nN]er/],
576 replace: []
577 )
578
579 assert ConfigDB.from_binary(binary) ==
580 [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []]
581 end
582
583 test "complex keyword with tuples with more than 2 values" do
584 binary =
585 ConfigDB.transform([
586 %{
587 "tuple" => [
588 ":http",
589 [
590 %{
591 "tuple" => [
592 ":key1",
593 [
594 %{
595 "tuple" => [
596 ":_",
597 [
598 %{
599 "tuple" => [
600 "/api/v1/streaming",
601 "Pleroma.Web.MastodonAPI.WebsocketHandler",
602 []
603 ]
604 },
605 %{
606 "tuple" => [
607 "/websocket",
608 "Phoenix.Endpoint.CowboyWebSocket",
609 %{
610 "tuple" => [
611 "Phoenix.Transports.WebSocket",
612 %{
613 "tuple" => [
614 "Pleroma.Web.Endpoint",
615 "Pleroma.Web.UserSocket",
616 []
617 ]
618 }
619 ]
620 }
621 ]
622 },
623 %{
624 "tuple" => [
625 ":_",
626 "Phoenix.Endpoint.Cowboy2Handler",
627 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
628 ]
629 }
630 ]
631 ]
632 }
633 ]
634 ]
635 }
636 ]
637 ]
638 }
639 ])
640
641 assert binary ==
642 :erlang.term_to_binary(
643 http: [
644 key1: [
645 _: [
646 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
647 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
648 {Phoenix.Transports.WebSocket,
649 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
650 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
651 ]
652 ]
653 ]
654 )
655
656 assert ConfigDB.from_binary(binary) == [
657 http: [
658 key1: [
659 {:_,
660 [
661 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
662 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
663 {Phoenix.Transports.WebSocket,
664 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
665 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
666 ]}
667 ]
668 ]
669 ]
670 end
671 end
672 end