From 410add1c30d230e86c22de4e54bb9999de980b16 Mon Sep 17 00:00:00 2001 From: Alex S Date: Sat, 22 Jun 2019 17:30:53 +0300 Subject: [PATCH] support for tuples with more than 2 values --- docs/api/admin_api.md | 7 +- lib/pleroma/web/admin_api/config.ex | 56 ++++---- .../admin_api/admin_api_controller_test.exs | 120 +++++++++++++++++- test/web/admin_api/config_test.exs | 75 +++++++++++ 4 files changed, 230 insertions(+), 28 deletions(-) diff --git a/docs/api/admin_api.md b/docs/api/admin_api.md index 5dcc8d059..63af33821 100644 --- a/docs/api/admin_api.md +++ b/docs/api/admin_api.md @@ -580,6 +580,8 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret Module name can be passed as string, which starts with `Pleroma`, e.g. `"Pleroma.Upload"`. Atom or boolean value can be passed with `:` in the beginning, e.g. `":true"`, `":upload"`. Integer with `i:`, e.g. `"i:150"`. +Tuple with more than 2 values with `{"tuple": ["first_val", Pleroma.Module, []]}`. +`{"tuple": ["some_string", "Pleroma.Some.Module", []]}` will be converted to `{"some_string", Pleroma.Some.Module, []}`. Compile time settings (need instance reboot): - all settings by this keys: @@ -619,6 +621,9 @@ Compile time settings (need instance reboot): "follow_redirect": ":true", "pool": ":upload" } + }, + "dispatch": { + "tuple": ["/api/v1/streaming", "Pleroma.Web.MastodonAPI.WebsocketHandler", []] } } } @@ -632,7 +637,7 @@ Compile time settings (need instance reboot): configs: [ { "key": string, - "value": string or {} or [] + "value": string or {} or [] or {"tuple": []} } ] } diff --git a/lib/pleroma/web/admin_api/config.ex b/lib/pleroma/web/admin_api/config.ex index ddcfc87d5..2e149bf25 100644 --- a/lib/pleroma/web/admin_api/config.ex +++ b/lib/pleroma/web/admin_api/config.ex @@ -77,6 +77,8 @@ defp do_convert(values) when is_list(values), do: for(val <- values, do: do_conv defp do_convert({k, v} = value) when is_tuple(value), do: %{k => do_convert(v)} + defp do_convert(value) when is_tuple(value), do: %{"tuple" => do_convert(Tuple.to_list(value))} + defp do_convert(value) when is_binary(value) or is_map(value) or is_number(value), do: value defp do_convert(value) when is_atom(value) do @@ -108,11 +110,16 @@ def transform(entity), do: :erlang.term_to_binary(entity) defp do_transform(%Regex{} = value) when is_map(value), do: value + defp do_transform(%{"tuple" => [k, values] = entity}) when length(entity) == 2 do + {do_transform(k), do_transform(values)} + end + + defp do_transform(%{"tuple" => values}) do + Enum.reduce(values, {}, fn val, acc -> Tuple.append(acc, do_transform(val)) end) + end + defp do_transform(value) when is_map(value) do - values = - for {key, val} <- value, - into: [], - do: {String.to_atom(key), do_transform(val)} + values = for {key, val} <- value, into: [], do: {String.to_atom(key), do_transform(val)} Enum.sort(values) end @@ -124,28 +131,27 @@ defp do_transform(value) when is_list(value) do defp do_transform(entity) when is_list(entity) and length(entity) == 1, do: hd(entity) defp do_transform(value) when is_binary(value) do - value = String.trim(value) - - case String.length(value) do - 0 -> - nil - - _ -> - cond do - String.starts_with?(value, "Pleroma") -> - String.to_existing_atom("Elixir." <> value) - - String.starts_with?(value, ":") -> - String.replace(value, ":", "") |> String.to_existing_atom() - - String.starts_with?(value, "i:") -> - String.replace(value, "i:", "") |> String.to_integer() - - true -> - value - end - end + String.trim(value) + |> do_transform_string() end defp do_transform(value), do: value + + defp do_transform_string(value) when byte_size(value) == 0, do: nil + + defp do_transform_string(value) do + cond do + String.starts_with?(value, "Pleroma") or String.starts_with?(value, "Phoenix") -> + String.to_existing_atom("Elixir." <> value) + + String.starts_with?(value, ":") -> + String.replace(value, ":", "") |> String.to_existing_atom() + + String.starts_with?(value, "i:") -> + String.replace(value, "i:", "") |> String.to_integer() + + true -> + value + end + end end diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index 17a872b21..49889d6d7 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -1343,6 +1343,8 @@ test "with settings in db", %{conn: conn} do Application.delete_env(:pleroma, :key4) Application.delete_env(:pleroma, :keyaa1) Application.delete_env(:pleroma, :keyaa2) + Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal) + Application.delete_env(:pleroma, Pleroma.Captcha.NotReal) :ok = File.rm(temp_file) end) @@ -1469,7 +1471,7 @@ test "common config example", %{conn: conn} do post(conn, "/api/pleroma/admin/config", %{ configs: [ %{ - "key" => "Pleroma.Captcha", + "key" => "Pleroma.Captcha.NotReal", "value" => %{ "enabled" => ":false", "method" => "Pleroma.Captcha.Kocaptcha", @@ -1482,7 +1484,7 @@ test "common config example", %{conn: conn} do assert json_response(conn, 200) == %{ "configs" => [ %{ - "key" => "Pleroma.Captcha", + "key" => "Pleroma.Captcha.NotReal", "value" => [ %{"enabled" => false}, %{"method" => "Pleroma.Captcha.Kocaptcha"}, @@ -1492,5 +1494,119 @@ test "common config example", %{conn: conn} do ] } end + + test "tuples with more than two values", %{conn: conn} do + conn = + post(conn, "/api/pleroma/admin/config", %{ + configs: [ + %{ + "key" => "Pleroma.Web.Endpoint.NotReal", + "value" => [ + %{ + "http" => %{ + "dispatch" => [ + %{ + "tuple" => [ + ":_", + [ + %{ + "tuple" => [ + "/api/v1/streaming", + "Pleroma.Web.MastodonAPI.WebsocketHandler", + [] + ] + }, + %{ + "tuple" => [ + "/websocket", + "Phoenix.Endpoint.CowboyWebSocket", + %{ + "tuple" => [ + "Phoenix.Transports.WebSocket", + %{ + "tuple" => [ + "Pleroma.Web.Endpoint", + "Pleroma.Web.UserSocket", + [] + ] + } + ] + } + ] + }, + %{ + "tuple" => [ + ":_", + "Phoenix.Endpoint.Cowboy2Handler", + %{ + "tuple" => ["Pleroma.Web.Endpoint", []] + } + ] + } + ] + ] + } + ] + } + } + ] + } + ] + }) + + assert json_response(conn, 200) == %{ + "configs" => [ + %{ + "key" => "Pleroma.Web.Endpoint.NotReal", + "value" => [ + %{ + "http" => %{ + "dispatch" => %{ + "_" => [ + %{ + "tuple" => [ + "/api/v1/streaming", + "Pleroma.Web.MastodonAPI.WebsocketHandler", + [] + ] + }, + %{ + "tuple" => [ + "/websocket", + "Phoenix.Endpoint.CowboyWebSocket", + %{ + "Elixir.Phoenix.Transports.WebSocket" => %{ + "tuple" => [ + "Pleroma.Web.Endpoint", + "Pleroma.Web.UserSocket", + [] + ] + } + } + ] + }, + %{ + "tuple" => [ + "_", + "Phoenix.Endpoint.Cowboy2Handler", + %{"Elixir.Pleroma.Web.Endpoint" => []} + ] + } + ] + } + } + } + ] + } + ] + } + end end end + +# Needed for testing +defmodule Pleroma.Web.Endpoint.NotReal do +end + +defmodule Pleroma.Captcha.NotReal do +end diff --git a/test/web/admin_api/config_test.exs b/test/web/admin_api/config_test.exs index a2fedca40..39050c276 100644 --- a/test/web/admin_api/config_test.exs +++ b/test/web/admin_api/config_test.exs @@ -179,5 +179,80 @@ test "complex map with sigil" do assert Config.from_binary(binary) == [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []] end + + test "complex map with tuples with more than 2 values" do + binary = + Config.transform(%{ + "http" => %{ + "dispatch" => [ + %{ + "tuple" => [ + ":_", + [ + %{ + "tuple" => [ + "/api/v1/streaming", + "Pleroma.Web.MastodonAPI.WebsocketHandler", + [] + ] + }, + %{ + "tuple" => [ + "/websocket", + "Phoenix.Endpoint.CowboyWebSocket", + %{ + "tuple" => [ + "Phoenix.Transports.WebSocket", + %{"tuple" => ["Pleroma.Web.Endpoint", "Pleroma.Web.UserSocket", []]} + ] + } + ] + }, + %{ + "tuple" => [ + ":_", + "Phoenix.Endpoint.Cowboy2Handler", + %{ + "tuple" => ["Pleroma.Web.Endpoint", []] + } + ] + } + ] + ] + } + ] + } + }) + + assert binary == + :erlang.term_to_binary( + http: [ + dispatch: [ + _: [ + {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, + {"/websocket", Phoenix.Endpoint.CowboyWebSocket, + {Phoenix.Transports.WebSocket, + {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}}, + {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}} + ] + ] + ] + ) + + assert Config.from_binary(binary) == [ + http: [ + dispatch: [ + {:_, + [ + {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, + {"/websocket", Phoenix.Endpoint.CowboyWebSocket, + {Phoenix.Transports.WebSocket, + {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}}, + {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}} + ]} + ] + ] + ] + end end end