diff options
Diffstat (limited to 'test/web/admin_api')
| -rw-r--r-- | test/web/admin_api/admin_api_controller_test.exs | 2381 | ||||
| -rw-r--r-- | test/web/admin_api/config_test.exs | 497 | ||||
| -rw-r--r-- | test/web/admin_api/search_test.exs | 14 | ||||
| -rw-r--r-- | test/web/admin_api/views/report_view_test.exs | 31 | 
4 files changed, 1855 insertions, 1068 deletions
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index 3b6d75a4c..8009d4386 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -1,48 +1,194 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    use Pleroma.Web.ConnCase +  use Oban.Testing, repo: Pleroma.Repo + +  import Pleroma.Factory +  import ExUnit.CaptureLog    alias Pleroma.Activity +  alias Pleroma.Config +  alias Pleroma.ConfigDB    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 -  describe "/api/pleroma/admin/users" do -    test "Delete" do -      admin = insert(:user, info: %{is_admin: true}) +  setup_all do +    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + +    :ok +  end + +  setup do +    admin = insert(:user, is_admin: true) +    token = insert(:oauth_admin_token, user: admin) + +    conn = +      build_conn() +      |> assign(:user, admin) +      |> assign(:token, token) + +    {:ok, %{admin: admin, token: token, conn: conn}} +  end + +  describe "with [:auth, :enforce_oauth_admin_scope_usage]," do +    clear_config([:auth, :enforce_oauth_admin_scope_usage]) do +      Config.put([:auth, :enforce_oauth_admin_scope_usage], true) +    end + +    test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope", +         %{admin: admin} do +      user = insert(:user) +      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"]) +      good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"]) + +      bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"]) +      bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"]) +      bad_token3 = nil + +      for good_token <- [good_token1, good_token2, good_token3] do +        conn = +          build_conn() +          |> assign(:user, admin) +          |> assign(:token, good_token) +          |> 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(url) + +        assert json_response(conn, :forbidden) +      end +    end +  end + +  describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do +    clear_config([:auth, :enforce_oauth_admin_scope_usage]) do +      Config.put([:auth, :enforce_oauth_admin_scope_usage], false) +    end + +    test "GET /api/pleroma/admin/users/:nickname requires " <> +           "read:accounts or admin:read:accounts or broader scope", +         %{admin: admin} do +      user = insert(:user) +      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"]) +      good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"]) +      good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"]) +      good_token5 = insert(:oauth_token, user: admin, scopes: ["read"]) + +      good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5] + +      bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"]) +      bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"]) +      bad_token3 = nil + +      for good_token <- good_tokens do +        conn = +          build_conn() +          |> assign(:user, admin) +          |> assign(:token, good_token) +          |> get(url) + +        assert json_response(conn, 200) +      end + +      for good_token <- good_tokens 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(url) + +        assert json_response(conn, :forbidden) +      end +    end +  end + +  describe "DELETE /api/pleroma/admin/users" do +    test "single user", %{admin: admin, conn: conn} do        user = insert(:user)        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json")          |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")        log_entry = Repo.one(ModerationLog) -      assert log_entry.data["subject"]["nickname"] == user.nickname -      assert log_entry.data["action"] == "delete" -        assert ModerationLog.get_log_entry_message(log_entry) == -               "@#{admin.nickname} deleted user @#{user.nickname}" +               "@#{admin.nickname} deleted users: @#{user.nickname}"        assert json_response(conn, 200) == user.nickname      end -    test "Create" do -      admin = insert(:user, info: %{is_admin: true}) +    test "multiple users", %{admin: admin, conn: conn} do +      user_one = insert(:user) +      user_two = insert(:user)        conn = -        build_conn() -        |> assign(:user, admin) +        conn +        |> put_req_header("accept", "application/json") +        |> delete("/api/pleroma/admin/users", %{ +          nicknames: [user_one.nickname, user_two.nickname] +        }) + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}" + +      response = json_response(conn, 200) +      assert response -- [user_one.nickname, user_two.nickname] == [] +    end +  end + +  describe "/api/pleroma/admin/users" do +    test "Create", %{conn: conn} do +      conn = +        conn          |> put_req_header("accept", "application/json")          |> post("/api/pleroma/admin/users", %{            "users" => [ @@ -67,13 +213,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []      end -    test "Cannot create user with exisiting email" do -      admin = insert(:user, info: %{is_admin: true}) +    test "Cannot create user with existing email", %{conn: conn} do        user = insert(:user)        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json")          |> post("/api/pleroma/admin/users", %{            "users" => [ @@ -98,13 +242,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do               ]      end -    test "Cannot create user with exisiting nickname" do -      admin = insert(:user, info: %{is_admin: true}) +    test "Cannot create user with existing nickname", %{conn: conn} do        user = insert(:user)        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json")          |> post("/api/pleroma/admin/users", %{            "users" => [ @@ -129,13 +271,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do               ]      end -    test "Multiple user creation works in transaction" do -      admin = insert(:user, info: %{is_admin: true}) +    test "Multiple user creation works in transaction", %{conn: conn} do        user = insert(:user)        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json")          |> post("/api/pleroma/admin/users", %{            "users" => [ @@ -179,13 +319,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    describe "/api/pleroma/admin/users/:nickname" do      test "Show", %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true})        user = insert(:user) -      conn = -        conn -        |> assign(:user, admin) -        |> get("/api/pleroma/admin/users/#{user.nickname}") +      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")        expected = %{          "deactivated" => false, @@ -195,33 +331,28 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          "roles" => %{"admin" => false, "moderator" => false},          "tags" => [],          "avatar" => User.avatar_url(user) |> MediaProxy.url(), -        "display_name" => HTML.strip_tags(user.name || user.nickname) +        "display_name" => HTML.strip_tags(user.name || user.nickname), +        "confirmation_pending" => false        }        assert expected == json_response(conn, 200)      end      test "when the user doesn't exist", %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true})        user = build(:user) -      conn = -        conn -        |> assign(:user, admin) -        |> get("/api/pleroma/admin/users/#{user.nickname}") +      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")        assert "Not found" == json_response(conn, 404)      end    end    describe "/api/pleroma/admin/users/follow" do -    test "allows to force-follow another user" do -      admin = insert(:user, info: %{is_admin: true}) +    test "allows to force-follow another user", %{admin: admin, conn: conn} do        user = insert(:user)        follower = insert(:user) -      build_conn() -      |> assign(:user, admin) +      conn        |> put_req_header("accept", "application/json")        |> post("/api/pleroma/admin/users/follow", %{          "follower" => follower.nickname, @@ -241,15 +372,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    end    describe "/api/pleroma/admin/users/unfollow" do -    test "allows to force-unfollow another user" do -      admin = insert(:user, info: %{is_admin: true}) +    test "allows to force-unfollow another user", %{admin: admin, conn: conn} do        user = insert(:user)        follower = insert(:user)        User.follow(follower, user) -      build_conn() -      |> assign(:user, admin) +      conn        |> put_req_header("accept", "application/json")        |> post("/api/pleroma/admin/users/unfollow", %{          "follower" => follower.nickname, @@ -269,23 +398,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    end    describe "PUT /api/pleroma/admin/users/tag" do -    setup do -      admin = insert(:user, info: %{is_admin: true}) +    setup %{conn: conn} do        user1 = insert(:user, %{tags: ["x"]})        user2 = insert(:user, %{tags: ["y"]})        user3 = insert(:user, %{tags: ["unchanged"]})        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json")          |> put( -          "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{ -            user2.nickname -          }&tags[]=foo&tags[]=bar" +          "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <> +            "#{user2.nickname}&tags[]=foo&tags[]=bar"          ) -      %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3} +      %{conn: conn, user1: user1, user2: user2, user3: user3}      end      test "it appends specified tags to users with specified nicknames", %{ @@ -318,23 +444,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    end    describe "DELETE /api/pleroma/admin/users/tag" do -    setup do -      admin = insert(:user, info: %{is_admin: true}) +    setup %{conn: conn} do        user1 = insert(:user, %{tags: ["x"]})        user2 = insert(:user, %{tags: ["y", "z"]})        user3 = insert(:user, %{tags: ["unchanged"]})        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json")          |> delete( -          "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{ -            user2.nickname -          }&tags[]=x&tags[]=z" +          "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <> +            "#{user2.nickname}&tags[]=x&tags[]=z"          ) -      %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3} +      %{conn: conn, user1: user1, user2: user2, user3: user3}      end      test "it removes specified tags from users with specified nicknames", %{ @@ -367,12 +490,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    end    describe "/api/pleroma/admin/users/:nickname/permission_group" do -    test "GET is giving user_info" do -      admin = insert(:user, info: %{is_admin: true}) - +    test "GET is giving user_info", %{admin: admin, conn: conn} do        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json")          |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/") @@ -382,13 +502,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do               }      end -    test "/:right POST, can add to a permission group" do -      admin = insert(:user, info: %{is_admin: true}) +    test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do        user = insert(:user)        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json")          |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin") @@ -402,121 +520,97 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "@#{admin.nickname} made @#{user.nickname} admin"      end -    test "/:right DELETE, can remove from a permission group" do -      admin = insert(:user, info: %{is_admin: true}) -      user = insert(:user, info: %{is_admin: true}) +    test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do +      user_one = insert(:user) +      user_two = insert(:user)        conn = -        build_conn() -        |> assign(:user, admin) +        conn          |> put_req_header("accept", "application/json") -        |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin") +        |> post("/api/pleroma/admin/users/permission_group/admin", %{ +          nicknames: [user_one.nickname, user_two.nickname] +        }) -      assert json_response(conn, 200) == %{ -               "is_admin" => false -             } +      assert json_response(conn, 200) == %{"is_admin" => true}        log_entry = Repo.one(ModerationLog)        assert ModerationLog.get_log_entry_message(log_entry) == -               "@#{admin.nickname} revoked admin role from @#{user.nickname}" +               "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"      end -  end -  describe "PUT /api/pleroma/admin/users/:nickname/activation_status" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +    test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do +      user = insert(:user, is_admin: true)        conn =          conn -        |> assign(:user, admin)          |> put_req_header("accept", "application/json") +        |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin") -      %{conn: conn, admin: admin} -    end - -    test "deactivates the user", %{conn: conn, admin: admin} do -      user = insert(:user) - -      conn = -        conn -        |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false}) - -      user = User.get_cached_by_id(user.id) -      assert user.info.deactivated == true -      assert json_response(conn, :no_content) +      assert json_response(conn, 200) == %{"is_admin" => false}        log_entry = Repo.one(ModerationLog)        assert ModerationLog.get_log_entry_message(log_entry) == -               "@#{admin.nickname} deactivated user @#{user.nickname}" +               "@#{admin.nickname} revoked admin role from @#{user.nickname}"      end -    test "activates the user", %{conn: conn, admin: admin} do -      user = insert(:user, info: %{deactivated: true}) +    test "/:right DELETE, can remove from a permission group (multiple)", %{ +      admin: admin, +      conn: conn +    } do +      user_one = insert(:user, is_admin: true) +      user_two = insert(:user, is_admin: true)        conn =          conn -        |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: true}) +        |> put_req_header("accept", "application/json") +        |> delete("/api/pleroma/admin/users/permission_group/admin", %{ +          nicknames: [user_one.nickname, user_two.nickname] +        }) -      user = User.get_cached_by_id(user.id) -      assert user.info.deactivated == false -      assert json_response(conn, :no_content) +      assert json_response(conn, 200) == %{"is_admin" => false}        log_entry = Repo.one(ModerationLog)        assert ModerationLog.get_log_entry_message(log_entry) == -               "@#{admin.nickname} activated user @#{user.nickname}" -    end - -    test "returns 403 when requested by a non-admin", %{conn: conn} do -      user = insert(:user) - -      conn = -        conn -        |> assign(:user, user) -        |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false}) - -      assert json_response(conn, :forbidden) +               "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{ +                 user_two.nickname +               }"      end    end    describe "POST /api/pleroma/admin/email_invite, with valid config" do -    setup do -      [user: insert(:user, info: %{is_admin: true})] -    end -      clear_config([:instance, :registrations_open]) do -      Pleroma.Config.put([:instance, :registrations_open], false) +      Config.put([:instance, :registrations_open], false)      end      clear_config([:instance, :invites_enabled]) do -      Pleroma.Config.put([:instance, :invites_enabled], true) +      Config.put([:instance, :invites_enabled], true)      end -    test "sends invitation and returns 204", %{conn: conn, user: user} do +    test "sends invitation and returns 204", %{admin: admin, conn: conn} do        recipient_email = "foo@bar.com"        recipient_name = "J. D."        conn = -        conn -        |> assign(:user, user) -        |> post( +        post( +          conn,            "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"          )        assert json_response(conn, :no_content) -      token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken)) +      token_record = List.last(Repo.all(Pleroma.UserInviteToken))        assert token_record        refute token_record.used -      notify_email = Pleroma.Config.get([:instance, :notify_email]) -      instance_name = Pleroma.Config.get([:instance, :name]) +      notify_email = Config.get([:instance, :notify_email]) +      instance_name = Config.get([:instance, :name])        email =          Pleroma.Emails.UserEmail.user_invitation_email( -          user, +          admin,            token_record,            recipient_email,            recipient_name @@ -529,12 +623,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        )      end -    test "it returns 403 if requested by a non-admin", %{conn: conn} do +    test "it returns 403 if requested by a non-admin" do        non_admin_user = insert(:user) +      token = insert(:oauth_token, user: non_admin_user)        conn = -        conn +        build_conn()          |> assign(:user, non_admin_user) +        |> assign(:token, token)          |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")        assert json_response(conn, :forbidden) @@ -542,74 +638,42 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    end    describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do -    setup do -      [user: insert(:user, info: %{is_admin: true})] -    end -      clear_config([:instance, :registrations_open])      clear_config([:instance, :invites_enabled]) -    test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do -      Pleroma.Config.put([:instance, :registrations_open], false) -      Pleroma.Config.put([:instance, :invites_enabled], false) +    test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do +      Config.put([:instance, :registrations_open], false) +      Config.put([:instance, :invites_enabled], false) -      conn = -        conn -        |> assign(:user, user) -        |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") +      conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")        assert json_response(conn, :internal_server_error)      end -    test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do -      Pleroma.Config.put([:instance, :registrations_open], true) -      Pleroma.Config.put([:instance, :invites_enabled], true) +    test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do +      Config.put([:instance, :registrations_open], true) +      Config.put([:instance, :invites_enabled], true) -      conn = -        conn -        |> assign(:user, user) -        |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") +      conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")        assert json_response(conn, :internal_server_error)      end    end -  test "/api/pleroma/admin/users/invite_token" do -    admin = insert(:user, info: %{is_admin: true}) - -    conn = -      build_conn() -      |> assign(:user, admin) -      |> put_req_header("accept", "application/json") -      |> get("/api/pleroma/admin/users/invite_token") - -    assert conn.status == 200 -  end - -  test "/api/pleroma/admin/users/:nickname/password_reset" do -    admin = insert(:user, info: %{is_admin: true}) +  test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do      user = insert(:user)      conn = -      build_conn() -      |> assign(:user, admin) +      conn        |> put_req_header("accept", "application/json")        |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset") -    assert conn.status == 200 +    resp = json_response(conn, 200) + +    assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])    end    describe "GET /api/pleroma/admin/users" do -    setup do -      admin = insert(:user, info: %{is_admin: true}) - -      conn = -        build_conn() -        |> assign(:user, admin) - -      {:ok, conn: conn, admin: admin} -    end -      test "renders users array for the first page", %{conn: conn, admin: admin} do        user = insert(:user, local: false, tags: ["foo", "bar"])        conn = get(conn, "/api/pleroma/admin/users?page=1") @@ -617,24 +681,26 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        users =          [            %{ -            "deactivated" => admin.info.deactivated, +            "deactivated" => admin.deactivated,              "id" => admin.id,              "nickname" => admin.nickname,              "roles" => %{"admin" => true, "moderator" => false},              "local" => true,              "tags" => [],              "avatar" => User.avatar_url(admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(admin.name || admin.nickname) +            "display_name" => HTML.strip_tags(admin.name || admin.nickname), +            "confirmation_pending" => false            },            %{ -            "deactivated" => user.info.deactivated, +            "deactivated" => user.deactivated,              "id" => user.id,              "nickname" => user.nickname,              "roles" => %{"admin" => false, "moderator" => false},              "local" => false,              "tags" => ["foo", "bar"],              "avatar" => User.avatar_url(user) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user.name || user.nickname) +            "display_name" => HTML.strip_tags(user.name || user.nickname), +            "confirmation_pending" => false            }          ]          |> Enum.sort_by(& &1["nickname"]) @@ -668,14 +734,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 50,                 "users" => [                   %{ -                   "deactivated" => user.info.deactivated, +                   "deactivated" => user.deactivated,                     "id" => user.id,                     "nickname" => user.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -692,14 +759,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 50,                 "users" => [                   %{ -                   "deactivated" => user.info.deactivated, +                   "deactivated" => user.deactivated,                     "id" => user.id,                     "nickname" => user.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -716,14 +784,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 50,                 "users" => [                   %{ -                   "deactivated" => user.info.deactivated, +                   "deactivated" => user.deactivated,                     "id" => user.id,                     "nickname" => user.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -740,14 +809,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 50,                 "users" => [                   %{ -                   "deactivated" => user.info.deactivated, +                   "deactivated" => user.deactivated,                     "id" => user.id,                     "nickname" => user.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -764,14 +834,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 50,                 "users" => [                   %{ -                   "deactivated" => user.info.deactivated, +                   "deactivated" => user.deactivated,                     "id" => user.id,                     "nickname" => user.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -788,14 +859,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 1,                 "users" => [                   %{ -                   "deactivated" => user.info.deactivated, +                   "deactivated" => user.deactivated,                     "id" => user.id,                     "nickname" => user.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -807,21 +879,23 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 1,                 "users" => [                   %{ -                   "deactivated" => user2.info.deactivated, +                   "deactivated" => user2.deactivated,                     "id" => user2.id,                     "nickname" => user2.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user2) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user2.name || user2.nickname) +                   "display_name" => HTML.strip_tags(user2.name || user2.nickname), +                   "confirmation_pending" => false                   }                 ]               }      end      test "only local users" do -      admin = insert(:user, info: %{is_admin: true}, nickname: "john") +      admin = insert(:user, is_admin: true, nickname: "john") +      token = insert(:oauth_admin_token, user: admin)        user = insert(:user, nickname: "bob")        insert(:user, nickname: "bobb", local: false) @@ -829,6 +903,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        conn =          build_conn()          |> assign(:user, admin) +        |> assign(:token, token)          |> get("/api/pleroma/admin/users?query=bo&filters=local")        assert json_response(conn, 200) == %{ @@ -836,51 +911,51 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 50,                 "users" => [                   %{ -                   "deactivated" => user.info.deactivated, +                   "deactivated" => user.deactivated,                     "id" => user.id,                     "nickname" => user.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               }      end -    test "only local users with no query", %{admin: old_admin} do -      admin = insert(:user, info: %{is_admin: true}, nickname: "john") +    test "only local users with no query", %{conn: conn, admin: old_admin} do +      admin = insert(:user, is_admin: true, nickname: "john")        user = insert(:user, nickname: "bob")        insert(:user, nickname: "bobb", local: false) -      conn = -        build_conn() -        |> assign(:user, admin) -        |> get("/api/pleroma/admin/users?filters=local") +      conn = get(conn, "/api/pleroma/admin/users?filters=local")        users =          [            %{ -            "deactivated" => user.info.deactivated, +            "deactivated" => user.deactivated,              "id" => user.id,              "nickname" => user.nickname,              "roles" => %{"admin" => false, "moderator" => false},              "local" => true,              "tags" => [],              "avatar" => User.avatar_url(user) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user.name || user.nickname) +            "display_name" => HTML.strip_tags(user.name || user.nickname), +            "confirmation_pending" => false            },            %{ -            "deactivated" => admin.info.deactivated, +            "deactivated" => admin.deactivated,              "id" => admin.id,              "nickname" => admin.nickname,              "roles" => %{"admin" => true, "moderator" => false},              "local" => true,              "tags" => [],              "avatar" => User.avatar_url(admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(admin.name || admin.nickname) +            "display_name" => HTML.strip_tags(admin.name || admin.nickname), +            "confirmation_pending" => false            },            %{              "deactivated" => false, @@ -890,7 +965,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "roles" => %{"admin" => true, "moderator" => false},              "tags" => [],              "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname) +            "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname), +            "confirmation_pending" => false            }          ]          |> Enum.sort_by(& &1["nickname"]) @@ -903,7 +979,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "load only admins", %{conn: conn, admin: admin} do -      second_admin = insert(:user, info: %{is_admin: true}) +      second_admin = insert(:user, is_admin: true)        insert(:user)        insert(:user) @@ -919,7 +995,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => admin.local,              "tags" => [],              "avatar" => User.avatar_url(admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(admin.name || admin.nickname) +            "display_name" => HTML.strip_tags(admin.name || admin.nickname), +            "confirmation_pending" => false            },            %{              "deactivated" => false, @@ -929,7 +1006,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => second_admin.local,              "tags" => [],              "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname) +            "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname), +            "confirmation_pending" => false            }          ]          |> Enum.sort_by(& &1["nickname"]) @@ -942,7 +1020,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "load only moderators", %{conn: conn} do -      moderator = insert(:user, info: %{is_moderator: true}) +      moderator = insert(:user, is_moderator: true)        insert(:user)        insert(:user) @@ -960,7 +1038,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => moderator.local,                     "tags" => [],                     "avatar" => User.avatar_url(moderator) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(moderator.name || moderator.nickname) +                   "display_name" => HTML.strip_tags(moderator.name || moderator.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -984,7 +1063,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => user1.local,              "tags" => ["first"],              "avatar" => User.avatar_url(user1) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user1.name || user1.nickname) +            "display_name" => HTML.strip_tags(user1.name || user1.nickname), +            "confirmation_pending" => false            },            %{              "deactivated" => false, @@ -994,7 +1074,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => user2.local,              "tags" => ["second"],              "avatar" => User.avatar_url(user2) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user2.name || user2.nickname) +            "display_name" => HTML.strip_tags(user2.name || user2.nickname), +            "confirmation_pending" => false            }          ]          |> Enum.sort_by(& &1["nickname"]) @@ -1007,15 +1088,17 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "it works with multiple filters" do -      admin = insert(:user, nickname: "john", info: %{is_admin: true}) -      user = insert(:user, nickname: "bob", local: false, info: %{deactivated: true}) +      admin = insert(:user, nickname: "john", is_admin: true) +      token = insert(:oauth_admin_token, user: admin) +      user = insert(:user, nickname: "bob", local: false, deactivated: true) -      insert(:user, nickname: "ken", local: true, info: %{deactivated: true}) -      insert(:user, nickname: "bobb", local: false, info: %{deactivated: false}) +      insert(:user, nickname: "ken", local: true, deactivated: true) +      insert(:user, nickname: "bobb", local: false, deactivated: false)        conn =          build_conn()          |> assign(:user, admin) +        |> assign(:token, token)          |> get("/api/pleroma/admin/users?filters=deactivated,external")        assert json_response(conn, 200) == %{ @@ -1023,63 +1106,115 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "page_size" => 50,                 "users" => [                   %{ -                   "deactivated" => user.info.deactivated, +                   "deactivated" => user.deactivated,                     "id" => user.id,                     "nickname" => user.nickname,                     "roles" => %{"admin" => false, "moderator" => false},                     "local" => user.local,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false +                 } +               ] +             } +    end + +    test "it omits relay user", %{admin: admin, conn: conn} do +      assert %User{} = Relay.get_actor() + +      conn = get(conn, "/api/pleroma/admin/users") + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [ +                 %{ +                   "deactivated" => admin.deactivated, +                   "id" => admin.id, +                   "nickname" => admin.nickname, +                   "roles" => %{"admin" => true, "moderator" => false}, +                   "local" => true, +                   "tags" => [], +                   "avatar" => User.avatar_url(admin) |> MediaProxy.url(), +                   "display_name" => HTML.strip_tags(admin.name || admin.nickname), +                   "confirmation_pending" => false                   }                 ]               }      end    end -  test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do -    admin = insert(:user, info: %{is_admin: true}) -    user = insert(:user) +  test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do +    user_one = insert(:user, deactivated: true) +    user_two = insert(:user, deactivated: true)      conn = -      build_conn() -      |> assign(:user, admin) -      |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation") +      patch( +        conn, +        "/api/pleroma/admin/users/activate", +        %{nicknames: [user_one.nickname, user_two.nickname]} +      ) + +    response = json_response(conn, 200) +    assert Enum.map(response["users"], & &1["deactivated"]) == [false, false] + +    log_entry = Repo.one(ModerationLog) + +    assert ModerationLog.get_log_entry_message(log_entry) == +             "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}" +  end + +  test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do +    user_one = insert(:user, deactivated: false) +    user_two = insert(:user, deactivated: false) + +    conn = +      patch( +        conn, +        "/api/pleroma/admin/users/deactivate", +        %{nicknames: [user_one.nickname, user_two.nickname]} +      ) + +    response = json_response(conn, 200) +    assert Enum.map(response["users"], & &1["deactivated"]) == [true, true] + +    log_entry = Repo.one(ModerationLog) + +    assert ModerationLog.get_log_entry_message(log_entry) == +             "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}" +  end + +  test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do +    user = insert(:user) + +    conn = patch(conn, "/api/pleroma/admin/users/#{user.nickname}/toggle_activation")      assert json_response(conn, 200) ==               %{ -               "deactivated" => !user.info.deactivated, +               "deactivated" => !user.deactivated,                 "id" => user.id,                 "nickname" => user.nickname,                 "roles" => %{"admin" => false, "moderator" => false},                 "local" => true,                 "tags" => [],                 "avatar" => User.avatar_url(user) |> MediaProxy.url(), -               "display_name" => HTML.strip_tags(user.name || user.nickname) +               "display_name" => HTML.strip_tags(user.name || user.nickname), +               "confirmation_pending" => false               }      log_entry = Repo.one(ModerationLog)      assert ModerationLog.get_log_entry_message(log_entry) == -             "@#{admin.nickname} deactivated user @#{user.nickname}" +             "@#{admin.nickname} deactivated users: @#{user.nickname}"    end -  describe "GET /api/pleroma/admin/users/invite_token" do -    setup do -      admin = insert(:user, info: %{is_admin: true}) - -      conn = -        build_conn() -        |> assign(:user, admin) - -      {:ok, conn: conn} -    end - +  describe "POST /api/pleroma/admin/users/invite_token" do      test "without options", %{conn: conn} do -      conn = get(conn, "/api/pleroma/admin/users/invite_token") +      conn = post(conn, "/api/pleroma/admin/users/invite_token") -      token = json_response(conn, 200) -      invite = UserInviteToken.find_by_token!(token) +      invite_json = json_response(conn, 200) +      invite = UserInviteToken.find_by_token!(invite_json["token"])        refute invite.used        refute invite.expires_at        refute invite.max_use @@ -1088,12 +1223,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      test "with expires_at", %{conn: conn} do        conn = -        get(conn, "/api/pleroma/admin/users/invite_token", %{ -          "invite" => %{"expires_at" => Date.to_string(Date.utc_today())} +        post(conn, "/api/pleroma/admin/users/invite_token", %{ +          "expires_at" => Date.to_string(Date.utc_today())          }) -      token = json_response(conn, 200) -      invite = UserInviteToken.find_by_token!(token) +      invite_json = json_response(conn, 200) +      invite = UserInviteToken.find_by_token!(invite_json["token"])        refute invite.used        assert invite.expires_at == Date.utc_today() @@ -1102,13 +1237,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "with max_use", %{conn: conn} do -      conn = -        get(conn, "/api/pleroma/admin/users/invite_token", %{ -          "invite" => %{"max_use" => 150} -        }) +      conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150}) -      token = json_response(conn, 200) -      invite = UserInviteToken.find_by_token!(token) +      invite_json = json_response(conn, 200) +      invite = UserInviteToken.find_by_token!(invite_json["token"])        refute invite.used        refute invite.expires_at        assert invite.max_use == 150 @@ -1117,12 +1249,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      test "with max use and expires_at", %{conn: conn} do        conn = -        get(conn, "/api/pleroma/admin/users/invite_token", %{ -          "invite" => %{"max_use" => 150, "expires_at" => Date.to_string(Date.utc_today())} +        post(conn, "/api/pleroma/admin/users/invite_token", %{ +          "max_use" => 150, +          "expires_at" => Date.to_string(Date.utc_today())          }) -      token = json_response(conn, 200) -      invite = UserInviteToken.find_by_token!(token) +      invite_json = json_response(conn, 200) +      invite = UserInviteToken.find_by_token!(invite_json["token"])        refute invite.used        assert invite.expires_at == Date.utc_today()        assert invite.max_use == 150 @@ -1131,16 +1264,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    end    describe "GET /api/pleroma/admin/users/invites" do -    setup do -      admin = insert(:user, info: %{is_admin: true}) - -      conn = -        build_conn() -        |> assign(:user, admin) - -      {:ok, conn: conn} -    end -      test "no invites", %{conn: conn} do        conn = get(conn, "/api/pleroma/admin/users/invites") @@ -1169,14 +1292,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    end    describe "POST /api/pleroma/admin/users/revoke_invite" do -    test "with token" do -      admin = insert(:user, info: %{is_admin: true}) +    test "with token", %{conn: conn} do        {:ok, invite} = UserInviteToken.create_invite() -      conn = -        build_conn() -        |> assign(:user, admin) -        |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token}) +      conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})        assert json_response(conn, 200) == %{                 "expires_at" => nil, @@ -1189,25 +1308,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do               }      end -    test "with invalid token" do -      admin = insert(:user, info: %{is_admin: true}) - -      conn = -        build_conn() -        |> assign(:user, admin) -        |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"}) +    test "with invalid token", %{conn: conn} do +      conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})        assert json_response(conn, :not_found) == "Not found"      end    end    describe "GET /api/pleroma/admin/reports/:id" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) - -      %{conn: assign(conn, :user, admin)} -    end -      test "returns report by its id", %{conn: conn} do        [reporter, target_user] = insert_pair(:user)        activity = insert(:note_activity, user: target_user) @@ -1234,9 +1342,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end -  describe "PUT /api/pleroma/admin/reports/:id" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +  describe "PATCH /api/pleroma/admin/reports" do +    setup do        [reporter, target_user] = insert_pair(:user)        activity = insert(:note_activity, user: target_user) @@ -1247,16 +1354,54 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do            "status_ids" => [activity.id]          }) -      %{conn: assign(conn, :user, admin), id: report_id, admin: admin} +      {:ok, %{id: second_report_id}} = +        CommonAPI.report(reporter, %{ +          "account_id" => target_user.id, +          "comment" => "I feel very offended", +          "status_ids" => [activity.id] +        }) + +      %{ +        id: report_id, +        second_report_id: second_report_id +      }      end -    test "mark report as resolved", %{conn: conn, id: id, admin: admin} do +    test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} do +      read_token = insert(:oauth_token, user: admin, scopes: ["admin:read"]) +      write_token = insert(:oauth_token, user: admin, scopes: ["admin:write:reports"]) +        response =          conn -        |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"}) -        |> json_response(:ok) +        |> assign(:token, read_token) +        |> patch("/api/pleroma/admin/reports", %{ +          "reports" => [%{"state" => "resolved", "id" => id}] +        }) +        |> json_response(403) -      assert response["state"] == "resolved" +      assert response == %{ +               "error" => "Insufficient permissions: admin:write:reports." +             } + +      conn +      |> assign(:token, write_token) +      |> patch("/api/pleroma/admin/reports", %{ +        "reports" => [%{"state" => "resolved", "id" => id}] +      }) +      |> json_response(:no_content) +    end + +    test "mark report as resolved", %{conn: conn, id: id, admin: admin} do +      conn +      |> patch("/api/pleroma/admin/reports", %{ +        "reports" => [ +          %{"state" => "resolved", "id" => id} +        ] +      }) +      |> json_response(:no_content) + +      activity = Activity.get_by_id(id) +      assert activity.data["state"] == "resolved"        log_entry = Repo.one(ModerationLog) @@ -1265,12 +1410,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "closes report", %{conn: conn, id: id, admin: admin} do -      response = -        conn -        |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"}) -        |> json_response(:ok) +      conn +      |> patch("/api/pleroma/admin/reports", %{ +        "reports" => [ +          %{"state" => "closed", "id" => id} +        ] +      }) +      |> json_response(:no_content) -      assert response["state"] == "closed" +      activity = Activity.get_by_id(id) +      assert activity.data["state"] == "closed"        log_entry = Repo.one(ModerationLog) @@ -1281,27 +1430,58 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      test "returns 400 when state is unknown", %{conn: conn, id: id} do        conn =          conn -        |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "test"}) +        |> patch("/api/pleroma/admin/reports", %{ +          "reports" => [ +            %{"state" => "test", "id" => id} +          ] +        }) -      assert json_response(conn, :bad_request) == "Unsupported state" +      assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"      end      test "returns 404 when report is not exist", %{conn: conn} do        conn =          conn -        |> put("/api/pleroma/admin/reports/test", %{"state" => "closed"}) +        |> patch("/api/pleroma/admin/reports", %{ +          "reports" => [ +            %{"state" => "closed", "id" => "test"} +          ] +        }) -      assert json_response(conn, :not_found) == "Not found" +      assert hd(json_response(conn, :bad_request))["error"] == "not_found"      end -  end -  describe "GET /api/pleroma/admin/reports" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +    test "updates state of multiple reports", %{ +      conn: conn, +      id: id, +      admin: admin, +      second_report_id: second_report_id +    } do +      conn +      |> patch("/api/pleroma/admin/reports", %{ +        "reports" => [ +          %{"state" => "resolved", "id" => id}, +          %{"state" => "closed", "id" => second_report_id} +        ] +      }) +      |> json_response(:no_content) -      %{conn: assign(conn, :user, admin)} +      activity = Activity.get_by_id(id) +      second_activity = Activity.get_by_id(second_report_id) +      assert activity.data["state"] == "resolved" +      assert second_activity.data["state"] == "closed" + +      [first_log_entry, second_log_entry] = Repo.all(ModerationLog) + +      assert ModerationLog.get_log_entry_message(first_log_entry) == +               "@#{admin.nickname} updated report ##{id} with 'resolved' state" + +      assert ModerationLog.get_log_entry_message(second_log_entry) == +               "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"      end +  end +  describe "GET /api/pleroma/admin/reports" do      test "returns empty response when no reports created", %{conn: conn} do        response =          conn @@ -1309,6 +1489,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          |> json_response(:ok)        assert Enum.empty?(response["reports"]) +      assert response["total"] == 0      end      test "returns reports", %{conn: conn} do @@ -1331,6 +1512,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert length(response["reports"]) == 1        assert report["id"] == report_id + +      assert response["total"] == 1      end      test "returns reports with specified state", %{conn: conn} do @@ -1364,6 +1547,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert length(response["reports"]) == 1        assert open_report["id"] == first_report_id +      assert response["total"] == 1 +        response =          conn          |> get("/api/pleroma/admin/reports", %{ @@ -1376,6 +1561,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert length(response["reports"]) == 1        assert closed_report["id"] == second_report_id +      assert response["total"] == 1 +        response =          conn          |> get("/api/pleroma/admin/reports", %{ @@ -1384,90 +1571,237 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          |> json_response(:ok)        assert Enum.empty?(response["reports"]) +      assert response["total"] == 0      end      test "returns 403 when requested by a non-admin" do        user = insert(:user) +      token = insert(:oauth_token, user: user)        conn =          build_conn()          |> assign(:user, user) +        |> assign(:token, token)          |> get("/api/pleroma/admin/reports") -      assert json_response(conn, :forbidden) == %{"error" => "User is not admin."} +      assert json_response(conn, :forbidden) == +               %{"error" => "User is not an admin or OAuth admin scope is not granted."}      end      test "returns 403 when requested by anonymous" do -      conn = -        build_conn() -        |> get("/api/pleroma/admin/reports") +      conn = get(build_conn(), "/api/pleroma/admin/reports")        assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}      end    end -  # -  describe "POST /api/pleroma/admin/reports/:id/respond" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +  describe "GET /api/pleroma/admin/grouped_reports" do +    setup do +      [reporter, target_user] = insert_pair(:user) -      %{conn: assign(conn, :user, admin), admin: admin} -    end +      date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!() +      date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() +      date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!() -    test "returns created dm", %{conn: conn, admin: admin} do -      [reporter, target_user] = insert_pair(:user) -      activity = insert(:note_activity, user: target_user) +      first_status = +        insert(:note_activity, user: target_user, data_attrs: %{"published" => date1}) -      {:ok, %{id: report_id}} = +      second_status = +        insert(:note_activity, user: target_user, data_attrs: %{"published" => date2}) + +      third_status = +        insert(:note_activity, user: target_user, data_attrs: %{"published" => date3}) + +      {:ok, first_report} =          CommonAPI.report(reporter, %{            "account_id" => target_user.id, -          "comment" => "I feel offended", -          "status_ids" => [activity.id] +          "status_ids" => [first_status.id, second_status.id, third_status.id] +        }) + +      {:ok, second_report} = +        CommonAPI.report(reporter, %{ +          "account_id" => target_user.id, +          "status_ids" => [first_status.id, second_status.id] +        }) + +      {:ok, third_report} = +        CommonAPI.report(reporter, %{ +          "account_id" => target_user.id, +          "status_ids" => [first_status.id]          }) +      %{ +        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], +        target_user: target_user, +        reporter: reporter +      } +    end + +    test "returns reports grouped by status", %{ +      conn: conn, +      first_status: first_status, +      second_status: second_status, +      third_status: third_status, +      first_status_reports: first_status_reports, +      second_status_reports: second_status_reports, +      third_status_reports: third_status_reports, +      target_user: target_user, +      reporter: reporter +    } do        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 length(response["reports"]) == 3 -      assert reporter.nickname in recipients -      assert response["content"] == "I will check it out" -      assert response["visibility"] == "direct" +      first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id)) -      log_entry = Repo.one(ModerationLog) +      second_group = Enum.find(response["reports"], &(&1["status"]["id"] == second_status.id)) -      assert ModerationLog.get_log_entry_message(log_entry) == -               "@#{admin.nickname} responded with 'I will check it out' to report ##{ -                 response["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 +      assert length(third_group["reports"]) == 1 + +      assert first_group["date"] == +               Enum.max_by(first_status_reports, fn act -> +                 NaiveDateTime.from_iso8601!(act.data["published"]) +               end).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 length(first_group["actors"]) == 1 +      assert hd(first_group["actors"])["id"] == reporter.id + +      assert Enum.map(first_group["reports"], & &1["id"]) -- +               Enum.map(first_status_reports, & &1.id) == [] + +      assert second_group["date"] == +               Enum.max_by(second_status_reports, fn act -> +                 NaiveDateTime.from_iso8601!(act.data["published"]) +               end).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 + +      assert length(second_group["actors"]) == 1 +      assert hd(second_group["actors"])["id"] == reporter.id + +      assert Enum.map(second_group["reports"], & &1["id"]) -- +               Enum.map(second_status_reports, & &1.id) == [] + +      assert third_group["date"] == +               Enum.max_by(third_status_reports, fn act -> +                 NaiveDateTime.from_iso8601!(act.data["published"]) +               end).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 + +      assert length(third_group["actors"]) == 1 +      assert hd(third_group["actors"])["id"] == reporter.id + +      assert Enum.map(third_group["reports"], & &1["id"]) -- +               Enum.map(third_status_reports, & &1.id) == []      end -    test "returns 400 when status is missing", %{conn: conn} do -      conn = post(conn, "/api/pleroma/admin/reports/test/respond") +    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") -      assert json_response(conn, :bad_request) == "Invalid parameters" +      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 404 when report id is invalid", %{conn: conn} do -      conn = -        post(conn, "/api/pleroma/admin/reports/test/respond", %{ -          "status" => "foo" -        }) +    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) -      assert json_response(conn, :not_found) == "Not found" +      refute Activity.get_by_ap_id(first_status.id) + +      response = +        conn +        |> get("/api/pleroma/admin/grouped_reports") +        |> json_response(:ok) + +      assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["status"][ +               "deleted" +             ] == true + +      assert length(Enum.filter(response["reports"], &(&1["status"]["deleted"] == false))) == 2 +    end + +    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) + +      refute Activity.get_by_ap_id(first_status.id) + +      response = +        conn +        |> get("/api/pleroma/admin/grouped_reports") +        |> json_response(:ok) + +      assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["account"]      end    end    describe "PUT /api/pleroma/admin/statuses/:id" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +    setup do        activity = insert(:note_activity) -      %{conn: assign(conn, :user, admin), id: activity.id, admin: admin} +      %{id: activity.id}      end      test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do @@ -1520,20 +1854,17 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "returns 400 when visibility is unknown", %{conn: conn, id: id} do -      conn = -        conn -        |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"}) +      conn = put(conn, "/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})        assert json_response(conn, :bad_request) == "Unsupported visibility"      end    end    describe "DELETE /api/pleroma/admin/statuses/:id" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +    setup do        activity = insert(:note_activity) -      %{conn: assign(conn, :user, admin), id: activity.id, admin: admin} +      %{id: activity.id}      end      test "deletes status", %{conn: conn, id: id, admin: admin} do @@ -1549,41 +1880,41 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "@#{admin.nickname} deleted status ##{id}"      end -    test "returns error when status is not exist", %{conn: conn} do -      conn = -        conn -        |> delete("/api/pleroma/admin/statuses/test") +    test "returns 404 when the status does not exist", %{conn: conn} do +      conn = delete(conn, "/api/pleroma/admin/statuses/test") -      assert json_response(conn, :bad_request) == "Could not delete" +      assert json_response(conn, :not_found) == "Not found"      end    end    describe "GET /api/pleroma/admin/config" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) - -      %{conn: assign(conn, :user, admin)} +    clear_config(:configurable_from_database) do +      Config.put(:configurable_from_database, true)      end -    test "without any settings in db", %{conn: conn} do +    test "when configuration from database is off", %{conn: conn} do +      Config.put(:configurable_from_database, false)        conn = get(conn, "/api/pleroma/admin/config") -      assert json_response(conn, 200) == %{"configs" => []} +      assert json_response(conn, 400) == +               "To use this endpoint you need to enable configuration from database."      end -    test "with settings in db", %{conn: conn} do +    test "with settings only in db", %{conn: conn} do        config1 = insert(:config)        config2 = insert(:config) -      conn = get(conn, "/api/pleroma/admin/config") +      conn = get(conn, "/api/pleroma/admin/config", %{"only_db" => true})        %{          "configs" => [            %{ +            "group" => ":pleroma",              "key" => key1,              "value" => _            },            %{ +            "group" => ":pleroma",              "key" => key2,              "value" => _            } @@ -1593,13 +1924,107 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert key1 == config1.key        assert key2 == config2.key      end + +    test "db is added to settings that are in db", %{conn: conn} do +      _config = insert(:config, key: ":instance", value: ConfigDB.to_binary(name: "Some name")) + +      %{"configs" => configs} = +        conn +        |> get("/api/pleroma/admin/config") +        |> json_response(200) + +      [instance_config] = +        Enum.filter(configs, fn %{"group" => group, "key" => key} -> +          group == ":pleroma" and key == ":instance" +        end) + +      assert instance_config["db"] == [":name"] +    end + +    test "merged default setting with db settings", %{conn: conn} do +      config1 = insert(:config) +      config2 = insert(:config) + +      config3 = +        insert(:config, +          value: ConfigDB.to_binary(k1: :v1, k2: :v2) +        ) + +      %{"configs" => configs} = +        conn +        |> get("/api/pleroma/admin/config") +        |> json_response(200) + +      assert length(configs) > 3 + +      received_configs = +        Enum.filter(configs, fn %{"group" => group, "key" => key} -> +          group == ":pleroma" and key in [config1.key, config2.key, config3.key] +        end) + +      assert length(received_configs) == 3 + +      db_keys = +        config3.value +        |> ConfigDB.from_binary() +        |> Keyword.keys() +        |> ConfigDB.convert() + +      Enum.each(received_configs, fn %{"value" => value, "db" => db} -> +        assert db in [[config1.key], [config2.key], db_keys] + +        assert value in [ +                 ConfigDB.from_binary_with_convert(config1.value), +                 ConfigDB.from_binary_with_convert(config2.value), +                 ConfigDB.from_binary_with_convert(config3.value) +               ] +      end) +    end + +    test "subkeys with full update right merge", %{conn: conn} do +      config1 = +        insert(:config, +          key: ":emoji", +          value: ConfigDB.to_binary(groups: [a: 1, b: 2], key: [a: 1]) +        ) + +      config2 = +        insert(:config, +          key: ":assets", +          value: ConfigDB.to_binary(mascots: [a: 1, b: 2], key: [a: 1]) +        ) + +      %{"configs" => configs} = +        conn +        |> get("/api/pleroma/admin/config") +        |> json_response(200) + +      vals = +        Enum.filter(configs, fn %{"group" => group, "key" => key} -> +          group == ":pleroma" and key in [config1.key, config2.key] +        end) + +      emoji = Enum.find(vals, fn %{"key" => key} -> key == ":emoji" end) +      assets = Enum.find(vals, fn %{"key" => key} -> key == ":assets" end) + +      emoji_val = ConfigDB.transform_with_out_binary(emoji["value"]) +      assets_val = ConfigDB.transform_with_out_binary(assets["value"]) + +      assert emoji_val[:groups] == [a: 1, b: 2] +      assert assets_val[:mascots] == [a: 1, b: 2] +    end    end -  describe "POST /api/pleroma/admin/config" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +  test "POST /api/pleroma/admin/config error", %{conn: conn} do +    conn = post(conn, "/api/pleroma/admin/config", %{"configs" => []}) -      temp_file = "config/test.exported_from_db.secret.exs" +    assert json_response(conn, 400) == +             "To use this endpoint you need to enable configuration from database." +  end + +  describe "POST /api/pleroma/admin/config" do +    setup do +      http = Application.get_env(:pleroma, :http)        on_exit(fn ->          Application.delete_env(:pleroma, :key1) @@ -1610,29 +2035,33 @@ 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) +        Restarter.Pleroma.refresh()        end) - -      %{conn: assign(conn, :user, admin)}      end -    clear_config([:instance, :dynamic_configuration]) do -      Pleroma.Config.put([:instance, :dynamic_configuration], true) +    clear_config(:configurable_from_database) do +      Config.put(:configurable_from_database, true)      end +    @tag capture_log: true      test "create new config setting in db", %{conn: conn} do +      ueberauth = Application.get_env(:ueberauth, Ueberauth) +      on_exit(fn -> Application.put_env(:ueberauth, Ueberauth, ueberauth) end) +        conn =          post(conn, "/api/pleroma/admin/config", %{            configs: [ -            %{group: "pleroma", key: "key1", value: "value1"}, +            %{group: ":pleroma", key: ":key1", value: "value1"},              %{ -              group: "ueberauth", -              key: "Ueberauth.Strategy.Twitter.OAuth", +              group: ":ueberauth", +              key: "Ueberauth",                value: [%{"tuple" => [":consumer_secret", "aaaa"]}]              },              %{ -              group: "pleroma", -              key: "key2", +              group: ":pleroma", +              key: ":key2",                value: %{                  ":nested_1" => "nested_value1",                  ":nested_2" => [ @@ -1642,21 +2071,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", []]}              }            ] @@ -1665,43 +2094,49 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma", -                   "key" => "key1", -                   "value" => "value1" +                   "group" => ":pleroma", +                   "key" => ":key1", +                   "value" => "value1", +                   "db" => [":key1"]                   },                   %{ -                   "group" => "ueberauth", -                   "key" => "Ueberauth.Strategy.Twitter.OAuth", -                   "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}] +                   "group" => ":ueberauth", +                   "key" => "Ueberauth", +                   "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}], +                   "db" => [":consumer_secret"]                   },                   %{ -                   "group" => "pleroma", -                   "key" => "key2", +                   "group" => ":pleroma", +                   "key" => ":key2",                     "value" => %{                       ":nested_1" => "nested_value1",                       ":nested_2" => [                         %{":nested_22" => "nested_value222"},                         %{":nested_33" => %{":nested_44" => "nested_444"}}                       ] -                   } +                   }, +                   "db" => [":key2"]                   },                   %{ -                   "group" => "pleroma", -                   "key" => "key3", +                   "group" => ":pleroma", +                   "key" => ":key3",                     "value" => [                       %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},                       %{"nested_4" => true} -                   ] +                   ], +                   "db" => [":key3"]                   },                   %{ -                   "group" => "pleroma", -                   "key" => "key4", -                   "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"} +                   "group" => ":pleroma", +                   "key" => ":key4", +                   "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}, +                   "db" => [":key4"]                   },                   %{ -                   "group" => "idna", -                   "key" => "key5", -                   "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]} +                   "group" => ":idna", +                   "key" => ":key5", +                   "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}, +                   "db" => [":key5"]                   }                 ]               } @@ -1729,25 +2164,303 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}      end -    test "update config setting & delete", %{conn: conn} do -      config1 = insert(:config, key: "keyaa1") -      config2 = insert(:config, key: "keyaa2") +    test "save configs setting without explicit key", %{conn: conn} do +      level = Application.get_env(:quack, :level) +      meta = Application.get_env(:quack, :meta) +      webhook_url = Application.get_env(:quack, :webhook_url) -      insert(:config, -        group: "ueberauth", -        key: "Ueberauth.Strategy.Microsoft.OAuth", -        value: :erlang.term_to_binary([]) -      ) +      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", +                   "db" => [":level"] +                 }, +                 %{ +                   "group" => ":quack", +                   "key" => ":meta", +                   "value" => [":none"], +                   "db" => [":meta"] +                 }, +                 %{ +                   "group" => ":quack", +                   "key" => ":webhook_url", +                   "value" => "https://hooks.slack.com/services/KEY", +                   "db" => [":webhook_url"] +                 } +               ] +             } + +      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]} +                   ], +                   "db" => [":key1", ":key2", ":key3"] +                 } +               ] +             } +    end + +    test "saving config which need pleroma reboot", %{conn: conn} do +      chat = Config.get(:chat) +      on_exit(fn -> Config.put(:chat, chat) end) + +      assert post( +               conn, +               "/api/pleroma/admin/config", +               %{ +                 configs: [ +                   %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]} +                 ] +               } +             ) +             |> json_response(200) == %{ +               "configs" => [ +                 %{ +                   "db" => [":enabled"], +                   "group" => ":pleroma", +                   "key" => ":chat", +                   "value" => [%{"tuple" => [":enabled", true]}] +                 } +               ], +               "need_reboot" => true +             } + +      configs = +        conn +        |> get("/api/pleroma/admin/config") +        |> json_response(200) + +      assert configs["need_reboot"] + +      capture_log(fn -> +        assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{} +      end) =~ "pleroma restarted" + +      configs = +        conn +        |> get("/api/pleroma/admin/config") +        |> json_response(200) + +      refute Map.has_key?(configs, "need_reboot") +    end + +    test "update setting which need reboot, don't change reboot flag until reboot", %{conn: conn} do +      chat = Config.get(:chat) +      on_exit(fn -> Config.put(:chat, chat) end) + +      assert post( +               conn, +               "/api/pleroma/admin/config", +               %{ +                 configs: [ +                   %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]} +                 ] +               } +             ) +             |> json_response(200) == %{ +               "configs" => [ +                 %{ +                   "db" => [":enabled"], +                   "group" => ":pleroma", +                   "key" => ":chat", +                   "value" => [%{"tuple" => [":enabled", true]}] +                 } +               ], +               "need_reboot" => true +             } + +      assert post(conn, "/api/pleroma/admin/config", %{ +               configs: [ +                 %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]} +               ] +             }) +             |> json_response(200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":key1", +                   "value" => [ +                     %{"tuple" => [":key3", 3]} +                   ], +                   "db" => [":key3"] +                 } +               ], +               "need_reboot" => true +             } + +      capture_log(fn -> +        assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{} +      end) =~ "pleroma restarted" + +      configs = +        conn +        |> get("/api/pleroma/admin/config") +        |> json_response(200) + +      refute Map.has_key?(configs, "need_reboot") +    end + +    test "saving config with nested merge", %{conn: conn} do +      config = +        insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: [k1: 1, k2: 2])) + +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{ +              group: config.group, +              key: config.key, +              value: [ +                %{"tuple" => [":key3", 3]}, +                %{ +                  "tuple" => [ +                    ":key2", +                    [ +                      %{"tuple" => [":k2", 1]}, +                      %{"tuple" => [":k3", 3]} +                    ] +                  ] +                } +              ] +            } +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":key1", +                   "value" => [ +                     %{"tuple" => [":key1", 1]}, +                     %{"tuple" => [":key3", 3]}, +                     %{ +                       "tuple" => [ +                         ":key2", +                         [ +                           %{"tuple" => [":k1", 1]}, +                           %{"tuple" => [":k2", 1]}, +                           %{"tuple" => [":k3", 3]} +                         ] +                       ] +                     } +                   ], +                   "db" => [":key1", ":key3", ":key2"] +                 } +               ] +             } +    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"]]}] +                       ] +                     } +                   ], +                   "db" => [":ssl_options"] +                 } +               ] +             } + +      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: config1.group, key: config1.key, value: "another_value"}, -            %{group: config2.group, key: config2.key, delete: "true"},              %{ -              group: "ueberauth", -              key: "Ueberauth.Strategy.Microsoft.OAuth", -              delete: "true" +              group: config.group, +              key: config.key, +              value: [":console", %{"tuple" => ["ExSyslogger", ":ex_syslogger"]}]              }            ]          }) @@ -1755,23 +2468,131 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma", +                   "group" => ":logger", +                   "key" => ":backends", +                   "value" => [ +                     ":console", +                     %{"tuple" => ["ExSyslogger", ":ex_syslogger"]} +                   ], +                   "db" => [":backends"] +                 } +               ] +             } + +      assert Application.get_env(:logger, :backends) == [ +               :console, +               {ExSyslogger, :ex_syslogger} +             ] + +      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", +                   "db" => [":adapter"] +                 } +               ] +             } +    end + +    test "update config setting & delete with fallback to default value", %{ +      conn: conn, +      admin: admin, +      token: token +    } do +      ueberauth = Application.get_env(:ueberauth, Ueberauth) +      config1 = insert(:config, key: ":keyaa1") +      config2 = insert(:config, key: ":keyaa2") + +      config3 = +        insert(:config, +          group: ":ueberauth", +          key: "Ueberauth" +        ) + +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{group: config1.group, key: config1.key, value: "another_value"}, +            %{group: config2.group, key: config2.key, value: "another_value"} +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma",                     "key" => config1.key, -                   "value" => "another_value" +                   "value" => "another_value", +                   "db" => [":keyaa1"] +                 }, +                 %{ +                   "group" => ":pleroma", +                   "key" => config2.key, +                   "value" => "another_value", +                   "db" => [":keyaa2"]                   }                 ]               }        assert Application.get_env(:pleroma, :keyaa1) == "another_value" -      refute Application.get_env(:pleroma, :keyaa2) +      assert Application.get_env(:pleroma, :keyaa2) == "another_value" +      assert Application.get_env(:ueberauth, Ueberauth) == ConfigDB.from_binary(config3.value) + +      conn = +        build_conn() +        |> assign(:user, admin) +        |> assign(:token, token) +        |> post("/api/pleroma/admin/config", %{ +          configs: [ +            %{group: config2.group, key: config2.key, delete: true}, +            %{ +              group: ":ueberauth", +              key: "Ueberauth", +              delete: true +            } +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [] +             } + +      assert Application.get_env(:ueberauth, Ueberauth) == ueberauth +      refute Keyword.has_key?(Application.get_all_env(:pleroma), :keyaa2)      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]}, @@ -1783,16 +2604,25 @@ 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 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]}, @@ -1804,8 +2634,28 @@ 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"]} +                   ], +                   "db" => [ +                     ":enabled", +                     ":method", +                     ":seconds_valid", +                     ":path", +                     ":key1", +                     ":partial_chain", +                     ":regex1", +                     ":regex2", +                     ":regex3", +                     ":regex4", +                     ":name"                     ] +                 }, +                 %{ +                   "group" => ":tesla", +                   "key" => ":adapter", +                   "value" => "Tesla.Adapter.Httpc", +                   "db" => [":adapter"]                   }                 ]               } @@ -1816,7 +2666,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "pleroma", +              "group" => ":pleroma",                "key" => "Pleroma.Web.Endpoint.NotReal",                "value" => [                  %{ @@ -1880,7 +2730,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma", +                   "group" => ":pleroma",                     "key" => "Pleroma.Web.Endpoint.NotReal",                     "value" => [                       %{ @@ -1936,7 +2786,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                           ]                         ]                       } -                   ] +                   ], +                   "db" => [":http"]                   }                 ]               } @@ -1947,7 +2798,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"]}, @@ -1977,7 +2828,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 %{                   "configs" => [                     %{ -                     "group" => "pleroma", +                     "group" => ":pleroma",                       "key" => ":key1",                       "value" => [                         %{"tuple" => [":key2", "some_val"]}, @@ -1998,7 +2849,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                             }                           ]                         } -                     ] +                     ], +                     "db" => [":key2", ":key3"]                     }                   ]                 } @@ -2009,7 +2861,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "pleroma", +              "group" => ":pleroma",                "key" => ":key1",                "value" => %{"key" => "some_val"}              } @@ -2020,83 +2872,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 %{                   "configs" => [                     %{ -                     "group" => "pleroma", +                     "group" => ":pleroma",                       "key" => ":key1", -                     "value" => %{"key" => "some_val"} +                     "value" => %{"key" => "some_val"}, +                     "db" => [":key1"]                     }                   ]                 }      end -    test "dispatch setting", %{conn: conn} do -      conn = -        post(conn, "/api/pleroma/admin/config", %{ -          configs: [ -            %{ -              "group" => "pleroma", -              "key" => "Pleroma.Web.Endpoint.NotReal", -              "value" => [ -                %{ -                  "tuple" => [ -                    ":http", -                    [ -                      %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]}, -                      %{"tuple" => [":dispatch", ["{:_, -       [ -         {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, -         {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, -          {Phoenix.Transports.WebSocket, -           {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, -         {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}} -       ]}"]]} -                    ] -                  ] -                } -              ] -            } -          ] -        }) - -      dispatch_string = -        "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <> -          "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <> -          "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <> -          "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}" - -      assert json_response(conn, 200) == %{ -               "configs" => [ -                 %{ -                   "group" => "pleroma", -                   "key" => "Pleroma.Web.Endpoint.NotReal", -                   "value" => [ -                     %{ -                       "tuple" => [ -                         ":http", -                         [ -                           %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]}, -                           %{ -                             "tuple" => [ -                               ":dispatch", -                               [ -                                 dispatch_string -                               ] -                             ] -                           } -                         ] -                       ] -                     } -                   ] -                 } -               ] -             } -    end -      test "queues key as atom", %{conn: conn} do        conn =          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "pleroma_job_queue", +              "group" => ":oban",                "key" => ":queues",                "value" => [                  %{"tuple" => [":federator_incoming", 50]}, @@ -2114,7 +2904,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma_job_queue", +                   "group" => ":oban",                     "key" => ":queues",                     "value" => [                       %{"tuple" => [":federator_incoming", 50]}, @@ -2124,6 +2914,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                       %{"tuple" => [":transmogrifier", 20]},                       %{"tuple" => [":scheduled_activities", 10]},                       %{"tuple" => [":background", 5]} +                   ], +                   "db" => [ +                     ":federator_incoming", +                     ":federator_outgoing", +                     ":web_push", +                     ":mailer", +                     ":transmogrifier", +                     ":scheduled_activities", +                     ":background"                     ]                   }                 ] @@ -2133,7 +2932,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")          ) @@ -2144,64 +2943,176 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                group: config.group,                key: config.key,                subkeys: [":subkey1", ":subkey3"], -              delete: "true" +              delete: true              }            ]          }) -      assert( -        json_response(conn, 200) == %{ -          "configs" => [ +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":keyaa1", +                   "value" => [%{"tuple" => [":subkey2", "val2"]}], +                   "db" => [":subkey2"] +                 } +               ] +             } +    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]} +                   ], +                   "db" => [":proxy_url", ":send_user_agent"] +                 } +               ] +             }      end -  end -  describe "config mix tasks run" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +    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]} +                   ], +                   "db" => [":proxy_url", ":send_user_agent"] +                 } +               ] +             } +    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]} +              ] +            } +          ] +        }) -      temp_file = "config/test.exported_from_db.secret.exs" +      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]} +                   ], +                   "db" => [":proxy_url", ":send_user_agent"] +                 } +               ] +             } +    end +  end -      Mix.shell(Mix.Shell.Quiet) +  describe "GET /api/pleroma/admin/restart" do +    clear_config(:configurable_from_database) do +      Config.put(:configurable_from_database, true) +    end -      on_exit(fn -> -        Mix.shell(Mix.Shell.IO) -        :ok = File.rm(temp_file) -      end) +    test "pleroma restarts", %{conn: conn} do +      capture_log(fn -> +        assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{} +      end) =~ "pleroma restarted" -      %{conn: assign(conn, :user, admin), admin: admin} +      refute Restarter.Pleroma.need_reboot?()      end +  end + +  describe "GET /api/pleroma/admin/statuses" do +    test "returns all public, unlisted, and direct statuses", %{conn: conn, admin: admin} do +      blocked = insert(:user) +      user = insert(:user) +      User.block(admin, blocked) + +      {:ok, _} = +        CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"}) -    clear_config([:instance, :dynamic_configuration]) do -      Pleroma.Config.put([:instance, :dynamic_configuration], true) +      {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"}) +      {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) +      {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) +      {:ok, _} = CommonAPI.post(blocked, %{"status" => ".", "visibility" => "public"}) + +      response = +        conn +        |> get("/api/pleroma/admin/statuses") +        |> json_response(200) + +      refute "private" in Enum.map(response, & &1["visibility"]) +      assert length(response) == 4      end -    test "transfer settings to DB and to file", %{conn: conn, admin: admin} do -      assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == [] -      conn = get(conn, "/api/pleroma/admin/config/migrate_to_db") -      assert json_response(conn, 200) == %{} -      assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0 +    test "returns only local statuses with local_only on", %{conn: conn} do +      user = insert(:user) +      remote_user = insert(:user, local: false, nickname: "archaeme@archae.me") +      insert(:note_activity, user: user, local: true) +      insert(:note_activity, user: remote_user, local: false) -      conn = -        build_conn() -        |> assign(:user, admin) -        |> get("/api/pleroma/admin/config/migrate_from_db") +      response = +        conn +        |> get("/api/pleroma/admin/statuses?local_only=true") +        |> json_response(200) + +      assert length(response) == 1 +    end -      assert json_response(conn, 200) == %{} -      assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == [] +    test "returns private statuses with godmode on", %{conn: conn} do +      user = insert(:user) +      {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) +      {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) +      conn = get(conn, "/api/pleroma/admin/statuses?godmode=true") +      assert json_response(conn, 200) |> length() == 2      end    end    describe "GET /api/pleroma/admin/users/:nickname/statuses" do      setup do -      admin = insert(:user, info: %{is_admin: true})        user = insert(:user)        date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() @@ -2212,11 +3123,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        insert(:note_activity, user: user, published: date2)        insert(:note_activity, user: user, published: date3) -      conn = -        build_conn() -        |> assign(:user, admin) - -      {:ok, conn: conn, user: user} +      %{user: user}      end      test "renders user's statuses", %{conn: conn, user: user} do @@ -2254,13 +3161,27 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) |> length() == 5      end + +    test "excludes reblogs by default", %{conn: conn, user: user} do +      other_user = insert(:user) +      {:ok, activity} = CommonAPI.post(user, %{"status" => "."}) +      {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, other_user) + +      conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses") +      assert json_response(conn_res, 200) |> length() == 0 + +      conn_res = +        get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true") + +      assert json_response(conn_res, 200) |> length() == 1 +    end    end    describe "GET /api/pleroma/admin/moderation_log" do -    setup %{conn: conn} do -      admin = insert(:user, info: %{is_admin: true}) +    setup do +      moderator = insert(:user, is_moderator: true) -      %{conn: assign(conn, :user, admin), admin: admin} +      %{moderator: moderator}      end      test "returns the log", %{conn: conn, admin: admin} do @@ -2293,9 +3214,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        conn = get(conn, "/api/pleroma/admin/moderation_log")        response = json_response(conn, 200) -      [first_entry, second_entry] = response +      [first_entry, second_entry] = response["items"] -      assert response |> length() == 2 +      assert response["total"] == 2        assert first_entry["data"]["action"] == "relay_unfollow"        assert first_entry["message"] == @@ -2337,9 +3258,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")        response1 = json_response(conn1, 200) -      [first_entry] = response1 +      [first_entry] = response1["items"] -      assert response1 |> length() == 1 +      assert response1["total"] == 2 +      assert response1["items"] |> length() == 1        assert first_entry["data"]["action"] == "relay_unfollow"        assert first_entry["message"] == @@ -2348,14 +3270,369 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")        response2 = json_response(conn2, 200) -      [second_entry] = response2 +      [second_entry] = response2["items"] -      assert response2 |> length() == 1 +      assert response2["total"] == 2 +      assert response2["items"] |> length() == 1        assert second_entry["data"]["action"] == "relay_follow"        assert second_entry["message"] ==                 "@#{admin.nickname} followed relay: https://example.org/relay"      end + +    test "filters log by date", %{conn: conn, admin: admin} do +      first_date = "2017-08-15T15:47:06Z" +      second_date = "2017-08-20T15:47:06Z" + +      Repo.insert(%ModerationLog{ +        data: %{ +          actor: %{ +            "id" => admin.id, +            "nickname" => admin.nickname, +            "type" => "user" +          }, +          action: "relay_follow", +          target: "https://example.org/relay" +        }, +        inserted_at: NaiveDateTime.from_iso8601!(first_date) +      }) + +      Repo.insert(%ModerationLog{ +        data: %{ +          actor: %{ +            "id" => admin.id, +            "nickname" => admin.nickname, +            "type" => "user" +          }, +          action: "relay_unfollow", +          target: "https://example.org/relay" +        }, +        inserted_at: NaiveDateTime.from_iso8601!(second_date) +      }) + +      conn1 = +        get( +          conn, +          "/api/pleroma/admin/moderation_log?start_date=#{second_date}" +        ) + +      response1 = json_response(conn1, 200) +      [first_entry] = response1["items"] + +      assert response1["total"] == 1 +      assert first_entry["data"]["action"] == "relay_unfollow" + +      assert first_entry["message"] == +               "@#{admin.nickname} unfollowed relay: https://example.org/relay" +    end + +    test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do +      Repo.insert(%ModerationLog{ +        data: %{ +          actor: %{ +            "id" => admin.id, +            "nickname" => admin.nickname, +            "type" => "user" +          }, +          action: "relay_follow", +          target: "https://example.org/relay" +        } +      }) + +      Repo.insert(%ModerationLog{ +        data: %{ +          actor: %{ +            "id" => moderator.id, +            "nickname" => moderator.nickname, +            "type" => "user" +          }, +          action: "relay_unfollow", +          target: "https://example.org/relay" +        } +      }) + +      conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}") + +      response1 = json_response(conn1, 200) +      [first_entry] = response1["items"] + +      assert response1["total"] == 1 +      assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id +    end + +    test "returns log filtered by search", %{conn: conn, moderator: moderator} do +      ModerationLog.insert_log(%{ +        actor: moderator, +        action: "relay_follow", +        target: "https://example.org/relay" +      }) + +      ModerationLog.insert_log(%{ +        actor: moderator, +        action: "relay_unfollow", +        target: "https://example.org/relay" +      }) + +      conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo") + +      response1 = json_response(conn1, 200) +      [first_entry] = response1["items"] + +      assert response1["total"] == 1 + +      assert get_in(first_entry, ["data", "message"]) == +               "@#{moderator.nickname} unfollowed relay: https://example.org/relay" +    end +  end + +  describe "PATCH /users/:nickname/force_password_reset" do +    test "sets password_reset_pending to true", %{conn: conn} do +      user = insert(:user) +      assert user.password_reset_pending == false + +      conn = +        patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]}) + +      assert json_response(conn, 204) == "" + +      ObanHelpers.perform_all() + +      assert User.get_by_id(user.id).password_reset_pending == true +    end +  end + +  describe "relays" do +    test "POST /relay", %{conn: conn, admin: admin} do +      conn = +        post(conn, "/api/pleroma/admin/relay", %{ +          relay_url: "http://mastodon.example.org/users/admin" +        }) + +      assert json_response(conn, 200) == "http://mastodon.example.org/users/admin" + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin" +    end + +    test "GET /relay", %{conn: conn} do +      relay_user = Pleroma.Web.ActivityPub.Relay.get_actor() + +      ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"] +      |> Enum.each(fn ap_id -> +        {:ok, user} = User.get_or_fetch_by_ap_id(ap_id) +        User.follow(relay_user, user) +      end) + +      conn = get(conn, "/api/pleroma/admin/relay") + +      assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == [] +    end + +    test "DELETE /relay", %{conn: conn, admin: admin} do +      post(conn, "/api/pleroma/admin/relay", %{ +        relay_url: "http://mastodon.example.org/users/admin" +      }) + +      conn = +        delete(conn, "/api/pleroma/admin/relay", %{ +          relay_url: "http://mastodon.example.org/users/admin" +        }) + +      assert json_response(conn, 200) == "http://mastodon.example.org/users/admin" + +      [log_entry_one, log_entry_two] = Repo.all(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry_one) == +               "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin" + +      assert ModerationLog.get_log_entry_message(log_entry_two) == +               "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin" +    end +  end + +  describe "instances" do +    test "GET /instances/:instance/statuses", %{conn: conn} do +      user = insert(:user, local: false, nickname: "archaeme@archae.me") +      user2 = insert(:user, local: false, nickname: "test@test.com") +      insert_pair(:note_activity, user: user) +      activity = insert(:note_activity, user: user2) + +      ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses") + +      response = json_response(ret_conn, 200) + +      assert length(response) == 2 + +      ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses") + +      response = json_response(ret_conn, 200) + +      assert length(response) == 1 + +      ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses") + +      response = json_response(ret_conn, 200) + +      assert Enum.empty?(response) + +      CommonAPI.repeat(activity.id, user) + +      ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses") +      response = json_response(ret_conn, 200) +      assert length(response) == 2 + +      ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true") +      response = json_response(ret_conn, 200) +      assert length(response) == 3 +    end +  end + +  describe "PATCH /confirm_email" do +    test "it confirms emails of two users", %{conn: conn, admin: admin} do +      [first_user, second_user] = insert_pair(:user, confirmation_pending: true) + +      assert first_user.confirmation_pending == true +      assert second_user.confirmation_pending == true + +      ret_conn = +        patch(conn, "/api/pleroma/admin/users/confirm_email", %{ +          nicknames: [ +            first_user.nickname, +            second_user.nickname +          ] +        }) + +      assert ret_conn.status == 200 + +      assert first_user.confirmation_pending == true +      assert second_user.confirmation_pending == true + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{ +                 second_user.nickname +               }" +    end +  end + +  describe "PATCH /resend_confirmation_email" do +    test "it resend emails for two users", %{conn: conn, admin: admin} do +      [first_user, second_user] = insert_pair(:user, confirmation_pending: true) + +      ret_conn = +        patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{ +          nicknames: [ +            first_user.nickname, +            second_user.nickname +          ] +        }) + +      assert ret_conn.status == 200 + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{ +                 second_user.nickname +               }" +    end +  end + +  describe "POST /reports/:id/notes" do +    setup %{conn: conn, admin: admin} do +      [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] +        }) + +      post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{ +        content: "this is disgusting!" +      }) + +      post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{ +        content: "this is disgusting2!" +      }) + +      %{ +        admin_id: admin.id, +        report_id: report_id +      } +    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", %{conn: conn, admin: admin} do +      conn = get(conn, "/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", %{conn: conn, report_id: report_id} do +      assert ReportNote |> Repo.all() |> length() == 2 + +      [note, _] = Repo.all(ReportNote) + +      delete(conn, "/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 + +  describe "/api/pleroma/admin/stats" do +    test "status visibility count", %{conn: conn} do +      admin = insert(:user, is_admin: true) +      user = insert(:user) +      CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) +      CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"}) +      CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"}) + +      response = +        conn +        |> assign(:user, admin) +        |> get("/api/pleroma/admin/stats") +        |> json_response(200) + +      assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} = +               response["status_visibility"] +    end    end  end diff --git a/test/web/admin_api/config_test.exs b/test/web/admin_api/config_test.exs deleted file mode 100644 index 204446b79..000000000 --- a/test/web/admin_api/config_test.exs +++ /dev/null @@ -1,497 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.AdminAPI.ConfigTest do -  use Pleroma.DataCase, async: true -  import Pleroma.Factory -  alias Pleroma.Web.AdminAPI.Config - -  test "get_by_key/1" do -    config = insert(:config) -    insert(:config) - -    assert config == Config.get_by_params(%{group: config.group, key: config.key}) -  end - -  test "create/1" do -    {:ok, config} = Config.create(%{group: "pleroma", key: "some_key", value: "some_value"}) -    assert config == Config.get_by_params(%{group: "pleroma", key: "some_key"}) -  end - -  test "update/1" do -    config = insert(:config) -    {:ok, updated} = Config.update(config, %{value: "some_value"}) -    loaded = Config.get_by_params(%{group: config.group, key: config.key}) -    assert loaded == updated -  end - -  test "update_or_create/1" do -    config = insert(:config) -    key2 = "another_key" - -    params = [ -      %{group: "pleroma", key: key2, value: "another_value"}, -      %{group: config.group, key: config.key, value: "new_value"} -    ] - -    assert Repo.all(Config) |> length() == 1 - -    Enum.each(params, &Config.update_or_create(&1)) - -    assert Repo.all(Config) |> length() == 2 - -    config1 = Config.get_by_params(%{group: config.group, key: config.key}) -    config2 = Config.get_by_params(%{group: "pleroma", key: key2}) - -    assert config1.value == Config.transform("new_value") -    assert config2.value == Config.transform("another_value") -  end - -  test "delete/1" do -    config = insert(:config) -    {:ok, _} = Config.delete(%{key: config.key, group: config.group}) -    refute Config.get_by_params(%{key: config.key, group: config.group}) -  end - -  describe "transform/1" do -    test "string" do -      binary = Config.transform("value as string") -      assert binary == :erlang.term_to_binary("value as string") -      assert Config.from_binary(binary) == "value as string" -    end - -    test "boolean" do -      binary = Config.transform(false) -      assert binary == :erlang.term_to_binary(false) -      assert Config.from_binary(binary) == false -    end - -    test "nil" do -      binary = Config.transform(nil) -      assert binary == :erlang.term_to_binary(nil) -      assert Config.from_binary(binary) == nil -    end - -    test "integer" do -      binary = Config.transform(150) -      assert binary == :erlang.term_to_binary(150) -      assert Config.from_binary(binary) == 150 -    end - -    test "atom" do -      binary = Config.transform(":atom") -      assert binary == :erlang.term_to_binary(:atom) -      assert Config.from_binary(binary) == :atom -    end - -    test "pleroma module" do -      binary = Config.transform("Pleroma.Bookmark") -      assert binary == :erlang.term_to_binary(Pleroma.Bookmark) -      assert Config.from_binary(binary) == Pleroma.Bookmark -    end - -    test "phoenix module" do -      binary = Config.transform("Phoenix.Socket.V1.JSONSerializer") -      assert binary == :erlang.term_to_binary(Phoenix.Socket.V1.JSONSerializer) -      assert Config.from_binary(binary) == Phoenix.Socket.V1.JSONSerializer -    end - -    test "sigil" do -      binary = Config.transform("~r/comp[lL][aA][iI][nN]er/") -      assert binary == :erlang.term_to_binary(~r/comp[lL][aA][iI][nN]er/) -      assert Config.from_binary(binary) == ~r/comp[lL][aA][iI][nN]er/ -    end - -    test "link sigil" do -      binary = Config.transform("~r/https:\/\/example.com/") -      assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/) -      assert Config.from_binary(binary) == ~r/https:\/\/example.com/ -    end - -    test "link sigil with u modifier" do -      binary = Config.transform("~r/https:\/\/example.com/u") -      assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/u) -      assert Config.from_binary(binary) == ~r/https:\/\/example.com/u -    end - -    test "link sigil with i modifier" do -      binary = Config.transform("~r/https:\/\/example.com/i") -      assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/i) -      assert Config.from_binary(binary) == ~r/https:\/\/example.com/i -    end - -    test "link sigil with s modifier" do -      binary = Config.transform("~r/https:\/\/example.com/s") -      assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/s) -      assert Config.from_binary(binary) == ~r/https:\/\/example.com/s -    end - -    test "2 child tuple" do -      binary = Config.transform(%{"tuple" => ["v1", ":v2"]}) -      assert binary == :erlang.term_to_binary({"v1", :v2}) -      assert Config.from_binary(binary) == {"v1", :v2} -    end - -    test "tuple with n childs" do -      binary = -        Config.transform(%{ -          "tuple" => [ -            "v1", -            ":v2", -            "Pleroma.Bookmark", -            150, -            false, -            "Phoenix.Socket.V1.JSONSerializer" -          ] -        }) - -      assert binary == -               :erlang.term_to_binary( -                 {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer} -               ) - -      assert Config.from_binary(binary) == -               {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer} -    end - -    test "tuple with dispatch key" do -      binary = Config.transform(%{"tuple" => [":dispatch", ["{:_, -       [ -         {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, -         {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, -          {Phoenix.Transports.WebSocket, -           {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, -         {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}} -       ]}"]]}) - -      assert binary == -               :erlang.term_to_binary( -                 {:dispatch, -                  [ -                    {:_, -                     [ -                       {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, -                       {"/websocket", Phoenix.Endpoint.CowboyWebSocket, -                        {Phoenix.Transports.WebSocket, -                         {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: "/websocket"]}}}, -                       {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}} -                     ]} -                  ]} -               ) - -      assert Config.from_binary(binary) == -               {:dispatch, -                [ -                  {:_, -                   [ -                     {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, -                     {"/websocket", Phoenix.Endpoint.CowboyWebSocket, -                      {Phoenix.Transports.WebSocket, -                       {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: "/websocket"]}}}, -                     {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}} -                   ]} -                ]} -    end - -    test "map with string key" do -      binary = Config.transform(%{"key" => "value"}) -      assert binary == :erlang.term_to_binary(%{"key" => "value"}) -      assert Config.from_binary(binary) == %{"key" => "value"} -    end - -    test "map with atom key" do -      binary = Config.transform(%{":key" => "value"}) -      assert binary == :erlang.term_to_binary(%{key: "value"}) -      assert Config.from_binary(binary) == %{key: "value"} -    end - -    test "list of strings" do -      binary = Config.transform(["v1", "v2", "v3"]) -      assert binary == :erlang.term_to_binary(["v1", "v2", "v3"]) -      assert Config.from_binary(binary) == ["v1", "v2", "v3"] -    end - -    test "list of modules" do -      binary = Config.transform(["Pleroma.Repo", "Pleroma.Activity"]) -      assert binary == :erlang.term_to_binary([Pleroma.Repo, Pleroma.Activity]) -      assert Config.from_binary(binary) == [Pleroma.Repo, Pleroma.Activity] -    end - -    test "list of atoms" do -      binary = Config.transform([":v1", ":v2", ":v3"]) -      assert binary == :erlang.term_to_binary([:v1, :v2, :v3]) -      assert Config.from_binary(binary) == [:v1, :v2, :v3] -    end - -    test "list of mixed values" do -      binary = -        Config.transform([ -          "v1", -          ":v2", -          "Pleroma.Repo", -          "Phoenix.Socket.V1.JSONSerializer", -          15, -          false -        ]) - -      assert binary == -               :erlang.term_to_binary([ -                 "v1", -                 :v2, -                 Pleroma.Repo, -                 Phoenix.Socket.V1.JSONSerializer, -                 15, -                 false -               ]) - -      assert Config.from_binary(binary) == [ -               "v1", -               :v2, -               Pleroma.Repo, -               Phoenix.Socket.V1.JSONSerializer, -               15, -               false -             ] -    end - -    test "simple keyword" do -      binary = Config.transform([%{"tuple" => [":key", "value"]}]) -      assert binary == :erlang.term_to_binary([{:key, "value"}]) -      assert Config.from_binary(binary) == [{:key, "value"}] -      assert Config.from_binary(binary) == [key: "value"] -    end - -    test "keyword with partial_chain key" do -      binary = -        Config.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}]) - -      assert binary == :erlang.term_to_binary(partial_chain: &:hackney_connect.partial_chain/1) -      assert Config.from_binary(binary) == [partial_chain: &:hackney_connect.partial_chain/1] -    end - -    test "keyword" do -      binary = -        Config.transform([ -          %{"tuple" => [":types", "Pleroma.PostgresTypes"]}, -          %{"tuple" => [":telemetry_event", ["Pleroma.Repo.Instrumenter"]]}, -          %{"tuple" => [":migration_lock", nil]}, -          %{"tuple" => [":key1", 150]}, -          %{"tuple" => [":key2", "string"]} -        ]) - -      assert binary == -               :erlang.term_to_binary( -                 types: Pleroma.PostgresTypes, -                 telemetry_event: [Pleroma.Repo.Instrumenter], -                 migration_lock: nil, -                 key1: 150, -                 key2: "string" -               ) - -      assert Config.from_binary(binary) == [ -               types: Pleroma.PostgresTypes, -               telemetry_event: [Pleroma.Repo.Instrumenter], -               migration_lock: nil, -               key1: 150, -               key2: "string" -             ] -    end - -    test "complex keyword with nested mixed childs" do -      binary = -        Config.transform([ -          %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]}, -          %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]}, -          %{"tuple" => [":link_name", true]}, -          %{"tuple" => [":proxy_remote", false]}, -          %{"tuple" => [":common_map", %{":key" => "value"}]}, -          %{ -            "tuple" => [ -              ":proxy_opts", -              [ -                %{"tuple" => [":redirect_on_failure", false]}, -                %{"tuple" => [":max_body_length", 1_048_576]}, -                %{ -                  "tuple" => [ -                    ":http", -                    [%{"tuple" => [":follow_redirect", true]}, %{"tuple" => [":pool", ":upload"]}] -                  ] -                } -              ] -            ] -          } -        ]) - -      assert binary == -               :erlang.term_to_binary( -                 uploader: Pleroma.Uploaders.Local, -                 filters: [Pleroma.Upload.Filter.Dedupe], -                 link_name: true, -                 proxy_remote: false, -                 common_map: %{key: "value"}, -                 proxy_opts: [ -                   redirect_on_failure: false, -                   max_body_length: 1_048_576, -                   http: [ -                     follow_redirect: true, -                     pool: :upload -                   ] -                 ] -               ) - -      assert Config.from_binary(binary) == -               [ -                 uploader: Pleroma.Uploaders.Local, -                 filters: [Pleroma.Upload.Filter.Dedupe], -                 link_name: true, -                 proxy_remote: false, -                 common_map: %{key: "value"}, -                 proxy_opts: [ -                   redirect_on_failure: false, -                   max_body_length: 1_048_576, -                   http: [ -                     follow_redirect: true, -                     pool: :upload -                   ] -                 ] -               ] -    end - -    test "common keyword" do -      binary = -        Config.transform([ -          %{"tuple" => [":level", ":warn"]}, -          %{"tuple" => [":meta", [":all"]]}, -          %{"tuple" => [":path", ""]}, -          %{"tuple" => [":val", nil]}, -          %{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]} -        ]) - -      assert binary == -               :erlang.term_to_binary( -                 level: :warn, -                 meta: [:all], -                 path: "", -                 val: nil, -                 webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE" -               ) - -      assert Config.from_binary(binary) == [ -               level: :warn, -               meta: [:all], -               path: "", -               val: nil, -               webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE" -             ] -    end - -    test "complex keyword with sigil" do -      binary = -        Config.transform([ -          %{"tuple" => [":federated_timeline_removal", []]}, -          %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]}, -          %{"tuple" => [":replace", []]} -        ]) - -      assert binary == -               :erlang.term_to_binary( -                 federated_timeline_removal: [], -                 reject: [~r/comp[lL][aA][iI][nN]er/], -                 replace: [] -               ) - -      assert Config.from_binary(binary) == -               [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []] -    end - -    test "complex keyword with tuples with more than 2 values" do -      binary = -        Config.transform([ -          %{ -            "tuple" => [ -              ":http", -              [ -                %{ -                  "tuple" => [ -                    ":key1", -                    [ -                      %{ -                        "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: [ -                   key1: [ -                     _: [ -                       {"/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: [ -                 key1: [ -                   {:_, -                    [ -                      {"/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 diff --git a/test/web/admin_api/search_test.exs b/test/web/admin_api/search_test.exs index 501a8d007..e0e3d4153 100644 --- a/test/web/admin_api/search_test.exs +++ b/test/web/admin_api/search_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.AdminAPI.SearchTest do @@ -47,9 +47,9 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do      end      test "it returns active/deactivated users" do -      insert(:user, info: %{deactivated: true}) -      insert(:user, info: %{deactivated: true}) -      insert(:user, info: %{deactivated: false}) +      insert(:user, deactivated: true) +      insert(:user, deactivated: true) +      insert(:user, deactivated: false)        {:ok, _results, active_count} =          Search.user(%{ @@ -70,7 +70,7 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do      test "it returns specific user" do        insert(:user)        insert(:user) -      user = insert(:user, nickname: "bob", local: true, info: %{deactivated: false}) +      user = insert(:user, nickname: "bob", local: true, deactivated: false)        {:ok, _results, total_count} = Search.user(%{query: ""}) @@ -108,7 +108,7 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do      end      test "it returns admin user" do -      admin = insert(:user, info: %{is_admin: true}) +      admin = insert(:user, is_admin: true)        insert(:user)        insert(:user) @@ -119,7 +119,7 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do      end      test "it returns moderator user" do -      moderator = insert(:user, info: %{is_moderator: true}) +      moderator = insert(:user, is_moderator: true)        insert(:user)        insert(:user) diff --git a/test/web/admin_api/views/report_view_test.exs b/test/web/admin_api/views/report_view_test.exs index a00c9c579..5db6629f2 100644 --- a/test/web/admin_api/views/report_view_test.exs +++ b/test/web/admin_api/views/report_view_test.exs @@ -1,10 +1,11 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.AdminAPI.ReportViewTest do    use Pleroma.DataCase    import Pleroma.Factory +  alias Pleroma.Web.AdminAPI.Report    alias Pleroma.Web.AdminAPI.ReportView    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.MastodonAPI.AccountView @@ -20,21 +21,22 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do        content: nil,        actor:          Map.merge( -          AccountView.render("account.json", %{user: user}), +          AccountView.render("show.json", %{user: user}),            Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})          ),        account:          Map.merge( -          AccountView.render("account.json", %{user: other_user}), +          AccountView.render("show.json", %{user: other_user}),            Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})          ),        statuses: [], +      notes: [],        state: "open",        id: activity.id      }      result = -      ReportView.render("show.json", %{report: activity}) +      ReportView.render("show.json", Report.extract_report_info(activity))        |> Map.delete(:created_at)      assert result == expected @@ -48,25 +50,28 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do      {:ok, report_activity} =        CommonAPI.report(user, %{"account_id" => other_user.id, "status_ids" => [activity.id]}) +    other_user = Pleroma.User.get_by_id(other_user.id) +      expected = %{        content: nil,        actor:          Map.merge( -          AccountView.render("account.json", %{user: user}), +          AccountView.render("show.json", %{user: user}),            Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})          ),        account:          Map.merge( -          AccountView.render("account.json", %{user: other_user}), +          AccountView.render("show.json", %{user: other_user}),            Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})          ), -      statuses: [StatusView.render("status.json", %{activity: activity})], +      statuses: [StatusView.render("show.json", %{activity: activity})],        state: "open", +      notes: [],        id: report_activity.id      }      result = -      ReportView.render("show.json", %{report: report_activity}) +      ReportView.render("show.json", Report.extract_report_info(report_activity))        |> Map.delete(:created_at)      assert result == expected @@ -78,7 +83,9 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do      {:ok, activity} = CommonAPI.report(user, %{"account_id" => other_user.id})      {:ok, activity} = CommonAPI.update_report_state(activity.id, "closed") -    assert %{state: "closed"} = ReportView.render("show.json", %{report: activity}) + +    assert %{state: "closed"} = +             ReportView.render("show.json", Report.extract_report_info(activity))    end    test "renders report description" do @@ -92,7 +99,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do        })      assert %{content: "posts are too good for this instance"} = -             ReportView.render("show.json", %{report: activity}) +             ReportView.render("show.json", Report.extract_report_info(activity))    end    test "sanitizes report description" do @@ -109,7 +116,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do      activity = Map.put(activity, :data, data)      refute "<script> alert('hecked :D:D:D:D:D:D:D') </script>" == -             ReportView.render("show.json", %{report: activity})[:content] +             ReportView.render("show.json", Report.extract_report_info(activity))[:content]    end    test "doesn't error out when the user doesn't exists" do @@ -125,6 +132,6 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do      Pleroma.User.delete(other_user)      Pleroma.User.invalidate_cache(other_user) -    assert %{} = ReportView.render("show.json", %{report: activity}) +    assert %{} = ReportView.render("show.json", Report.extract_report_info(activity))    end  end  | 
