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.Web.AdminAPI.ConfigTest do
6 use Pleroma.DataCase, async: true
8 alias Pleroma.Web.AdminAPI.Config
10 test "get_by_key/1" do
11 config = insert(:config)
14 assert config == Config.get_by_params(%{group: config.group, key: config.key})
18 {:ok, config} = Config.create(%{group: "pleroma", key: "some_key", value: "some_value"})
19 assert config == Config.get_by_params(%{group: "pleroma", key: "some_key"})
23 config = insert(:config)
24 {:ok, updated} = Config.update(config, %{value: "some_value"})
25 loaded = Config.get_by_params(%{group: config.group, key: config.key})
26 assert loaded == updated
29 describe "update_or_create/1" do
31 config = insert(:config)
35 %{group: "pleroma", key: key2, value: "another_value"},
36 %{group: config.group, key: config.key, value: "new_value"}
39 assert Repo.all(Config) |> length() == 1
41 Enum.each(params, &Config.update_or_create(&1))
43 assert Repo.all(Config) |> length() == 2
45 config1 = Config.get_by_params(%{group: config.group, key: config.key})
46 config2 = Config.get_by_params(%{group: "pleroma", key: key2})
48 assert config1.value == Config.transform("new_value")
49 assert config2.value == Config.transform("another_value")
52 test "partial update" do
53 config = insert(:config, value: Config.to_binary(key1: "val1", key2: :val2))
56 Config.update_or_create(%{
59 value: [key1: :val1, key3: :val3]
62 updated = Config.get_by_params(%{group: config.group, key: config.key})
64 value = Config.from_binary(updated.value)
65 assert length(value) == 3
66 assert value[:key1] == :val1
67 assert value[:key2] == :val2
68 assert value[:key3] == :val3
72 config = insert(:config, value: Config.to_binary(key1: "val1", key2: [k1: :v1, k2: "v2"]))
75 Config.update_or_create(%{
78 value: [key1: :val1, key2: [k2: :v2, k3: :v3], key3: :val3]
81 updated = Config.get_by_params(%{group: config.group, key: config.key})
83 assert config.value == updated.value
85 value = Config.from_binary(updated.value)
86 assert value[:key1] == :val1
87 assert value[:key2] == [k1: :v1, k2: :v2, k3: :v3]
88 assert value[:key3] == :val3
91 test "only full update for some keys" do
92 config1 = insert(:config, key: ":ecto_repos", value: Config.to_binary(repo: Pleroma.Repo))
93 config2 = insert(:config, group: ":cors_plug", key: ":max_age", value: Config.to_binary(18))
96 Config.update_or_create(%{
99 value: [another_repo: [Pleroma.Repo]]
103 Config.update_or_create(%{
104 group: config2.group,
109 updated1 = Config.get_by_params(%{group: config1.group, key: config1.key})
110 updated2 = Config.get_by_params(%{group: config2.group, key: config2.key})
112 assert Config.from_binary(updated1.value) == [another_repo: [Pleroma.Repo]]
113 assert Config.from_binary(updated2.value) == 777
116 test "full update if value is not keyword" do
121 value: Config.to_binary(Tesla.Adapter.Hackney)
125 Config.update_or_create(%{
128 value: Tesla.Adapter.Httpc
131 updated = Config.get_by_params(%{group: config.group, key: config.key})
133 assert Config.from_binary(updated.value) == Tesla.Adapter.Httpc
138 config = insert(:config)
139 {:ok, _} = Config.delete(%{key: config.key, group: config.group})
140 refute Config.get_by_params(%{key: config.key, group: config.group})
143 describe "transform/1" do
145 binary = Config.transform("value as string")
146 assert binary == :erlang.term_to_binary("value as string")
147 assert Config.from_binary(binary) == "value as string"
151 binary = Config.transform(false)
152 assert binary == :erlang.term_to_binary(false)
153 assert Config.from_binary(binary) == false
157 binary = Config.transform(nil)
158 assert binary == :erlang.term_to_binary(nil)
159 assert Config.from_binary(binary) == nil
163 binary = Config.transform(150)
164 assert binary == :erlang.term_to_binary(150)
165 assert Config.from_binary(binary) == 150
169 binary = Config.transform(":atom")
170 assert binary == :erlang.term_to_binary(:atom)
171 assert Config.from_binary(binary) == :atom
174 test "ssl options" do
175 binary = Config.transform([":tlsv1", ":tlsv1.1", ":tlsv1.2"])
176 assert binary == :erlang.term_to_binary([:tlsv1, :"tlsv1.1", :"tlsv1.2"])
177 assert Config.from_binary(binary) == [:tlsv1, :"tlsv1.1", :"tlsv1.2"]
180 test "pleroma module" do
181 binary = Config.transform("Pleroma.Bookmark")
182 assert binary == :erlang.term_to_binary(Pleroma.Bookmark)
183 assert Config.from_binary(binary) == Pleroma.Bookmark
186 test "pleroma string" do
187 binary = Config.transform("Pleroma")
188 assert binary == :erlang.term_to_binary("Pleroma")
189 assert Config.from_binary(binary) == "Pleroma"
192 test "phoenix module" do
193 binary = Config.transform("Phoenix.Socket.V1.JSONSerializer")
194 assert binary == :erlang.term_to_binary(Phoenix.Socket.V1.JSONSerializer)
195 assert Config.from_binary(binary) == Phoenix.Socket.V1.JSONSerializer
198 test "tesla module" do
199 binary = Config.transform("Tesla.Adapter.Hackney")
200 assert binary == :erlang.term_to_binary(Tesla.Adapter.Hackney)
201 assert Config.from_binary(binary) == Tesla.Adapter.Hackney
204 test "ExSyslogger module" do
205 binary = Config.transform("ExSyslogger")
206 assert binary == :erlang.term_to_binary(ExSyslogger)
207 assert Config.from_binary(binary) == ExSyslogger
210 test "Quack.Logger module" do
211 binary = Config.transform("Quack.Logger")
212 assert binary == :erlang.term_to_binary(Quack.Logger)
213 assert Config.from_binary(binary) == Quack.Logger
217 binary = Config.transform("~r[comp[lL][aA][iI][nN]er]")
218 assert binary == :erlang.term_to_binary(~r/comp[lL][aA][iI][nN]er/)
219 assert Config.from_binary(binary) == ~r/comp[lL][aA][iI][nN]er/
223 binary = Config.transform("~r/https:\/\/example.com/")
224 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/)
225 assert Config.from_binary(binary) == ~r/https:\/\/example.com/
228 test "link sigil with um modifiers" do
229 binary = Config.transform("~r/https:\/\/example.com/um")
230 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/um)
231 assert Config.from_binary(binary) == ~r/https:\/\/example.com/um
234 test "link sigil with i modifier" do
235 binary = Config.transform("~r/https:\/\/example.com/i")
236 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/i)
237 assert Config.from_binary(binary) == ~r/https:\/\/example.com/i
240 test "link sigil with s modifier" do
241 binary = Config.transform("~r/https:\/\/example.com/s")
242 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/s)
243 assert Config.from_binary(binary) == ~r/https:\/\/example.com/s
246 test "raise if valid delimiter not found" do
247 assert_raise ArgumentError, "valid delimiter for Regex expression not found", fn ->
248 Config.transform("~r/https://[]{}<>\"'()|example.com/s")
252 test "2 child tuple" do
253 binary = Config.transform(%{"tuple" => ["v1", ":v2"]})
254 assert binary == :erlang.term_to_binary({"v1", :v2})
255 assert Config.from_binary(binary) == {"v1", :v2}
258 test "proxy tuple with localhost" do
261 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]
264 assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, :localhost, 1234}})
265 assert Config.from_binary(binary) == {:proxy_url, {:socks5, :localhost, 1234}}
268 test "proxy tuple with domain" do
271 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]
274 assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, 'domain.com', 1234}})
275 assert Config.from_binary(binary) == {:proxy_url, {:socks5, 'domain.com', 1234}}
278 test "proxy tuple with ip" do
281 "tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]
284 assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}})
285 assert Config.from_binary(binary) == {:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}}
288 test "tuple with n childs" do
297 "Phoenix.Socket.V1.JSONSerializer"
302 :erlang.term_to_binary(
303 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
306 assert Config.from_binary(binary) ==
307 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
310 test "tuple with dispatch key" do
311 binary = Config.transform(%{"tuple" => [":dispatch", ["{:_,
313 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
314 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
315 {Phoenix.Transports.WebSocket,
316 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
317 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
321 :erlang.term_to_binary(
326 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
327 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
328 {Phoenix.Transports.WebSocket,
329 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: "/websocket"]}}},
330 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
335 assert Config.from_binary(binary) ==
340 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
341 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
342 {Phoenix.Transports.WebSocket,
343 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: "/websocket"]}}},
344 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
349 test "map with string key" do
350 binary = Config.transform(%{"key" => "value"})
351 assert binary == :erlang.term_to_binary(%{"key" => "value"})
352 assert Config.from_binary(binary) == %{"key" => "value"}
355 test "map with atom key" do
356 binary = Config.transform(%{":key" => "value"})
357 assert binary == :erlang.term_to_binary(%{key: "value"})
358 assert Config.from_binary(binary) == %{key: "value"}
361 test "list of strings" do
362 binary = Config.transform(["v1", "v2", "v3"])
363 assert binary == :erlang.term_to_binary(["v1", "v2", "v3"])
364 assert Config.from_binary(binary) == ["v1", "v2", "v3"]
367 test "list of modules" do
368 binary = Config.transform(["Pleroma.Repo", "Pleroma.Activity"])
369 assert binary == :erlang.term_to_binary([Pleroma.Repo, Pleroma.Activity])
370 assert Config.from_binary(binary) == [Pleroma.Repo, Pleroma.Activity]
373 test "list of atoms" do
374 binary = Config.transform([":v1", ":v2", ":v3"])
375 assert binary == :erlang.term_to_binary([:v1, :v2, :v3])
376 assert Config.from_binary(binary) == [:v1, :v2, :v3]
379 test "list of mixed values" do
385 "Phoenix.Socket.V1.JSONSerializer",
391 :erlang.term_to_binary([
395 Phoenix.Socket.V1.JSONSerializer,
400 assert Config.from_binary(binary) == [
404 Phoenix.Socket.V1.JSONSerializer,
410 test "simple keyword" do
411 binary = Config.transform([%{"tuple" => [":key", "value"]}])
412 assert binary == :erlang.term_to_binary([{:key, "value"}])
413 assert Config.from_binary(binary) == [{:key, "value"}]
414 assert Config.from_binary(binary) == [key: "value"]
417 test "keyword with partial_chain key" do
419 Config.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}])
421 assert binary == :erlang.term_to_binary(partial_chain: &:hackney_connect.partial_chain/1)
422 assert Config.from_binary(binary) == [partial_chain: &:hackney_connect.partial_chain/1]
428 %{"tuple" => [":types", "Pleroma.PostgresTypes"]},
429 %{"tuple" => [":telemetry_event", ["Pleroma.Repo.Instrumenter"]]},
430 %{"tuple" => [":migration_lock", nil]},
431 %{"tuple" => [":key1", 150]},
432 %{"tuple" => [":key2", "string"]}
436 :erlang.term_to_binary(
437 types: Pleroma.PostgresTypes,
438 telemetry_event: [Pleroma.Repo.Instrumenter],
444 assert Config.from_binary(binary) == [
445 types: Pleroma.PostgresTypes,
446 telemetry_event: [Pleroma.Repo.Instrumenter],
453 test "complex keyword with nested mixed childs" do
456 %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]},
457 %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]},
458 %{"tuple" => [":link_name", true]},
459 %{"tuple" => [":proxy_remote", false]},
460 %{"tuple" => [":common_map", %{":key" => "value"}]},
465 %{"tuple" => [":redirect_on_failure", false]},
466 %{"tuple" => [":max_body_length", 1_048_576]},
470 [%{"tuple" => [":follow_redirect", true]}, %{"tuple" => [":pool", ":upload"]}]
479 :erlang.term_to_binary(
480 uploader: Pleroma.Uploaders.Local,
481 filters: [Pleroma.Upload.Filter.Dedupe],
484 common_map: %{key: "value"},
486 redirect_on_failure: false,
487 max_body_length: 1_048_576,
489 follow_redirect: true,
495 assert Config.from_binary(binary) ==
497 uploader: Pleroma.Uploaders.Local,
498 filters: [Pleroma.Upload.Filter.Dedupe],
501 common_map: %{key: "value"},
503 redirect_on_failure: false,
504 max_body_length: 1_048_576,
506 follow_redirect: true,
513 test "common keyword" do
516 %{"tuple" => [":level", ":warn"]},
517 %{"tuple" => [":meta", [":all"]]},
518 %{"tuple" => [":path", ""]},
519 %{"tuple" => [":val", nil]},
520 %{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]}
524 :erlang.term_to_binary(
529 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
532 assert Config.from_binary(binary) == [
537 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
541 test "complex keyword with sigil" do
544 %{"tuple" => [":federated_timeline_removal", []]},
545 %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]},
546 %{"tuple" => [":replace", []]}
550 :erlang.term_to_binary(
551 federated_timeline_removal: [],
552 reject: [~r/comp[lL][aA][iI][nN]er/],
556 assert Config.from_binary(binary) ==
557 [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []]
560 test "complex keyword with tuples with more than 2 values" do
578 "Pleroma.Web.MastodonAPI.WebsocketHandler",
585 "Phoenix.Endpoint.CowboyWebSocket",
588 "Phoenix.Transports.WebSocket",
591 "Pleroma.Web.Endpoint",
592 "Pleroma.Web.UserSocket",
603 "Phoenix.Endpoint.Cowboy2Handler",
604 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
619 :erlang.term_to_binary(
623 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
624 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
625 {Phoenix.Transports.WebSocket,
626 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
627 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
633 assert Config.from_binary(binary) == [
638 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
639 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
640 {Phoenix.Transports.WebSocket,
641 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
642 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}