diff options
| author | feld <feld@feld.me> | 2020-10-29 21:06:15 +0000 | 
|---|---|---|
| committer | feld <feld@feld.me> | 2020-10-29 21:06:15 +0000 | 
| commit | 1cce1bd72940db14208a88b98840081d772316a1 (patch) | |
| tree | 5421415bf775270671774edcd51f4be96d0caa64 /test | |
| parent | 6d7dc1241c448aeef7dd36970b5fafc58adb63a7 (diff) | |
| parent | ef627b9391e0dde8adf03c0132fbc2eeac6bdede (diff) | |
| download | pleroma-1cce1bd72940db14208a88b98840081d772316a1.tar.gz pleroma-1cce1bd72940db14208a88b98840081d772316a1.zip | |
Merge branch 'issue/2137-user-filters-admin-fe' into 'develop'
[#2137] admin/users filters
See merge request pleroma/pleroma!3016
Diffstat (limited to 'test')
3 files changed, 996 insertions, 1046 deletions
| diff --git a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs index cba6b43d3..34b26dddf 100644 --- a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs @@ -7,22 +7,17 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    use Oban.Testing, repo: Pleroma.Repo    import ExUnit.CaptureLog -  import Mock    import Pleroma.Factory    import Swoosh.TestAssertions    alias Pleroma.Activity    alias Pleroma.Config -  alias Pleroma.HTML    alias Pleroma.MFA    alias Pleroma.ModerationLog    alias Pleroma.Repo    alias Pleroma.Tests.ObanHelpers    alias Pleroma.User -  alias Pleroma.Web -  alias Pleroma.Web.ActivityPub.Relay    alias Pleroma.Web.CommonAPI -  alias Pleroma.Web.MediaProxy    setup_all do      Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -153,300 +148,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end -  describe "DELETE /api/pleroma/admin/users" do -    test "single user", %{admin: admin, conn: conn} do -      clear_config([:instance, :federating], true) - -      user = -        insert(:user, -          avatar: %{"url" => [%{"href" => "https://someurl"}]}, -          banner: %{"url" => [%{"href" => "https://somebanner"}]}, -          bio: "Hello world!", -          name: "A guy" -        ) - -      # Create some activities to check they got deleted later -      follower = insert(:user) -      {:ok, _} = CommonAPI.post(user, %{status: "test"}) -      {:ok, _, _, _} = CommonAPI.follow(user, follower) -      {:ok, _, _, _} = CommonAPI.follow(follower, user) -      user = Repo.get(User, user.id) -      assert user.note_count == 1 -      assert user.follower_count == 1 -      assert user.following_count == 1 -      refute user.deactivated - -      with_mock Pleroma.Web.Federator, -        publish: fn _ -> nil end, -        perform: fn _, _ -> nil end do -        conn = -          conn -          |> put_req_header("accept", "application/json") -          |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}") - -        ObanHelpers.perform_all() - -        assert User.get_by_nickname(user.nickname).deactivated - -        log_entry = Repo.one(ModerationLog) - -        assert ModerationLog.get_log_entry_message(log_entry) == -                 "@#{admin.nickname} deleted users: @#{user.nickname}" - -        assert json_response(conn, 200) == [user.nickname] - -        user = Repo.get(User, user.id) -        assert user.deactivated - -        assert user.avatar == %{} -        assert user.banner == %{} -        assert user.note_count == 0 -        assert user.follower_count == 0 -        assert user.following_count == 0 -        assert user.bio == "" -        assert user.name == nil - -        assert called(Pleroma.Web.Federator.publish(:_)) -      end -    end - -    test "multiple users", %{admin: admin, conn: conn} do -      user_one = insert(:user) -      user_two = insert(:user) - -      conn = -        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" => [ -            %{ -              "nickname" => "lain", -              "email" => "lain@example.org", -              "password" => "test" -            }, -            %{ -              "nickname" => "lain2", -              "email" => "lain2@example.org", -              "password" => "test" -            } -          ] -        }) - -      response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type")) -      assert response == ["success", "success"] - -      log_entry = Repo.one(ModerationLog) - -      assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == [] -    end - -    test "Cannot create user with existing email", %{conn: conn} do -      user = insert(:user) - -      conn = -        conn -        |> put_req_header("accept", "application/json") -        |> post("/api/pleroma/admin/users", %{ -          "users" => [ -            %{ -              "nickname" => "lain", -              "email" => user.email, -              "password" => "test" -            } -          ] -        }) - -      assert json_response(conn, 409) == [ -               %{ -                 "code" => 409, -                 "data" => %{ -                   "email" => user.email, -                   "nickname" => "lain" -                 }, -                 "error" => "email has already been taken", -                 "type" => "error" -               } -             ] -    end - -    test "Cannot create user with existing nickname", %{conn: conn} do -      user = insert(:user) - -      conn = -        conn -        |> put_req_header("accept", "application/json") -        |> post("/api/pleroma/admin/users", %{ -          "users" => [ -            %{ -              "nickname" => user.nickname, -              "email" => "someuser@plerama.social", -              "password" => "test" -            } -          ] -        }) - -      assert json_response(conn, 409) == [ -               %{ -                 "code" => 409, -                 "data" => %{ -                   "email" => "someuser@plerama.social", -                   "nickname" => user.nickname -                 }, -                 "error" => "nickname has already been taken", -                 "type" => "error" -               } -             ] -    end - -    test "Multiple user creation works in transaction", %{conn: conn} do -      user = insert(:user) - -      conn = -        conn -        |> put_req_header("accept", "application/json") -        |> post("/api/pleroma/admin/users", %{ -          "users" => [ -            %{ -              "nickname" => "newuser", -              "email" => "newuser@pleroma.social", -              "password" => "test" -            }, -            %{ -              "nickname" => "lain", -              "email" => user.email, -              "password" => "test" -            } -          ] -        }) - -      assert json_response(conn, 409) == [ -               %{ -                 "code" => 409, -                 "data" => %{ -                   "email" => user.email, -                   "nickname" => "lain" -                 }, -                 "error" => "email has already been taken", -                 "type" => "error" -               }, -               %{ -                 "code" => 409, -                 "data" => %{ -                   "email" => "newuser@pleroma.social", -                   "nickname" => "newuser" -                 }, -                 "error" => "", -                 "type" => "error" -               } -             ] - -      assert User.get_by_nickname("newuser") === nil -    end -  end - -  describe "/api/pleroma/admin/users/:nickname" do -    test "Show", %{conn: conn} do -      user = insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") - -      expected = %{ -        "deactivated" => false, -        "id" => to_string(user.id), -        "local" => true, -        "nickname" => user.nickname, -        "roles" => %{"admin" => false, "moderator" => false}, -        "tags" => [], -        "avatar" => User.avatar_url(user) |> MediaProxy.url(), -        "display_name" => HTML.strip_tags(user.name || user.nickname), -        "confirmation_pending" => false, -        "approval_pending" => false, -        "url" => user.ap_id, -        "registration_reason" => nil, -        "actor_type" => "Person" -      } - -      assert expected == json_response(conn, 200) -    end - -    test "when the user doesn't exist", %{conn: conn} do -      user = build(:user) - -      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") - -      assert %{"error" => "Not found"} == json_response(conn, 404) -    end -  end - -  describe "/api/pleroma/admin/users/follow" do -    test "allows to force-follow another user", %{admin: admin, conn: conn} do -      user = insert(:user) -      follower = insert(:user) - -      conn -      |> put_req_header("accept", "application/json") -      |> post("/api/pleroma/admin/users/follow", %{ -        "follower" => follower.nickname, -        "followed" => user.nickname -      }) - -      user = User.get_cached_by_id(user.id) -      follower = User.get_cached_by_id(follower.id) - -      assert User.following?(follower, user) - -      log_entry = Repo.one(ModerationLog) - -      assert ModerationLog.get_log_entry_message(log_entry) == -               "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}" -    end -  end - -  describe "/api/pleroma/admin/users/unfollow" do -    test "allows to force-unfollow another user", %{admin: admin, conn: conn} do -      user = insert(:user) -      follower = insert(:user) - -      User.follow(follower, user) - -      conn -      |> put_req_header("accept", "application/json") -      |> post("/api/pleroma/admin/users/unfollow", %{ -        "follower" => follower.nickname, -        "followed" => user.nickname -      }) - -      user = User.get_cached_by_id(user.id) -      follower = User.get_cached_by_id(follower.id) - -      refute User.following?(follower, user) - -      log_entry = Repo.one(ModerationLog) - -      assert ModerationLog.get_log_entry_message(log_entry) == -               "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}" -    end -  end -    describe "PUT /api/pleroma/admin/users/tag" do      setup %{conn: conn} do        user1 = insert(:user, %{tags: ["x"]}) @@ -643,753 +344,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])    end -  describe "GET /api/pleroma/admin/users" do -    test "renders users array for the first page", %{conn: conn, admin: admin} do -      user = insert(:user, local: false, tags: ["foo", "bar"]) -      user2 = insert(:user, approval_pending: true, registration_reason: "I'm a chill dude") - -      conn = get(conn, "/api/pleroma/admin/users?page=1") - -      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, -            "approval_pending" => false, -            "url" => admin.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          }, -          %{ -            "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), -            "confirmation_pending" => false, -            "approval_pending" => false, -            "url" => user.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          }, -          %{ -            "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), -            "confirmation_pending" => false, -            "approval_pending" => true, -            "url" => user2.ap_id, -            "registration_reason" => "I'm a chill dude", -            "actor_type" => "Person" -          } -        ] -        |> Enum.sort_by(& &1["nickname"]) - -      assert json_response(conn, 200) == %{ -               "count" => 3, -               "page_size" => 50, -               "users" => users -             } -    end - -    test "pagination works correctly with service users", %{conn: conn} do -      service1 = User.get_or_create_service_actor_by_ap_id(Web.base_url() <> "/meido", "meido") - -      insert_list(25, :user) - -      assert %{"count" => 26, "page_size" => 10, "users" => users1} = -               conn -               |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"}) -               |> json_response(200) - -      assert Enum.count(users1) == 10 -      assert service1 not in users1 - -      assert %{"count" => 26, "page_size" => 10, "users" => users2} = -               conn -               |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"}) -               |> json_response(200) - -      assert Enum.count(users2) == 10 -      assert service1 not in users2 - -      assert %{"count" => 26, "page_size" => 10, "users" => users3} = -               conn -               |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"}) -               |> json_response(200) - -      assert Enum.count(users3) == 6 -      assert service1 not in users3 -    end - -    test "renders empty array for the second page", %{conn: conn} do -      insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users?page=2") - -      assert json_response(conn, 200) == %{ -               "count" => 2, -               "page_size" => 50, -               "users" => [] -             } -    end - -    test "regular search", %{conn: conn} do -      user = insert(:user, nickname: "bob") - -      conn = get(conn, "/api/pleroma/admin/users?query=bo") - -      assert json_response(conn, 200) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end - -    test "search by domain", %{conn: conn} do -      user = insert(:user, nickname: "nickname@domain.com") -      insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users?query=domain.com") - -      assert json_response(conn, 200) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end - -    test "search by full nickname", %{conn: conn} do -      user = insert(:user, nickname: "nickname@domain.com") -      insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com") - -      assert json_response(conn, 200) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end - -    test "search by display name", %{conn: conn} do -      user = insert(:user, name: "Display name") -      insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users?name=display") - -      assert json_response(conn, 200) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end - -    test "search by email", %{conn: conn} do -      user = insert(:user, email: "email@example.com") -      insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users?email=email@example.com") - -      assert json_response(conn, 200) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end - -    test "regular search with page size", %{conn: conn} do -      user = insert(:user, nickname: "aalice") -      user2 = insert(:user, nickname: "alice") - -      conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1") - -      assert json_response(conn1, 200) == %{ -               "count" => 2, -               "page_size" => 1, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } - -      conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2") - -      assert json_response(conn2, 200) == %{ -               "count" => 2, -               "page_size" => 1, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user2.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end - -    test "only local users" do -      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) - -      conn = -        build_conn() -        |> assign(:user, admin) -        |> assign(:token, token) -        |> get("/api/pleroma/admin/users?query=bo&filters=local") - -      assert json_response(conn, 200) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end - -    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 = get(conn, "/api/pleroma/admin/users?filters=local") - -      users = -        [ -          %{ -            "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), -            "confirmation_pending" => false, -            "approval_pending" => false, -            "url" => user.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          }, -          %{ -            "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, -            "approval_pending" => false, -            "url" => admin.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          }, -          %{ -            "deactivated" => false, -            "id" => old_admin.id, -            "local" => true, -            "nickname" => old_admin.nickname, -            "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), -            "confirmation_pending" => false, -            "approval_pending" => false, -            "url" => old_admin.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          } -        ] -        |> Enum.sort_by(& &1["nickname"]) - -      assert json_response(conn, 200) == %{ -               "count" => 3, -               "page_size" => 50, -               "users" => users -             } -    end - -    test "only unapproved users", %{conn: conn} do -      user = -        insert(:user, -          nickname: "sadboy", -          approval_pending: true, -          registration_reason: "Plz let me in!" -        ) - -      insert(:user, nickname: "happyboy", approval_pending: false) - -      conn = get(conn, "/api/pleroma/admin/users?filters=need_approval") - -      users = -        [ -          %{ -            "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), -            "confirmation_pending" => false, -            "approval_pending" => true, -            "url" => user.ap_id, -            "registration_reason" => "Plz let me in!", -            "actor_type" => "Person" -          } -        ] -        |> Enum.sort_by(& &1["nickname"]) - -      assert json_response(conn, 200) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => users -             } -    end - -    test "load only admins", %{conn: conn, admin: admin} do -      second_admin = insert(:user, is_admin: true) -      insert(:user) -      insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users?filters=is_admin") - -      users = -        [ -          %{ -            "deactivated" => false, -            "id" => admin.id, -            "nickname" => admin.nickname, -            "roles" => %{"admin" => true, "moderator" => false}, -            "local" => admin.local, -            "tags" => [], -            "avatar" => User.avatar_url(admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(admin.name || admin.nickname), -            "confirmation_pending" => false, -            "approval_pending" => false, -            "url" => admin.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          }, -          %{ -            "deactivated" => false, -            "id" => second_admin.id, -            "nickname" => second_admin.nickname, -            "roles" => %{"admin" => true, "moderator" => false}, -            "local" => second_admin.local, -            "tags" => [], -            "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname), -            "confirmation_pending" => false, -            "approval_pending" => false, -            "url" => second_admin.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          } -        ] -        |> Enum.sort_by(& &1["nickname"]) - -      assert json_response(conn, 200) == %{ -               "count" => 2, -               "page_size" => 50, -               "users" => users -             } -    end - -    test "load only moderators", %{conn: conn} do -      moderator = insert(:user, is_moderator: true) -      insert(:user) -      insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator") - -      assert json_response(conn, 200) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => [ -                 %{ -                   "deactivated" => false, -                   "id" => moderator.id, -                   "nickname" => moderator.nickname, -                   "roles" => %{"admin" => false, "moderator" => true}, -                   "local" => moderator.local, -                   "tags" => [], -                   "avatar" => User.avatar_url(moderator) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(moderator.name || moderator.nickname), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => moderator.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end - -    test "load users with tags list", %{conn: conn} do -      user1 = insert(:user, tags: ["first"]) -      user2 = insert(:user, tags: ["second"]) -      insert(:user) -      insert(:user) - -      conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second") - -      users = -        [ -          %{ -            "deactivated" => false, -            "id" => user1.id, -            "nickname" => user1.nickname, -            "roles" => %{"admin" => false, "moderator" => false}, -            "local" => user1.local, -            "tags" => ["first"], -            "avatar" => User.avatar_url(user1) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user1.name || user1.nickname), -            "confirmation_pending" => false, -            "approval_pending" => false, -            "url" => user1.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          }, -          %{ -            "deactivated" => false, -            "id" => user2.id, -            "nickname" => user2.nickname, -            "roles" => %{"admin" => false, "moderator" => false}, -            "local" => user2.local, -            "tags" => ["second"], -            "avatar" => User.avatar_url(user2) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user2.name || user2.nickname), -            "confirmation_pending" => false, -            "approval_pending" => false, -            "url" => user2.ap_id, -            "registration_reason" => nil, -            "actor_type" => "Person" -          } -        ] -        |> Enum.sort_by(& &1["nickname"]) - -      assert json_response(conn, 200) == %{ -               "count" => 2, -               "page_size" => 50, -               "users" => users -             } -    end - -    test "`active` filters out users pending approval", %{token: token} do -      insert(:user, approval_pending: true) -      %{id: user_id} = insert(:user, approval_pending: false) -      %{id: admin_id} = token.user - -      conn = -        build_conn() -        |> assign(:user, token.user) -        |> assign(:token, token) -        |> get("/api/pleroma/admin/users?filters=active") - -      assert %{ -               "count" => 2, -               "page_size" => 50, -               "users" => [ -                 %{"id" => ^admin_id}, -                 %{"id" => ^user_id} -               ] -             } = json_response(conn, 200) -    end - -    test "it works with multiple filters" do -      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, 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) == %{ -               "count" => 1, -               "page_size" => 50, -               "users" => [ -                 %{ -                   "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), -                   "confirmation_pending" => false, -                   "approval_pending" => false, -                   "url" => user.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    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, -                   "approval_pending" => false, -                   "url" => admin.ap_id, -                   "registration_reason" => nil, -                   "actor_type" => "Person" -                 } -               ] -             } -    end -  end - -  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 = -      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/approve", %{admin: admin, conn: conn} do -    user_one = insert(:user, approval_pending: true) -    user_two = insert(:user, approval_pending: true) - -    conn = -      patch( -        conn, -        "/api/pleroma/admin/users/approve", -        %{nicknames: [user_one.nickname, user_two.nickname]} -      ) - -    response = json_response(conn, 200) -    assert Enum.map(response["users"], & &1["approval_pending"]) == [false, false] - -    log_entry = Repo.one(ModerationLog) - -    assert ModerationLog.get_log_entry_message(log_entry) == -             "@#{admin.nickname} approved 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.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), -               "confirmation_pending" => false, -               "approval_pending" => false, -               "url" => user.ap_id, -               "registration_reason" => nil, -               "actor_type" => "Person" -             } - -    log_entry = Repo.one(ModerationLog) - -    assert ModerationLog.get_log_entry_message(log_entry) == -             "@#{admin.nickname} deactivated users: @#{user.nickname}" -  end -    describe "PUT disable_mfa" do      test "returns 200 and disable 2fa", %{conn: conn} do        user = diff --git a/test/pleroma/web/admin_api/controllers/user_controller_test.exs b/test/pleroma/web/admin_api/controllers/user_controller_test.exs new file mode 100644 index 000000000..da26caf25 --- /dev/null +++ b/test/pleroma/web/admin_api/controllers/user_controller_test.exs @@ -0,0 +1,971 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.UserControllerTest do +  use Pleroma.Web.ConnCase +  use Oban.Testing, repo: Pleroma.Repo + +  import Mock +  import Pleroma.Factory + +  alias Pleroma.Config +  alias Pleroma.HTML +  alias Pleroma.ModerationLog +  alias Pleroma.Repo +  alias Pleroma.Tests.ObanHelpers +  alias Pleroma.User +  alias Pleroma.Web +  alias Pleroma.Web.ActivityPub.Relay +  alias Pleroma.Web.CommonAPI +  alias Pleroma.Web.MediaProxy + +  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 + +  test "with valid `admin_token` query parameter, skips OAuth scopes check" do +    clear_config([:admin_token], "password123") + +    user = insert(:user) + +    conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123") + +    assert json_response(conn, 200) +  end + +  describe "with [:auth, :enforce_oauth_admin_scope_usage]," do +    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true) + +    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 +    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false) + +    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 +      clear_config([:instance, :federating], true) + +      user = +        insert(:user, +          avatar: %{"url" => [%{"href" => "https://someurl"}]}, +          banner: %{"url" => [%{"href" => "https://somebanner"}]}, +          bio: "Hello world!", +          name: "A guy" +        ) + +      # Create some activities to check they got deleted later +      follower = insert(:user) +      {:ok, _} = CommonAPI.post(user, %{status: "test"}) +      {:ok, _, _, _} = CommonAPI.follow(user, follower) +      {:ok, _, _, _} = CommonAPI.follow(follower, user) +      user = Repo.get(User, user.id) +      assert user.note_count == 1 +      assert user.follower_count == 1 +      assert user.following_count == 1 +      refute user.deactivated + +      with_mock Pleroma.Web.Federator, +        publish: fn _ -> nil end, +        perform: fn _, _ -> nil end do +        conn = +          conn +          |> put_req_header("accept", "application/json") +          |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}") + +        ObanHelpers.perform_all() + +        assert User.get_by_nickname(user.nickname).deactivated + +        log_entry = Repo.one(ModerationLog) + +        assert ModerationLog.get_log_entry_message(log_entry) == +                 "@#{admin.nickname} deleted users: @#{user.nickname}" + +        assert json_response(conn, 200) == [user.nickname] + +        user = Repo.get(User, user.id) +        assert user.deactivated + +        assert user.avatar == %{} +        assert user.banner == %{} +        assert user.note_count == 0 +        assert user.follower_count == 0 +        assert user.following_count == 0 +        assert user.bio == "" +        assert user.name == nil + +        assert called(Pleroma.Web.Federator.publish(:_)) +      end +    end + +    test "multiple users", %{admin: admin, conn: conn} do +      user_one = insert(:user) +      user_two = insert(:user) + +      conn = +        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" => [ +            %{ +              "nickname" => "lain", +              "email" => "lain@example.org", +              "password" => "test" +            }, +            %{ +              "nickname" => "lain2", +              "email" => "lain2@example.org", +              "password" => "test" +            } +          ] +        }) + +      response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type")) +      assert response == ["success", "success"] + +      log_entry = Repo.one(ModerationLog) + +      assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == [] +    end + +    test "Cannot create user with existing email", %{conn: conn} do +      user = insert(:user) + +      conn = +        conn +        |> put_req_header("accept", "application/json") +        |> post("/api/pleroma/admin/users", %{ +          "users" => [ +            %{ +              "nickname" => "lain", +              "email" => user.email, +              "password" => "test" +            } +          ] +        }) + +      assert json_response(conn, 409) == [ +               %{ +                 "code" => 409, +                 "data" => %{ +                   "email" => user.email, +                   "nickname" => "lain" +                 }, +                 "error" => "email has already been taken", +                 "type" => "error" +               } +             ] +    end + +    test "Cannot create user with existing nickname", %{conn: conn} do +      user = insert(:user) + +      conn = +        conn +        |> put_req_header("accept", "application/json") +        |> post("/api/pleroma/admin/users", %{ +          "users" => [ +            %{ +              "nickname" => user.nickname, +              "email" => "someuser@plerama.social", +              "password" => "test" +            } +          ] +        }) + +      assert json_response(conn, 409) == [ +               %{ +                 "code" => 409, +                 "data" => %{ +                   "email" => "someuser@plerama.social", +                   "nickname" => user.nickname +                 }, +                 "error" => "nickname has already been taken", +                 "type" => "error" +               } +             ] +    end + +    test "Multiple user creation works in transaction", %{conn: conn} do +      user = insert(:user) + +      conn = +        conn +        |> put_req_header("accept", "application/json") +        |> post("/api/pleroma/admin/users", %{ +          "users" => [ +            %{ +              "nickname" => "newuser", +              "email" => "newuser@pleroma.social", +              "password" => "test" +            }, +            %{ +              "nickname" => "lain", +              "email" => user.email, +              "password" => "test" +            } +          ] +        }) + +      assert json_response(conn, 409) == [ +               %{ +                 "code" => 409, +                 "data" => %{ +                   "email" => user.email, +                   "nickname" => "lain" +                 }, +                 "error" => "email has already been taken", +                 "type" => "error" +               }, +               %{ +                 "code" => 409, +                 "data" => %{ +                   "email" => "newuser@pleroma.social", +                   "nickname" => "newuser" +                 }, +                 "error" => "", +                 "type" => "error" +               } +             ] + +      assert User.get_by_nickname("newuser") === nil +    end +  end + +  describe "/api/pleroma/admin/users/:nickname" do +    test "Show", %{conn: conn} do +      user = insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") + +      assert user_response(user) == json_response(conn, 200) +    end + +    test "when the user doesn't exist", %{conn: conn} do +      user = build(:user) + +      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") + +      assert %{"error" => "Not found"} == json_response(conn, 404) +    end +  end + +  describe "/api/pleroma/admin/users/follow" do +    test "allows to force-follow another user", %{admin: admin, conn: conn} do +      user = insert(:user) +      follower = insert(:user) + +      conn +      |> put_req_header("accept", "application/json") +      |> post("/api/pleroma/admin/users/follow", %{ +        "follower" => follower.nickname, +        "followed" => user.nickname +      }) + +      user = User.get_cached_by_id(user.id) +      follower = User.get_cached_by_id(follower.id) + +      assert User.following?(follower, user) + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}" +    end +  end + +  describe "/api/pleroma/admin/users/unfollow" do +    test "allows to force-unfollow another user", %{admin: admin, conn: conn} do +      user = insert(:user) +      follower = insert(:user) + +      User.follow(follower, user) + +      conn +      |> put_req_header("accept", "application/json") +      |> post("/api/pleroma/admin/users/unfollow", %{ +        "follower" => follower.nickname, +        "followed" => user.nickname +      }) + +      user = User.get_cached_by_id(user.id) +      follower = User.get_cached_by_id(follower.id) + +      refute User.following?(follower, user) + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}" +    end +  end + +  describe "GET /api/pleroma/admin/users" do +    test "renders users array for the first page", %{conn: conn, admin: admin} do +      user = insert(:user, local: false, tags: ["foo", "bar"]) +      user2 = insert(:user, approval_pending: true, registration_reason: "I'm a chill dude") + +      conn = get(conn, "/api/pleroma/admin/users?page=1") + +      users = +        [ +          user_response( +            admin, +            %{"roles" => %{"admin" => true, "moderator" => false}} +          ), +          user_response(user, %{"local" => false, "tags" => ["foo", "bar"]}), +          user_response( +            user2, +            %{ +              "local" => true, +              "approval_pending" => true, +              "registration_reason" => "I'm a chill dude", +              "actor_type" => "Person" +            } +          ) +        ] +        |> Enum.sort_by(& &1["nickname"]) + +      assert json_response(conn, 200) == %{ +               "count" => 3, +               "page_size" => 50, +               "users" => users +             } +    end + +    test "pagination works correctly with service users", %{conn: conn} do +      service1 = User.get_or_create_service_actor_by_ap_id(Web.base_url() <> "/meido", "meido") + +      insert_list(25, :user) + +      assert %{"count" => 26, "page_size" => 10, "users" => users1} = +               conn +               |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"}) +               |> json_response(200) + +      assert Enum.count(users1) == 10 +      assert service1 not in users1 + +      assert %{"count" => 26, "page_size" => 10, "users" => users2} = +               conn +               |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"}) +               |> json_response(200) + +      assert Enum.count(users2) == 10 +      assert service1 not in users2 + +      assert %{"count" => 26, "page_size" => 10, "users" => users3} = +               conn +               |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"}) +               |> json_response(200) + +      assert Enum.count(users3) == 6 +      assert service1 not in users3 +    end + +    test "renders empty array for the second page", %{conn: conn} do +      insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users?page=2") + +      assert json_response(conn, 200) == %{ +               "count" => 2, +               "page_size" => 50, +               "users" => [] +             } +    end + +    test "regular search", %{conn: conn} do +      user = insert(:user, nickname: "bob") + +      conn = get(conn, "/api/pleroma/admin/users?query=bo") + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [user_response(user, %{"local" => true})] +             } +    end + +    test "search by domain", %{conn: conn} do +      user = insert(:user, nickname: "nickname@domain.com") +      insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users?query=domain.com") + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [user_response(user)] +             } +    end + +    test "search by full nickname", %{conn: conn} do +      user = insert(:user, nickname: "nickname@domain.com") +      insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com") + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [user_response(user)] +             } +    end + +    test "search by display name", %{conn: conn} do +      user = insert(:user, name: "Display name") +      insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users?name=display") + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [user_response(user)] +             } +    end + +    test "search by email", %{conn: conn} do +      user = insert(:user, email: "email@example.com") +      insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users?email=email@example.com") + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [user_response(user)] +             } +    end + +    test "regular search with page size", %{conn: conn} do +      user = insert(:user, nickname: "aalice") +      user2 = insert(:user, nickname: "alice") + +      conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1") + +      assert json_response(conn1, 200) == %{ +               "count" => 2, +               "page_size" => 1, +               "users" => [user_response(user)] +             } + +      conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2") + +      assert json_response(conn2, 200) == %{ +               "count" => 2, +               "page_size" => 1, +               "users" => [user_response(user2)] +             } +    end + +    test "only local users" do +      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) + +      conn = +        build_conn() +        |> assign(:user, admin) +        |> assign(:token, token) +        |> get("/api/pleroma/admin/users?query=bo&filters=local") + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [user_response(user)] +             } +    end + +    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 = get(conn, "/api/pleroma/admin/users?filters=local") + +      users = +        [ +          user_response(user), +          user_response(admin, %{ +            "roles" => %{"admin" => true, "moderator" => false} +          }), +          user_response(old_admin, %{ +            "deactivated" => false, +            "roles" => %{"admin" => true, "moderator" => false} +          }) +        ] +        |> Enum.sort_by(& &1["nickname"]) + +      assert json_response(conn, 200) == %{ +               "count" => 3, +               "page_size" => 50, +               "users" => users +             } +    end + +    test "only unconfirmed users", %{conn: conn} do +      sad_user = insert(:user, nickname: "sadboy", confirmation_pending: true) +      old_user = insert(:user, nickname: "oldboy", confirmation_pending: true) + +      insert(:user, nickname: "happyboy", approval_pending: false) +      insert(:user, confirmation_pending: false) + +      result = +        conn +        |> get("/api/pleroma/admin/users?filters=unconfirmed") +        |> json_response(200) + +      users = +        Enum.map([old_user, sad_user], fn user -> +          user_response(user, %{ +            "confirmation_pending" => true, +            "approval_pending" => false +          }) +        end) +        |> Enum.sort_by(& &1["nickname"]) + +      assert result == %{"count" => 2, "page_size" => 50, "users" => users} +    end + +    test "only unapproved users", %{conn: conn} do +      user = +        insert(:user, +          nickname: "sadboy", +          approval_pending: true, +          registration_reason: "Plz let me in!" +        ) + +      insert(:user, nickname: "happyboy", approval_pending: false) + +      conn = get(conn, "/api/pleroma/admin/users?filters=need_approval") + +      users = [ +        user_response( +          user, +          %{"approval_pending" => true, "registration_reason" => "Plz let me in!"} +        ) +      ] + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => users +             } +    end + +    test "load only admins", %{conn: conn, admin: admin} do +      second_admin = insert(:user, is_admin: true) +      insert(:user) +      insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users?filters=is_admin") + +      users = +        [ +          user_response(admin, %{ +            "deactivated" => false, +            "roles" => %{"admin" => true, "moderator" => false} +          }), +          user_response(second_admin, %{ +            "deactivated" => false, +            "roles" => %{"admin" => true, "moderator" => false} +          }) +        ] +        |> Enum.sort_by(& &1["nickname"]) + +      assert json_response(conn, 200) == %{ +               "count" => 2, +               "page_size" => 50, +               "users" => users +             } +    end + +    test "load only moderators", %{conn: conn} do +      moderator = insert(:user, is_moderator: true) +      insert(:user) +      insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator") + +      assert json_response(conn, 200) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [ +                 user_response(moderator, %{ +                   "deactivated" => false, +                   "roles" => %{"admin" => false, "moderator" => true} +                 }) +               ] +             } +    end + +    test "load users with actor_type is Person", %{admin: admin, conn: conn} do +      insert(:user, actor_type: "Service") +      insert(:user, actor_type: "Application") + +      user1 = insert(:user) +      user2 = insert(:user) + +      response = +        conn +        |> get(user_path(conn, :list), %{actor_types: ["Person"]}) +        |> json_response(200) + +      users = +        [ +          user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}}), +          user_response(user1), +          user_response(user2) +        ] +        |> Enum.sort_by(& &1["nickname"]) + +      assert response == %{"count" => 3, "page_size" => 50, "users" => users} +    end + +    test "load users with actor_type is Person and Service", %{admin: admin, conn: conn} do +      user_service = insert(:user, actor_type: "Service") +      insert(:user, actor_type: "Application") + +      user1 = insert(:user) +      user2 = insert(:user) + +      response = +        conn +        |> get(user_path(conn, :list), %{actor_types: ["Person", "Service"]}) +        |> json_response(200) + +      users = +        [ +          user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}}), +          user_response(user1), +          user_response(user2), +          user_response(user_service, %{"actor_type" => "Service"}) +        ] +        |> Enum.sort_by(& &1["nickname"]) + +      assert response == %{"count" => 4, "page_size" => 50, "users" => users} +    end + +    test "load users with actor_type is Service", %{conn: conn} do +      user_service = insert(:user, actor_type: "Service") +      insert(:user, actor_type: "Application") +      insert(:user) +      insert(:user) + +      response = +        conn +        |> get(user_path(conn, :list), %{actor_types: ["Service"]}) +        |> json_response(200) + +      users = [user_response(user_service, %{"actor_type" => "Service"})] + +      assert response == %{"count" => 1, "page_size" => 50, "users" => users} +    end + +    test "load users with tags list", %{conn: conn} do +      user1 = insert(:user, tags: ["first"]) +      user2 = insert(:user, tags: ["second"]) +      insert(:user) +      insert(:user) + +      conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second") + +      users = +        [ +          user_response(user1, %{"tags" => ["first"]}), +          user_response(user2, %{"tags" => ["second"]}) +        ] +        |> Enum.sort_by(& &1["nickname"]) + +      assert json_response(conn, 200) == %{ +               "count" => 2, +               "page_size" => 50, +               "users" => users +             } +    end + +    test "`active` filters out users pending approval", %{token: token} do +      insert(:user, approval_pending: true) +      %{id: user_id} = insert(:user, approval_pending: false) +      %{id: admin_id} = token.user + +      conn = +        build_conn() +        |> assign(:user, token.user) +        |> assign(:token, token) +        |> get("/api/pleroma/admin/users?filters=active") + +      assert %{ +               "count" => 2, +               "page_size" => 50, +               "users" => [ +                 %{"id" => ^admin_id}, +                 %{"id" => ^user_id} +               ] +             } = json_response(conn, 200) +    end + +    test "it works with multiple filters" do +      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, 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) == %{ +               "count" => 1, +               "page_size" => 50, +               "users" => [user_response(user)] +             } +    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" => [ +                 user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}}) +               ] +             } +    end +  end + +  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 = +      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/approve", %{admin: admin, conn: conn} do +    user_one = insert(:user, approval_pending: true) +    user_two = insert(:user, approval_pending: true) + +    conn = +      patch( +        conn, +        "/api/pleroma/admin/users/approve", +        %{nicknames: [user_one.nickname, user_two.nickname]} +      ) + +    response = json_response(conn, 200) +    assert Enum.map(response["users"], & &1["approval_pending"]) == [false, false] + +    log_entry = Repo.one(ModerationLog) + +    assert ModerationLog.get_log_entry_message(log_entry) == +             "@#{admin.nickname} approved 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) == +             user_response( +               user, +               %{"deactivated" => !user.deactivated} +             ) + +    log_entry = Repo.one(ModerationLog) + +    assert ModerationLog.get_log_entry_message(log_entry) == +             "@#{admin.nickname} deactivated users: @#{user.nickname}" +  end + +  defp user_response(user, attrs \\ %{}) do +    %{ +      "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), +      "confirmation_pending" => false, +      "approval_pending" => false, +      "url" => user.ap_id, +      "registration_reason" => nil, +      "actor_type" => "Person" +    } +    |> Map.merge(attrs) +  end +end diff --git a/test/pleroma/web/admin_api/search_test.exs b/test/pleroma/web/admin_api/search_test.exs index ceec64f1e..92a116c65 100644 --- a/test/pleroma/web/admin_api/search_test.exs +++ b/test/pleroma/web/admin_api/search_test.exs @@ -143,6 +143,20 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do        assert user2 in users      end +    test "it returns users by actor_types" do +      user_service = insert(:user, actor_type: "Service") +      user_application = insert(:user, actor_type: "Application") +      user1 = insert(:user) +      user2 = insert(:user) + +      {:ok, [^user_service], 1} = Search.user(%{actor_types: ["Service"]}) +      {:ok, [^user_application], 1} = Search.user(%{actor_types: ["Application"]}) +      {:ok, [^user1, ^user2], 2} = Search.user(%{actor_types: ["Person"]}) + +      {:ok, [^user_service, ^user1, ^user2], 3} = +        Search.user(%{actor_types: ["Person", "Service"]}) +    end +      test "it returns user by display name" do        user = insert(:user, name: "Display name")        insert(:user) @@ -178,6 +192,17 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do        assert count == 1      end +    test "it returns unconfirmed user" do +      unconfirmed = insert(:user, confirmation_pending: true) +      insert(:user) +      insert(:user) + +      {:ok, _results, total} = Search.user() +      {:ok, [^unconfirmed], count} = Search.user(%{unconfirmed: true}) +      assert total == 3 +      assert count == 1 +    end +      test "it returns non-discoverable users" do        insert(:user)        insert(:user, is_discoverable: false) | 
