1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.ConfigDBTest do
6 use Pleroma.DataCase, async: true
10 test "get_by_key/1" do
11 config = insert(:config)
14 assert config == ConfigDB.get_by_params(%{group: config.group, key: config.key})
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"})
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
29 test "get_all_as_keyword/0" do
31 insert(:config, group: ":quack", key: ":level", value: ConfigDB.to_binary(:info))
32 insert(:config, group: ":quack", key: ":meta", value: ConfigDB.to_binary([:none]))
37 value: ConfigDB.to_binary("https://hooks.slack.com/services/KEY/some_val")
41 pleroma: [{_, %{another: _, another_key: _}}],
45 webhook_url: "https://hooks.slack.com/services/KEY/some_val"
47 ] = ConfigDB.get_all_as_keyword()
50 describe "update_or_create/1" do
52 config = insert(:config)
56 %{group: "pleroma", key: key2, value: "another_value"},
57 %{group: config.group, key: config.key, value: "new_value"}
60 assert Repo.all(ConfigDB) |> length() == 1
62 Enum.each(params, &ConfigDB.update_or_create(&1))
64 assert Repo.all(ConfigDB) |> length() == 2
66 config1 = ConfigDB.get_by_params(%{group: config.group, key: config.key})
67 config2 = ConfigDB.get_by_params(%{group: "pleroma", key: key2})
69 assert config1.value == ConfigDB.transform("new_value")
70 assert config2.value == ConfigDB.transform("another_value")
73 test "partial update" do
74 config = insert(:config, value: ConfigDB.to_binary(key1: "val1", key2: :val2))
77 ConfigDB.update_or_create(%{
80 value: [key1: :val1, key3: :val3]
83 updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
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
93 config = insert(:config, value: ConfigDB.to_binary(key1: "val1", key2: [k1: :v1, k2: "v2"]))
96 ConfigDB.update_or_create(%{
99 value: [key1: :val1, key2: [k2: :v2, k3: :v3], key3: :val3]
102 updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
104 assert config.value == updated.value
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
112 test "only full update for some keys" do
113 config1 = insert(:config, key: ":ecto_repos", value: ConfigDB.to_binary(repo: Pleroma.Repo))
116 insert(:config, group: ":cors_plug", key: ":max_age", value: ConfigDB.to_binary(18))
119 ConfigDB.update_or_create(%{
120 group: config1.group,
122 value: [another_repo: [Pleroma.Repo]]
126 ConfigDB.update_or_create(%{
127 group: config2.group,
132 updated1 = ConfigDB.get_by_params(%{group: config1.group, key: config1.key})
133 updated2 = ConfigDB.get_by_params(%{group: config2.group, key: config2.key})
135 assert ConfigDB.from_binary(updated1.value) == [another_repo: [Pleroma.Repo]]
136 assert ConfigDB.from_binary(updated2.value) == 777
139 test "full update if value is not keyword" do
144 value: ConfigDB.to_binary(Tesla.Adapter.Hackney)
148 ConfigDB.update_or_create(%{
151 value: Tesla.Adapter.Httpc
154 updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
156 assert ConfigDB.from_binary(updated.value) == Tesla.Adapter.Httpc
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})
166 describe "transform/1" 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"
174 binary = ConfigDB.transform(false)
175 assert binary == :erlang.term_to_binary(false)
176 assert ConfigDB.from_binary(binary) == false
180 binary = ConfigDB.transform(nil)
181 assert binary == :erlang.term_to_binary(nil)
182 assert ConfigDB.from_binary(binary) == nil
186 binary = ConfigDB.transform(150)
187 assert binary == :erlang.term_to_binary(150)
188 assert ConfigDB.from_binary(binary) == 150
192 binary = ConfigDB.transform(":atom")
193 assert binary == :erlang.term_to_binary(:atom)
194 assert ConfigDB.from_binary(binary) == :atom
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"]
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
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"
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
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
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
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
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/
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/
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
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
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
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")
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}
281 test "proxy tuple with localhost" do
283 ConfigDB.transform(%{
284 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]
287 assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, :localhost, 1234}})
288 assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, :localhost, 1234}}
291 test "proxy tuple with domain" do
293 ConfigDB.transform(%{
294 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]
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}}
301 test "proxy tuple with ip" do
303 ConfigDB.transform(%{
304 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]
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}}
311 test "tuple with n childs" do
313 ConfigDB.transform(%{
320 "Phoenix.Socket.V1.JSONSerializer"
325 :erlang.term_to_binary(
326 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
329 assert ConfigDB.from_binary(binary) ==
330 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
333 test "tuple with dispatch key" do
334 binary = ConfigDB.transform(%{"tuple" => [":dispatch", ["{:_,
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, []}}
344 :erlang.term_to_binary(
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, []}}
358 assert ConfigDB.from_binary(binary) ==
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, []}}
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"}
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"}
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"]
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]
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]
402 test "list of mixed values" do
408 "Phoenix.Socket.V1.JSONSerializer",
414 :erlang.term_to_binary([
418 Phoenix.Socket.V1.JSONSerializer,
423 assert ConfigDB.from_binary(binary) == [
427 Phoenix.Socket.V1.JSONSerializer,
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"]
440 test "keyword with partial_chain key" do
442 ConfigDB.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}])
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]
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"]}
459 :erlang.term_to_binary(
460 types: Pleroma.PostgresTypes,
461 telemetry_event: [Pleroma.Repo.Instrumenter],
467 assert ConfigDB.from_binary(binary) == [
468 types: Pleroma.PostgresTypes,
469 telemetry_event: [Pleroma.Repo.Instrumenter],
476 test "complex keyword with nested mixed childs" do
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"}]},
488 %{"tuple" => [":redirect_on_failure", false]},
489 %{"tuple" => [":max_body_length", 1_048_576]},
493 [%{"tuple" => [":follow_redirect", true]}, %{"tuple" => [":pool", ":upload"]}]
502 :erlang.term_to_binary(
503 uploader: Pleroma.Uploaders.Local,
504 filters: [Pleroma.Upload.Filter.Dedupe],
507 common_map: %{key: "value"},
509 redirect_on_failure: false,
510 max_body_length: 1_048_576,
512 follow_redirect: true,
518 assert ConfigDB.from_binary(binary) ==
520 uploader: Pleroma.Uploaders.Local,
521 filters: [Pleroma.Upload.Filter.Dedupe],
524 common_map: %{key: "value"},
526 redirect_on_failure: false,
527 max_body_length: 1_048_576,
529 follow_redirect: true,
536 test "common keyword" do
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"]}
547 :erlang.term_to_binary(
552 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
555 assert ConfigDB.from_binary(binary) == [
560 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
564 test "complex keyword with sigil" do
567 %{"tuple" => [":federated_timeline_removal", []]},
568 %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]},
569 %{"tuple" => [":replace", []]}
573 :erlang.term_to_binary(
574 federated_timeline_removal: [],
575 reject: [~r/comp[lL][aA][iI][nN]er/],
579 assert ConfigDB.from_binary(binary) ==
580 [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []]
583 test "complex keyword with tuples with more than 2 values" do
601 "Pleroma.Web.MastodonAPI.WebsocketHandler",
608 "Phoenix.Endpoint.CowboyWebSocket",
611 "Phoenix.Transports.WebSocket",
614 "Pleroma.Web.Endpoint",
615 "Pleroma.Web.UserSocket",
626 "Phoenix.Endpoint.Cowboy2Handler",
627 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
642 :erlang.term_to_binary(
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, []}}
656 assert ConfigDB.from_binary(binary) == [
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, []}}