little fixes and typos fix
[akkoma] / test / web / admin_api / admin_api_controller_test.exs
index 2fc23ad6c567cb4806cc0d2d5fd893538921b128..d83a95aae8459c03210957e89403fc83dfc45d01 100644 (file)
@@ -10,11 +10,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
   alias Pleroma.HTML
   alias Pleroma.ModerationLog
   alias Pleroma.Repo
+  alias Pleroma.ReportNote
   alias Pleroma.Tests.ObanHelpers
   alias Pleroma.User
   alias Pleroma.UserInviteToken
   alias Pleroma.Web.ActivityPub.Relay
   alias Pleroma.Web.CommonAPI
+  alias Pleroma.Web.MastodonAPI.StatusView
   alias Pleroma.Web.MediaProxy
   import Pleroma.Factory
 
@@ -36,6 +38,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope" do
       user = insert(:user)
       admin = insert(:user, is_admin: true)
+      url = "/api/pleroma/admin/users/#{user.nickname}"
 
       good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
       good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
@@ -50,17 +53,27 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
           build_conn()
           |> assign(:user, admin)
           |> assign(:token, good_token)
-          |> get("/api/pleroma/admin/users/#{user.nickname}")
+          |> get(url)
 
         assert json_response(conn, 200)
       end
 
+      for good_token <- [good_token1, good_token2, good_token3] do
+        conn =
+          build_conn()
+          |> assign(:user, nil)
+          |> assign(:token, good_token)
+          |> get(url)
+
+        assert json_response(conn, :forbidden)
+      end
+
       for bad_token <- [bad_token1, bad_token2, bad_token3] do
         conn =
           build_conn()
           |> assign(:user, admin)
           |> assign(:token, bad_token)
-          |> get("/api/pleroma/admin/users/#{user.nickname}")
+          |> get(url)
 
         assert json_response(conn, :forbidden)
       end
@@ -1656,6 +1669,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
         second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
         third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
+        first_report: first_report,
         first_status_reports: [first_report, second_report, third_report],
         second_status_reports: [first_report, second_report],
         third_status_reports: [first_report],
@@ -1682,14 +1696,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
 
       assert length(response["reports"]) == 3
 
-      first_group =
-        Enum.find(response["reports"], &(&1["status"]["id"] == first_status.data["id"]))
+      first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id))
 
-      second_group =
-        Enum.find(response["reports"], &(&1["status"]["id"] == second_status.data["id"]))
+      second_group = Enum.find(response["reports"], &(&1["status"]["id"] == second_status.id))
 
-      third_group =
-        Enum.find(response["reports"], &(&1["status"]["id"] == third_status.data["id"]))
+      third_group = Enum.find(response["reports"], &(&1["status"]["id"] == third_status.id))
 
       assert length(first_group["reports"]) == 3
       assert length(second_group["reports"]) == 2
@@ -1700,13 +1711,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                  NaiveDateTime.from_iso8601!(act.data["published"])
                end).data["published"]
 
-      assert first_group["status"] == %{
-               "id" => first_status.data["id"],
-               "content" => first_status.object.data["content"],
-               "published" => first_status.object.data["published"]
-             }
+      assert first_group["status"] ==
+               Map.put(
+                 stringify_keys(StatusView.render("show.json", %{activity: first_status})),
+                 "deleted",
+                 false
+               )
 
-      assert first_group["account"]["id"] == target_user.id
+      assert(first_group["account"]["id"] == target_user.id)
 
       assert length(first_group["actors"]) == 1
       assert hd(first_group["actors"])["id"] == reporter.id
@@ -1719,11 +1731,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                  NaiveDateTime.from_iso8601!(act.data["published"])
                end).data["published"]
 
-      assert second_group["status"] == %{
-               "id" => second_status.data["id"],
-               "content" => second_status.object.data["content"],
-               "published" => second_status.object.data["published"]
-             }
+      assert second_group["status"] ==
+               Map.put(
+                 stringify_keys(StatusView.render("show.json", %{activity: second_status})),
+                 "deleted",
+                 false
+               )
 
       assert second_group["account"]["id"] == target_user.id
 
@@ -1738,11 +1751,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                  NaiveDateTime.from_iso8601!(act.data["published"])
                end).data["published"]
 
-      assert third_group["status"] == %{
-               "id" => third_status.data["id"],
-               "content" => third_status.object.data["content"],
-               "published" => third_status.object.data["published"]
-             }
+      assert third_group["status"] ==
+               Map.put(
+                 stringify_keys(StatusView.render("show.json", %{activity: third_status})),
+                 "deleted",
+                 false
+               )
 
       assert third_group["account"]["id"] == target_user.id
 
@@ -1752,60 +1766,69 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert Enum.map(third_group["reports"], & &1["id"]) --
                Enum.map(third_status_reports, & &1.id) == []
     end
-  end
 
-  describe "POST /api/pleroma/admin/reports/:id/respond" do
-    setup %{conn: conn} do
-      admin = insert(:user, is_admin: true)
+    test "reopened report renders status data", %{
+      conn: conn,
+      first_report: first_report,
+      first_status: first_status
+    } do
+      {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
 
-      %{conn: assign(conn, :user, admin), admin: admin}
+      response =
+        conn
+        |> get("/api/pleroma/admin/grouped_reports")
+        |> json_response(:ok)
+
+      first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id))
+
+      assert first_group["status"] ==
+               Map.put(
+                 stringify_keys(StatusView.render("show.json", %{activity: first_status})),
+                 "deleted",
+                 false
+               )
     end
 
-    test "returns created dm", %{conn: conn, admin: admin} do
-      [reporter, target_user] = insert_pair(:user)
-      activity = insert(:note_activity, user: target_user)
+    test "reopened report does not render status data if status has been deleted", %{
+      conn: conn,
+      first_report: first_report,
+      first_status: first_status,
+      target_user: target_user
+    } do
+      {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
+      {:ok, _} = CommonAPI.delete(first_status.id, target_user)
 
-      {:ok, %{id: report_id}} =
-        CommonAPI.report(reporter, %{
-          "account_id" => target_user.id,
-          "comment" => "I feel offended",
-          "status_ids" => [activity.id]
-        })
+      refute Activity.get_by_ap_id(first_status.id)
 
       response =
         conn
-        |> post("/api/pleroma/admin/reports/#{report_id}/respond", %{
-          "status" => "I will check it out"
-        })
+        |> get("/api/pleroma/admin/grouped_reports")
         |> json_response(:ok)
 
-      recipients = Enum.map(response["mentions"], & &1["username"])
+      assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["status"][
+               "deleted"
+             ] == true
 
-      assert reporter.nickname in recipients
-      assert response["content"] == "I will check it out"
-      assert response["visibility"] == "direct"
-
-      log_entry = Repo.one(ModerationLog)
-
-      assert ModerationLog.get_log_entry_message(log_entry) ==
-               "@#{admin.nickname} responded with 'I will check it out' to report ##{
-                 response["id"]
-               }"
+      assert length(Enum.filter(response["reports"], &(&1["status"]["deleted"] == false))) == 2
     end
 
-    test "returns 400 when status is missing", %{conn: conn} do
-      conn = post(conn, "/api/pleroma/admin/reports/test/respond")
+    test "account not empty if status was deleted", %{
+      conn: conn,
+      first_report: first_report,
+      first_status: first_status,
+      target_user: target_user
+    } do
+      {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
+      {:ok, _} = CommonAPI.delete(first_status.id, target_user)
 
-      assert json_response(conn, :bad_request) == "Invalid parameters"
-    end
+      refute Activity.get_by_ap_id(first_status.id)
 
-    test "returns 404 when report id is invalid", %{conn: conn} do
-      conn =
-        post(conn, "/api/pleroma/admin/reports/test/respond", %{
-          "status" => "foo"
-        })
+      response =
+        conn
+        |> get("/api/pleroma/admin/grouped_reports")
+        |> json_response(:ok)
 
-      assert json_response(conn, :not_found) == "Not found"
+      assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["account"]
     end
   end
 
@@ -1906,16 +1929,31 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
   end
 
   describe "GET /api/pleroma/admin/config" do
+    clear_config([:instance, :dynamic_configuration]) do
+      Pleroma.Config.put([:instance, :dynamic_configuration], true)
+    end
+
     setup %{conn: conn} do
       admin = insert(:user, is_admin: true)
 
       %{conn: assign(conn, :user, admin)}
     end
 
+    test "when dynamic configuration is off", %{conn: conn} do
+      initial = Pleroma.Config.get([:instance, :dynamic_configuration])
+      Pleroma.Config.put([:instance, :dynamic_configuration], false)
+      on_exit(fn -> Pleroma.Config.put([:instance, :dynamic_configuration], initial) end)
+      conn = get(conn, "/api/pleroma/admin/config")
+
+      assert json_response(conn, 400) ==
+               "To use this endpoint you need to enable dynamic configuration."
+    end
+
     test "without any settings in db", %{conn: conn} do
       conn = get(conn, "/api/pleroma/admin/config")
 
-      assert json_response(conn, 200) == %{"configs" => []}
+      assert json_response(conn, 400) ==
+               "To use dynamic configuration migrate your settings to database."
     end
 
     test "with settings in db", %{conn: conn} do
@@ -1927,6 +1965,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       %{
         "configs" => [
           %{
+            "group" => ":pleroma",
             "key" => key1,
             "value" => _
           },
@@ -1942,11 +1981,23 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     end
   end
 
+  test "POST /api/pleroma/admin/config error" do
+    admin = insert(:user, is_admin: true)
+
+    conn =
+      build_conn()
+      |> assign(:user, admin)
+      |> post("/api/pleroma/admin/config", %{"configs" => []})
+
+    assert json_response(conn, 400) ==
+             "To use this endpoint you need to enable dynamic configuration."
+  end
+
   describe "POST /api/pleroma/admin/config" do
     setup %{conn: conn} do
       admin = insert(:user, is_admin: true)
 
-      temp_file = "config/test.exported_from_db.secret.exs"
+      http = Application.get_env(:pleroma, :http)
 
       on_exit(fn ->
         Application.delete_env(:pleroma, :key1)
@@ -1957,7 +2008,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         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)
+        Application.put_env(:pleroma, :http, http)
+        Application.put_env(:tesla, :adapter, Tesla.Mock)
+        :ok = File.rm("config/test.exported_from_db.secret.exs")
       end)
 
       %{conn: assign(conn, :user, admin)}
@@ -1972,15 +2025,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       conn =
         post(conn, "/api/pleroma/admin/config", %{
           configs: [
-            %{group: "pleroma", key: "key1", value: "value1"},
+            %{group: ":pleroma", key: ":key1", value: "value1"},
             %{
-              group: "ueberauth",
+              group: ":ueberauth",
               key: "Ueberauth.Strategy.Twitter.OAuth",
               value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
             },
             %{
-              group: "pleroma",
-              key: "key2",
+              group: ":pleroma",
+              key: ":key2",
               value: %{
                 ":nested_1" => "nested_value1",
                 ":nested_2" => [
@@ -1990,21 +2043,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
               }
             },
             %{
-              group: "pleroma",
-              key: "key3",
+              group: ":pleroma",
+              key: ":key3",
               value: [
                 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
                 %{"nested_4" => true}
               ]
             },
             %{
-              group: "pleroma",
-              key: "key4",
+              group: ":pleroma",
+              key: ":key4",
               value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
             },
             %{
-              group: "idna",
-              key: "key5",
+              group: ":idna",
+              key: ":key5",
               value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
             }
           ]
@@ -2013,18 +2066,18 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert json_response(conn, 200) == %{
                "configs" => [
                  %{
-                   "group" => "pleroma",
-                   "key" => "key1",
+                   "group" => ":pleroma",
+                   "key" => ":key1",
                    "value" => "value1"
                  },
                  %{
-                   "group" => "ueberauth",
+                   "group" => ":ueberauth",
                    "key" => "Ueberauth.Strategy.Twitter.OAuth",
                    "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
                  },
                  %{
-                   "group" => "pleroma",
-                   "key" => "key2",
+                   "group" => ":pleroma",
+                   "key" => ":key2",
                    "value" => %{
                      ":nested_1" => "nested_value1",
                      ":nested_2" => [
@@ -2034,21 +2087,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                    }
                  },
                  %{
-                   "group" => "pleroma",
-                   "key" => "key3",
+                   "group" => ":pleroma",
+                   "key" => ":key3",
                    "value" => [
                      %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
                      %{"nested_4" => true}
                    ]
                  },
                  %{
-                   "group" => "pleroma",
-                   "key" => "key4",
+                   "group" => ":pleroma",
+                   "key" => ":key4",
                    "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
                  },
                  %{
-                   "group" => "idna",
-                   "key" => "key5",
+                   "group" => ":idna",
+                   "key" => ":key5",
                    "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
                  }
                ]
@@ -2077,14 +2130,200 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
     end
 
+    test "save config setting without key", %{conn: conn} do
+      level = Application.get_env(:quack, :level)
+      meta = Application.get_env(:quack, :meta)
+      webhook_url = Application.get_env(:quack, :webhook_url)
+
+      on_exit(fn ->
+        Application.put_env(:quack, :level, level)
+        Application.put_env(:quack, :meta, meta)
+        Application.put_env(:quack, :webhook_url, webhook_url)
+      end)
+
+      conn =
+        post(conn, "/api/pleroma/admin/config", %{
+          configs: [
+            %{
+              group: ":quack",
+              key: ":level",
+              value: ":info"
+            },
+            %{
+              group: ":quack",
+              key: ":meta",
+              value: [":none"]
+            },
+            %{
+              group: ":quack",
+              key: ":webhook_url",
+              value: "https://hooks.slack.com/services/KEY"
+            }
+          ]
+        })
+
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{"group" => ":quack", "key" => ":level", "value" => ":info"},
+                 %{"group" => ":quack", "key" => ":meta", "value" => [":none"]},
+                 %{
+                   "group" => ":quack",
+                   "key" => ":webhook_url",
+                   "value" => "https://hooks.slack.com/services/KEY"
+                 }
+               ]
+             }
+
+      assert Application.get_env(:quack, :level) == :info
+      assert Application.get_env(:quack, :meta) == [:none]
+      assert Application.get_env(:quack, :webhook_url) == "https://hooks.slack.com/services/KEY"
+    end
+
+    test "saving config with partial update", %{conn: conn} do
+      config = insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2))
+
+      conn =
+        post(conn, "/api/pleroma/admin/config", %{
+          configs: [
+            %{group: config.group, key: config.key, value: [%{"tuple" => [":key3", 3]}]}
+          ]
+        })
+
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{
+                   "group" => ":pleroma",
+                   "key" => ":key1",
+                   "value" => [
+                     %{"tuple" => [":key1", 1]},
+                     %{"tuple" => [":key2", 2]},
+                     %{"tuple" => [":key3", 3]}
+                   ]
+                 }
+               ]
+             }
+    end
+
+    test "saving special atoms", %{conn: conn} do
+      conn =
+        post(conn, "/api/pleroma/admin/config", %{
+          "configs" => [
+            %{
+              "group" => ":pleroma",
+              "key" => ":key1",
+              "value" => [
+                %{
+                  "tuple" => [
+                    ":ssl_options",
+                    [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
+                  ]
+                }
+              ]
+            }
+          ]
+        })
+
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{
+                   "group" => ":pleroma",
+                   "key" => ":key1",
+                   "value" => [
+                     %{
+                       "tuple" => [
+                         ":ssl_options",
+                         [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
+                       ]
+                     }
+                   ]
+                 }
+               ]
+             }
+
+      assert Application.get_env(:pleroma, :key1) == [
+               ssl_options: [versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]]
+             ]
+    end
+
+    test "saving full setting if value is in full_key_update list", %{conn: conn} do
+      backends = Application.get_env(:logger, :backends)
+      on_exit(fn -> Application.put_env(:logger, :backends, backends) end)
+
+      config =
+        insert(:config,
+          group: ":logger",
+          key: ":backends",
+          value: :erlang.term_to_binary([])
+        )
+
+      conn =
+        post(conn, "/api/pleroma/admin/config", %{
+          configs: [
+            %{
+              group: config.group,
+              key: config.key,
+              value: [":console", %{"tuple" => ["ExSyslogger", ":ex_syslogger"]}]
+            }
+          ]
+        })
+
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{
+                   "group" => ":logger",
+                   "key" => ":backends",
+                   "value" => [
+                     ":console",
+                     %{"tuple" => ["ExSyslogger", ":ex_syslogger"]}
+                   ]
+                 }
+               ]
+             }
+
+      assert Application.get_env(:logger, :backends) == [
+               :console,
+               {ExSyslogger, :ex_syslogger}
+             ]
+
+      ExUnit.CaptureLog.capture_log(fn ->
+        require Logger
+        Logger.warn("Ooops...")
+      end) =~ "Ooops..."
+    end
+
+    test "saving full setting if value is not keyword", %{conn: conn} do
+      config =
+        insert(:config,
+          group: ":tesla",
+          key: ":adapter",
+          value: :erlang.term_to_binary(Tesla.Adapter.Hackey)
+        )
+
+      conn =
+        post(conn, "/api/pleroma/admin/config", %{
+          configs: [
+            %{group: config.group, key: config.key, value: "Tesla.Adapter.Httpc"}
+          ]
+        })
+
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{
+                   "group" => ":tesla",
+                   "key" => ":adapter",
+                   "value" => "Tesla.Adapter.Httpc"
+                 }
+               ]
+             }
+    end
+
     test "update config setting & delete", %{conn: conn} do
-      config1 = insert(:config, key: "keyaa1")
-      config2 = insert(:config, key: "keyaa2")
+      config1 = insert(:config, key: ":keyaa1")
+      config2 = insert(:config, key: ":keyaa2")
 
       insert(:config,
         group: "ueberauth",
-        key: "Ueberauth.Strategy.Microsoft.OAuth",
-        value: :erlang.term_to_binary([])
+        key: "Ueberauth.Strategy.Microsoft.OAuth"
       )
 
       conn =
@@ -2103,7 +2342,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert json_response(conn, 200) == %{
                "configs" => [
                  %{
-                   "group" => "pleroma",
+                   "group" => ":pleroma",
                    "key" => config1.key,
                    "value" => "another_value"
                  }
@@ -2115,11 +2354,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     end
 
     test "common config example", %{conn: conn} do
+      adapter = Application.get_env(:tesla, :adapter)
+      on_exit(fn -> Application.put_env(:tesla, :adapter, adapter) end)
+
       conn =
         post(conn, "/api/pleroma/admin/config", %{
           configs: [
             %{
-              "group" => "pleroma",
+              "group" => ":pleroma",
               "key" => "Pleroma.Captcha.NotReal",
               "value" => [
                 %{"tuple" => [":enabled", false]},
@@ -2131,16 +2373,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
                 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
                 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
-                %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
+                %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},
+                %{"tuple" => [":name", "Pleroma"]}
               ]
-            }
+            },
+            %{"group" => ":tesla", "key" => ":adapter", "value" => "Tesla.Adapter.Httpc"}
           ]
         })
 
+      assert Application.get_env(:tesla, :adapter) == Tesla.Adapter.Httpc
+      assert Pleroma.Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"
+
       assert json_response(conn, 200) == %{
                "configs" => [
                  %{
-                   "group" => "pleroma",
+                   "group" => ":pleroma",
                    "key" => "Pleroma.Captcha.NotReal",
                    "value" => [
                      %{"tuple" => [":enabled", false]},
@@ -2152,9 +2399,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                      %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
                      %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
                      %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
-                     %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
+                     %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]},
+                     %{"tuple" => [":name", "Pleroma"]}
                    ]
-                 }
+                 },
+                 %{"group" => ":tesla", "key" => ":adapter", "value" => "Tesla.Adapter.Httpc"}
                ]
              }
     end
@@ -2164,7 +2413,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         post(conn, "/api/pleroma/admin/config", %{
           configs: [
             %{
-              "group" => "pleroma",
+              "group" => ":pleroma",
               "key" => "Pleroma.Web.Endpoint.NotReal",
               "value" => [
                 %{
@@ -2228,7 +2477,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert json_response(conn, 200) == %{
                "configs" => [
                  %{
-                   "group" => "pleroma",
+                   "group" => ":pleroma",
                    "key" => "Pleroma.Web.Endpoint.NotReal",
                    "value" => [
                      %{
@@ -2295,7 +2544,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         post(conn, "/api/pleroma/admin/config", %{
           configs: [
             %{
-              "group" => "pleroma",
+              "group" => ":pleroma",
               "key" => ":key1",
               "value" => [
                 %{"tuple" => [":key2", "some_val"]},
@@ -2325,7 +2574,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                %{
                  "configs" => [
                    %{
-                     "group" => "pleroma",
+                     "group" => ":pleroma",
                      "key" => ":key1",
                      "value" => [
                        %{"tuple" => [":key2", "some_val"]},
@@ -2357,7 +2606,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         post(conn, "/api/pleroma/admin/config", %{
           configs: [
             %{
-              "group" => "pleroma",
+              "group" => ":pleroma",
               "key" => ":key1",
               "value" => %{"key" => "some_val"}
             }
@@ -2368,7 +2617,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                %{
                  "configs" => [
                    %{
-                     "group" => "pleroma",
+                     "group" => ":pleroma",
                      "key" => ":key1",
                      "value" => %{"key" => "some_val"}
                    }
@@ -2381,7 +2630,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         post(conn, "/api/pleroma/admin/config", %{
           configs: [
             %{
-              "group" => "pleroma",
+              "group" => ":pleroma",
               "key" => "Pleroma.Web.Endpoint.NotReal",
               "value" => [
                 %{
@@ -2414,7 +2663,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert json_response(conn, 200) == %{
                "configs" => [
                  %{
-                   "group" => "pleroma",
+                   "group" => ":pleroma",
                    "key" => "Pleroma.Web.Endpoint.NotReal",
                    "value" => [
                      %{
@@ -2444,7 +2693,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         post(conn, "/api/pleroma/admin/config", %{
           configs: [
             %{
-              "group" => "oban",
+              "group" => ":oban",
               "key" => ":queues",
               "value" => [
                 %{"tuple" => [":federator_incoming", 50]},
@@ -2462,7 +2711,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert json_response(conn, 200) == %{
                "configs" => [
                  %{
-                   "group" => "oban",
+                   "group" => ":oban",
                    "key" => ":queues",
                    "value" => [
                      %{"tuple" => [":federator_incoming", 50]},
@@ -2481,7 +2730,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     test "delete part of settings by atom subkeys", %{conn: conn} do
       config =
         insert(:config,
-          key: "keyaa1",
+          key: ":keyaa1",
           value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
         )
 
@@ -2497,17 +2746,102 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
           ]
         })
 
-      assert(
-        json_response(conn, 200) == %{
-          "configs" => [
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{
+                   "group" => ":pleroma",
+                   "key" => ":keyaa1",
+                   "value" => [%{"tuple" => [":subkey2", "val2"]}]
+                 }
+               ]
+             }
+    end
+
+    test "proxy tuple localhost", %{conn: conn} do
+      conn =
+        post(conn, "/api/pleroma/admin/config", %{
+          configs: [
             %{
-              "group" => "pleroma",
-              "key" => "keyaa1",
-              "value" => [%{"tuple" => [":subkey2", "val2"]}]
+              group: ":pleroma",
+              key: ":http",
+              value: [
+                %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]},
+                %{"tuple" => [":send_user_agent", false]}
+              ]
             }
           ]
-        }
-      )
+        })
+
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{
+                   "group" => ":pleroma",
+                   "key" => ":http",
+                   "value" => [
+                     %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]},
+                     %{"tuple" => [":send_user_agent", false]}
+                   ]
+                 }
+               ]
+             }
+    end
+
+    test "proxy tuple domain", %{conn: conn} do
+      conn =
+        post(conn, "/api/pleroma/admin/config", %{
+          configs: [
+            %{
+              group: ":pleroma",
+              key: ":http",
+              value: [
+                %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]},
+                %{"tuple" => [":send_user_agent", false]}
+              ]
+            }
+          ]
+        })
+
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{
+                   "group" => ":pleroma",
+                   "key" => ":http",
+                   "value" => [
+                     %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]},
+                     %{"tuple" => [":send_user_agent", false]}
+                   ]
+                 }
+               ]
+             }
+    end
+
+    test "proxy tuple ip", %{conn: conn} do
+      conn =
+        post(conn, "/api/pleroma/admin/config", %{
+          configs: [
+            %{
+              group: ":pleroma",
+              key: ":http",
+              value: [
+                %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]},
+                %{"tuple" => [":send_user_agent", false]}
+              ]
+            }
+          ]
+        })
+
+      assert json_response(conn, 200) == %{
+               "configs" => [
+                 %{
+                   "group" => ":pleroma",
+                   "key" => ":http",
+                   "value" => [
+                     %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]},
+                     %{"tuple" => [":send_user_agent", false]}
+                   ]
+                 }
+               ]
+             }
     end
   end
 
@@ -2515,16 +2849,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     setup %{conn: conn} do
       admin = insert(:user, is_admin: true)
 
-      temp_file = "config/test.exported_from_db.secret.exs"
-
       Mix.shell(Mix.Shell.Quiet)
 
       on_exit(fn ->
         Mix.shell(Mix.Shell.IO)
-        :ok = File.rm(temp_file)
       end)
 
-      %{conn: assign(conn, :user, admin), admin: admin}
+      %{conn: assign(conn, :user, admin)}
     end
 
     clear_config([:instance, :dynamic_configuration]) do
@@ -2535,20 +2866,28 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
     end
 
-    test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
+    test "transfer settings to DB and to file", %{conn: conn} do
+      on_exit(fn -> :ok = File.rm("config/test.exported_from_db.secret.exs") end)
       assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
-      conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
-      assert json_response(conn, 200) == %{}
+      Mix.Tasks.Pleroma.Config.run(["migrate_to_db"])
       assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
 
-      conn =
-        build_conn()
-        |> assign(:user, admin)
-        |> get("/api/pleroma/admin/config/migrate_from_db")
+      conn = get(conn, "/api/pleroma/admin/config/migrate_from_db")
 
       assert json_response(conn, 200) == %{}
       assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
     end
+
+    test "returns error if dynamic configuration is off", %{conn: conn} do
+      initial = Pleroma.Config.get([:instance, :dynamic_configuration])
+      on_exit(fn -> Pleroma.Config.put([:instance, :dynamic_configuration], initial) end)
+      Pleroma.Config.put([:instance, :dynamic_configuration], false)
+
+      conn = get(conn, "/api/pleroma/admin/config/migrate_from_db")
+
+      assert json_response(conn, 400) ==
+               "To use this endpoint you need to enable dynamic configuration."
+    end
   end
 
   describe "GET /api/pleroma/admin/users/:nickname/statuses" do
@@ -3005,6 +3344,92 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
                }"
     end
   end
+
+  describe "POST /reports/:id/notes" do
+    setup do
+      admin = insert(:user, is_admin: true)
+      [reporter, target_user] = insert_pair(:user)
+      activity = insert(:note_activity, user: target_user)
+
+      {:ok, %{id: report_id}} =
+        CommonAPI.report(reporter, %{
+          "account_id" => target_user.id,
+          "comment" => "I feel offended",
+          "status_ids" => [activity.id]
+        })
+
+      build_conn()
+      |> assign(:user, admin)
+      |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
+        content: "this is disgusting!"
+      })
+
+      build_conn()
+      |> assign(:user, admin)
+      |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
+        content: "this is disgusting2!"
+      })
+
+      %{
+        admin_id: admin.id,
+        report_id: report_id,
+        admin: admin
+      }
+    end
+
+    test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
+      [note, _] = Repo.all(ReportNote)
+
+      assert %{
+               activity_id: ^report_id,
+               content: "this is disgusting!",
+               user_id: ^admin_id
+             } = note
+    end
+
+    test "it returns reports with notes", %{admin: admin} do
+      conn =
+        build_conn()
+        |> assign(:user, admin)
+        |> get("/api/pleroma/admin/reports")
+
+      response = json_response(conn, 200)
+      notes = hd(response["reports"])["notes"]
+      [note, _] = notes
+
+      assert note["user"]["nickname"] == admin.nickname
+      assert note["content"] == "this is disgusting!"
+      assert note["created_at"]
+      assert response["total"] == 1
+    end
+
+    test "it deletes the note", %{admin: admin, report_id: report_id} do
+      assert ReportNote |> Repo.all() |> length() == 2
+
+      [note, _] = Repo.all(ReportNote)
+
+      build_conn()
+      |> assign(:user, admin)
+      |> delete("/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
+
+      assert ReportNote |> Repo.all() |> length() == 1
+    end
+  end
+
+  test "GET /api/pleroma/admin/config/descriptions", %{conn: conn} do
+    admin = insert(:user, is_admin: true)
+
+    conn =
+      assign(conn, :user, admin)
+      |> get("/api/pleroma/admin/config/descriptions")
+
+    assert [child | _others] = json_response(conn, 200)
+
+    assert child["children"]
+    assert child["key"]
+    assert String.starts_with?(child["group"], ":")
+    assert child["description"]
+  end
 end
 
 # Needed for testing