config editing through database
[akkoma] / test / web / admin_api / config_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.Web.AdminAPI.ConfigTest do
6 use Pleroma.DataCase, async: true
7 import Pleroma.Factory
8 alias Pleroma.Web.AdminAPI.Config
9
10 test "get_by_key/1" do
11 config = insert(:config)
12 insert(:config)
13
14 assert config == Config.get_by_params(%{group: config.group, key: config.key})
15 end
16
17 test "create/1" do
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"})
20 end
21
22 test "update/1" do
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
27 end
28
29 test "update_or_create/1" do
30 config = insert(:config)
31 key2 = "another_key"
32
33 params = [
34 %{group: "pleroma", key: key2, value: "another_value"},
35 %{group: config.group, key: config.key, value: "new_value"}
36 ]
37
38 assert Repo.all(Config) |> length() == 1
39
40 Enum.each(params, &Config.update_or_create(&1))
41
42 assert Repo.all(Config) |> length() == 2
43
44 config1 = Config.get_by_params(%{group: config.group, key: config.key})
45 config2 = Config.get_by_params(%{group: "pleroma", key: key2})
46
47 assert config1.value == Config.transform("new_value")
48 assert config2.value == Config.transform("another_value")
49 end
50
51 test "delete/1" do
52 config = insert(:config)
53 {:ok, _} = Config.delete(%{key: config.key, group: config.group})
54 refute Config.get_by_params(%{key: config.key, group: config.group})
55 end
56
57 describe "transform/1" do
58 test "string" do
59 binary = Config.transform("value as string")
60 assert binary == :erlang.term_to_binary("value as string")
61 assert Config.from_binary(binary) == "value as string"
62 end
63
64 test "boolean" do
65 binary = Config.transform(false)
66 assert binary == :erlang.term_to_binary(false)
67 assert Config.from_binary(binary) == false
68 end
69
70 test "nil" do
71 binary = Config.transform(nil)
72 assert binary == :erlang.term_to_binary(nil)
73 assert Config.from_binary(binary) == nil
74 end
75
76 test "integer" do
77 binary = Config.transform(150)
78 assert binary == :erlang.term_to_binary(150)
79 assert Config.from_binary(binary) == 150
80 end
81
82 test "atom" do
83 binary = Config.transform(":atom")
84 assert binary == :erlang.term_to_binary(:atom)
85 assert Config.from_binary(binary) == :atom
86 end
87
88 test "pleroma module" do
89 binary = Config.transform("Pleroma.Bookmark")
90 assert binary == :erlang.term_to_binary(Pleroma.Bookmark)
91 assert Config.from_binary(binary) == Pleroma.Bookmark
92 end
93
94 test "pleroma string" do
95 binary = Config.transform("Pleroma")
96 assert binary == :erlang.term_to_binary("Pleroma")
97 assert Config.from_binary(binary) == "Pleroma"
98 end
99
100 test "phoenix module" do
101 binary = Config.transform("Phoenix.Socket.V1.JSONSerializer")
102 assert binary == :erlang.term_to_binary(Phoenix.Socket.V1.JSONSerializer)
103 assert Config.from_binary(binary) == Phoenix.Socket.V1.JSONSerializer
104 end
105
106 test "tesla module" do
107 binary = Config.transform("Tesla.Adapter.Hackney")
108 assert binary == :erlang.term_to_binary(Tesla.Adapter.Hackney)
109 assert Config.from_binary(binary) == Tesla.Adapter.Hackney
110 end
111
112 test "sigil" do
113 binary = Config.transform("~r[comp[lL][aA][iI][nN]er]")
114 assert binary == :erlang.term_to_binary(~r/comp[lL][aA][iI][nN]er/)
115 assert Config.from_binary(binary) == ~r/comp[lL][aA][iI][nN]er/
116 end
117
118 test "link sigil" do
119 binary = Config.transform("~r/https:\/\/example.com/")
120 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/)
121 assert Config.from_binary(binary) == ~r/https:\/\/example.com/
122 end
123
124 test "link sigil with um modifiers" do
125 binary = Config.transform("~r/https:\/\/example.com/um")
126 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/um)
127 assert Config.from_binary(binary) == ~r/https:\/\/example.com/um
128 end
129
130 test "link sigil with i modifier" do
131 binary = Config.transform("~r/https:\/\/example.com/i")
132 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/i)
133 assert Config.from_binary(binary) == ~r/https:\/\/example.com/i
134 end
135
136 test "link sigil with s modifier" do
137 binary = Config.transform("~r/https:\/\/example.com/s")
138 assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/s)
139 assert Config.from_binary(binary) == ~r/https:\/\/example.com/s
140 end
141
142 test "raise if valid delimiter not found" do
143 assert_raise ArgumentError, "valid delimiter for Regex expression not found", fn ->
144 Config.transform("~r/https://[]{}<>\"'()|example.com/s")
145 end
146 end
147
148 test "2 child tuple" do
149 binary = Config.transform(%{"tuple" => ["v1", ":v2"]})
150 assert binary == :erlang.term_to_binary({"v1", :v2})
151 assert Config.from_binary(binary) == {"v1", :v2}
152 end
153
154 test "tuple with n childs" do
155 binary =
156 Config.transform(%{
157 "tuple" => [
158 "v1",
159 ":v2",
160 "Pleroma.Bookmark",
161 150,
162 false,
163 "Phoenix.Socket.V1.JSONSerializer"
164 ]
165 })
166
167 assert binary ==
168 :erlang.term_to_binary(
169 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
170 )
171
172 assert Config.from_binary(binary) ==
173 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
174 end
175
176 test "tuple with dispatch key" do
177 binary = Config.transform(%{"tuple" => [":dispatch", ["{:_,
178 [
179 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
180 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
181 {Phoenix.Transports.WebSocket,
182 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
183 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
184 ]}"]]})
185
186 assert binary ==
187 :erlang.term_to_binary(
188 {:dispatch,
189 [
190 {:_,
191 [
192 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
193 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
194 {Phoenix.Transports.WebSocket,
195 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: "/websocket"]}}},
196 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
197 ]}
198 ]}
199 )
200
201 assert Config.from_binary(binary) ==
202 {:dispatch,
203 [
204 {:_,
205 [
206 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
207 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
208 {Phoenix.Transports.WebSocket,
209 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: "/websocket"]}}},
210 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
211 ]}
212 ]}
213 end
214
215 test "map with string key" do
216 binary = Config.transform(%{"key" => "value"})
217 assert binary == :erlang.term_to_binary(%{"key" => "value"})
218 assert Config.from_binary(binary) == %{"key" => "value"}
219 end
220
221 test "map with atom key" do
222 binary = Config.transform(%{":key" => "value"})
223 assert binary == :erlang.term_to_binary(%{key: "value"})
224 assert Config.from_binary(binary) == %{key: "value"}
225 end
226
227 test "list of strings" do
228 binary = Config.transform(["v1", "v2", "v3"])
229 assert binary == :erlang.term_to_binary(["v1", "v2", "v3"])
230 assert Config.from_binary(binary) == ["v1", "v2", "v3"]
231 end
232
233 test "list of modules" do
234 binary = Config.transform(["Pleroma.Repo", "Pleroma.Activity"])
235 assert binary == :erlang.term_to_binary([Pleroma.Repo, Pleroma.Activity])
236 assert Config.from_binary(binary) == [Pleroma.Repo, Pleroma.Activity]
237 end
238
239 test "list of atoms" do
240 binary = Config.transform([":v1", ":v2", ":v3"])
241 assert binary == :erlang.term_to_binary([:v1, :v2, :v3])
242 assert Config.from_binary(binary) == [:v1, :v2, :v3]
243 end
244
245 test "list of mixed values" do
246 binary =
247 Config.transform([
248 "v1",
249 ":v2",
250 "Pleroma.Repo",
251 "Phoenix.Socket.V1.JSONSerializer",
252 15,
253 false
254 ])
255
256 assert binary ==
257 :erlang.term_to_binary([
258 "v1",
259 :v2,
260 Pleroma.Repo,
261 Phoenix.Socket.V1.JSONSerializer,
262 15,
263 false
264 ])
265
266 assert Config.from_binary(binary) == [
267 "v1",
268 :v2,
269 Pleroma.Repo,
270 Phoenix.Socket.V1.JSONSerializer,
271 15,
272 false
273 ]
274 end
275
276 test "simple keyword" do
277 binary = Config.transform([%{"tuple" => [":key", "value"]}])
278 assert binary == :erlang.term_to_binary([{:key, "value"}])
279 assert Config.from_binary(binary) == [{:key, "value"}]
280 assert Config.from_binary(binary) == [key: "value"]
281 end
282
283 test "keyword with partial_chain key" do
284 binary =
285 Config.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}])
286
287 assert binary == :erlang.term_to_binary(partial_chain: &:hackney_connect.partial_chain/1)
288 assert Config.from_binary(binary) == [partial_chain: &:hackney_connect.partial_chain/1]
289 end
290
291 test "keyword" do
292 binary =
293 Config.transform([
294 %{"tuple" => [":types", "Pleroma.PostgresTypes"]},
295 %{"tuple" => [":telemetry_event", ["Pleroma.Repo.Instrumenter"]]},
296 %{"tuple" => [":migration_lock", nil]},
297 %{"tuple" => [":key1", 150]},
298 %{"tuple" => [":key2", "string"]}
299 ])
300
301 assert binary ==
302 :erlang.term_to_binary(
303 types: Pleroma.PostgresTypes,
304 telemetry_event: [Pleroma.Repo.Instrumenter],
305 migration_lock: nil,
306 key1: 150,
307 key2: "string"
308 )
309
310 assert Config.from_binary(binary) == [
311 types: Pleroma.PostgresTypes,
312 telemetry_event: [Pleroma.Repo.Instrumenter],
313 migration_lock: nil,
314 key1: 150,
315 key2: "string"
316 ]
317 end
318
319 test "complex keyword with nested mixed childs" do
320 binary =
321 Config.transform([
322 %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]},
323 %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]},
324 %{"tuple" => [":link_name", true]},
325 %{"tuple" => [":proxy_remote", false]},
326 %{"tuple" => [":common_map", %{":key" => "value"}]},
327 %{
328 "tuple" => [
329 ":proxy_opts",
330 [
331 %{"tuple" => [":redirect_on_failure", false]},
332 %{"tuple" => [":max_body_length", 1_048_576]},
333 %{
334 "tuple" => [
335 ":http",
336 [%{"tuple" => [":follow_redirect", true]}, %{"tuple" => [":pool", ":upload"]}]
337 ]
338 }
339 ]
340 ]
341 }
342 ])
343
344 assert binary ==
345 :erlang.term_to_binary(
346 uploader: Pleroma.Uploaders.Local,
347 filters: [Pleroma.Upload.Filter.Dedupe],
348 link_name: true,
349 proxy_remote: false,
350 common_map: %{key: "value"},
351 proxy_opts: [
352 redirect_on_failure: false,
353 max_body_length: 1_048_576,
354 http: [
355 follow_redirect: true,
356 pool: :upload
357 ]
358 ]
359 )
360
361 assert Config.from_binary(binary) ==
362 [
363 uploader: Pleroma.Uploaders.Local,
364 filters: [Pleroma.Upload.Filter.Dedupe],
365 link_name: true,
366 proxy_remote: false,
367 common_map: %{key: "value"},
368 proxy_opts: [
369 redirect_on_failure: false,
370 max_body_length: 1_048_576,
371 http: [
372 follow_redirect: true,
373 pool: :upload
374 ]
375 ]
376 ]
377 end
378
379 test "common keyword" do
380 binary =
381 Config.transform([
382 %{"tuple" => [":level", ":warn"]},
383 %{"tuple" => [":meta", [":all"]]},
384 %{"tuple" => [":path", ""]},
385 %{"tuple" => [":val", nil]},
386 %{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]}
387 ])
388
389 assert binary ==
390 :erlang.term_to_binary(
391 level: :warn,
392 meta: [:all],
393 path: "",
394 val: nil,
395 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
396 )
397
398 assert Config.from_binary(binary) == [
399 level: :warn,
400 meta: [:all],
401 path: "",
402 val: nil,
403 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
404 ]
405 end
406
407 test "complex keyword with sigil" do
408 binary =
409 Config.transform([
410 %{"tuple" => [":federated_timeline_removal", []]},
411 %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]},
412 %{"tuple" => [":replace", []]}
413 ])
414
415 assert binary ==
416 :erlang.term_to_binary(
417 federated_timeline_removal: [],
418 reject: [~r/comp[lL][aA][iI][nN]er/],
419 replace: []
420 )
421
422 assert Config.from_binary(binary) ==
423 [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []]
424 end
425
426 test "complex keyword with tuples with more than 2 values" do
427 binary =
428 Config.transform([
429 %{
430 "tuple" => [
431 ":http",
432 [
433 %{
434 "tuple" => [
435 ":key1",
436 [
437 %{
438 "tuple" => [
439 ":_",
440 [
441 %{
442 "tuple" => [
443 "/api/v1/streaming",
444 "Pleroma.Web.MastodonAPI.WebsocketHandler",
445 []
446 ]
447 },
448 %{
449 "tuple" => [
450 "/websocket",
451 "Phoenix.Endpoint.CowboyWebSocket",
452 %{
453 "tuple" => [
454 "Phoenix.Transports.WebSocket",
455 %{
456 "tuple" => [
457 "Pleroma.Web.Endpoint",
458 "Pleroma.Web.UserSocket",
459 []
460 ]
461 }
462 ]
463 }
464 ]
465 },
466 %{
467 "tuple" => [
468 ":_",
469 "Phoenix.Endpoint.Cowboy2Handler",
470 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
471 ]
472 }
473 ]
474 ]
475 }
476 ]
477 ]
478 }
479 ]
480 ]
481 }
482 ])
483
484 assert binary ==
485 :erlang.term_to_binary(
486 http: [
487 key1: [
488 _: [
489 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
490 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
491 {Phoenix.Transports.WebSocket,
492 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
493 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
494 ]
495 ]
496 ]
497 )
498
499 assert Config.from_binary(binary) == [
500 http: [
501 key1: [
502 {:_,
503 [
504 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
505 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
506 {Phoenix.Transports.WebSocket,
507 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
508 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
509 ]}
510 ]
511 ]
512 ]
513 end
514 end
515 end