diff options
| author | kaniini <ariadne@dereferenced.org> | 2019-08-25 19:39:37 +0000 | 
|---|---|---|
| committer | kaniini <ariadne@dereferenced.org> | 2019-08-25 19:39:37 +0000 | 
| commit | 897bd7a15e6fef5e26cb207e14d36ee06ceb0995 (patch) | |
| tree | 81250e2b7077ae3d36f6536f8701f14475eb94d7 /test | |
| parent | 503139b3431799fed3f280d990fb26c6632f2f25 (diff) | |
| parent | 37dd3867bb0439e4a2717eb780a1837196fcef00 (diff) | |
| download | pleroma-897bd7a15e6fef5e26cb207e14d36ee06ceb0995.tar.gz pleroma-897bd7a15e6fef5e26cb207e14d36ee06ceb0995.zip | |
Merge branch 'feature/moderation-log' into 'develop'
Log admin/moderator actions
See merge request pleroma/pleroma!1582
Diffstat (limited to 'test')
| -rw-r--r-- | test/moderation_log_test.exs | 301 | ||||
| -rw-r--r-- | test/web/admin_api/admin_api_controller_test.exs | 241 | 
2 files changed, 527 insertions, 15 deletions
| diff --git a/test/moderation_log_test.exs b/test/moderation_log_test.exs new file mode 100644 index 000000000..c78708471 --- /dev/null +++ b/test/moderation_log_test.exs @@ -0,0 +1,301 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.ModerationLogTest do +  alias Pleroma.Activity +  alias Pleroma.ModerationLog + +  use Pleroma.DataCase + +  import Pleroma.Factory + +  describe "user moderation" do +    setup do +      admin = insert(:user, info: %{is_admin: true}) +      moderator = insert(:user, info: %{is_moderator: true}) +      subject1 = insert(:user) +      subject2 = insert(:user) + +      [admin: admin, moderator: moderator, subject1: subject1, subject2: subject2] +    end + +    test "logging user deletion by moderator", %{moderator: moderator, subject1: subject1} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          subject: subject1, +          action: "delete" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} deleted user @#{subject1.nickname}" +    end + +    test "logging user creation by moderator", %{ +      moderator: moderator, +      subject1: subject1, +      subject2: subject2 +    } do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          subjects: [subject1, subject2], +          action: "create" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} created users: @#{subject1.nickname}, @#{subject2.nickname}" +    end + +    test "logging user follow by admin", %{admin: admin, subject1: subject1, subject2: subject2} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: admin, +          followed: subject1, +          follower: subject2, +          action: "follow" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{admin.nickname} made @#{subject2.nickname} follow @#{subject1.nickname}" +    end + +    test "logging user unfollow by admin", %{admin: admin, subject1: subject1, subject2: subject2} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: admin, +          followed: subject1, +          follower: subject2, +          action: "unfollow" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{admin.nickname} made @#{subject2.nickname} unfollow @#{subject1.nickname}" +    end + +    test "logging user tagged by admin", %{admin: admin, subject1: subject1, subject2: subject2} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: admin, +          nicknames: [subject1.nickname, subject2.nickname], +          tags: ["foo", "bar"], +          action: "tag" +        }) + +      log = Repo.one(ModerationLog) + +      users = +        [subject1.nickname, subject2.nickname] +        |> Enum.map(&"@#{&1}") +        |> Enum.join(", ") + +      tags = ["foo", "bar"] |> Enum.join(", ") + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{admin.nickname} added tags: #{tags} to users: #{users}" +    end + +    test "logging user untagged by admin", %{admin: admin, subject1: subject1, subject2: subject2} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: admin, +          nicknames: [subject1.nickname, subject2.nickname], +          tags: ["foo", "bar"], +          action: "untag" +        }) + +      log = Repo.one(ModerationLog) + +      users = +        [subject1.nickname, subject2.nickname] +        |> Enum.map(&"@#{&1}") +        |> Enum.join(", ") + +      tags = ["foo", "bar"] |> Enum.join(", ") + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{admin.nickname} removed tags: #{tags} from users: #{users}" +    end + +    test "logging user grant by moderator", %{moderator: moderator, subject1: subject1} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          subject: subject1, +          action: "grant", +          permission: "moderator" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} made @#{subject1.nickname} moderator" +    end + +    test "logging user revoke by moderator", %{moderator: moderator, subject1: subject1} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          subject: subject1, +          action: "revoke", +          permission: "moderator" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} revoked moderator role from @#{subject1.nickname}" +    end + +    test "logging relay follow", %{moderator: moderator} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          action: "relay_follow", +          target: "https://example.org/relay" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} followed relay: https://example.org/relay" +    end + +    test "logging relay unfollow", %{moderator: moderator} do +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          action: "relay_unfollow", +          target: "https://example.org/relay" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} unfollowed relay: https://example.org/relay" +    end + +    test "logging report update", %{moderator: moderator} do +      report = %Activity{ +        id: "9m9I1F4p8ftrTP6QTI", +        data: %{ +          "type" => "Flag", +          "state" => "resolved" +        } +      } + +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          action: "report_update", +          subject: report +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} updated report ##{report.id} with 'resolved' state" +    end + +    test "logging report response", %{moderator: moderator} do +      report = %Activity{ +        id: "9m9I1F4p8ftrTP6QTI", +        data: %{ +          "type" => "Note" +        } +      } + +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          action: "report_response", +          subject: report, +          text: "look at this" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} responded with 'look at this' to report ##{report.id}" +    end + +    test "logging status sensitivity update", %{moderator: moderator} do +      note = insert(:note_activity) + +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          action: "status_update", +          subject: note, +          sensitive: "true", +          visibility: nil +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} updated status ##{note.id}, set sensitive: 'true'" +    end + +    test "logging status visibility update", %{moderator: moderator} do +      note = insert(:note_activity) + +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          action: "status_update", +          subject: note, +          sensitive: nil, +          visibility: "private" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} updated status ##{note.id}, set visibility: 'private'" +    end + +    test "logging status sensitivity & visibility update", %{moderator: moderator} do +      note = insert(:note_activity) + +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          action: "status_update", +          subject: note, +          sensitive: "true", +          visibility: "private" +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} updated status ##{note.id}, set sensitive: 'true', visibility: 'private'" +    end + +    test "logging status deletion", %{moderator: moderator} do +      note = insert(:note_activity) + +      {:ok, _} = +        ModerationLog.insert_log(%{ +          actor: moderator, +          action: "status_delete", +          subject_id: note.id +        }) + +      log = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log) == +               "@#{moderator.nickname} deleted status ##{note.id}" +    end +  end +end diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index ab829d6bd..1afdb6a50 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -7,6 +7,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    alias Pleroma.Activity    alias Pleroma.HTML +  alias Pleroma.ModerationLog +  alias Pleroma.Repo    alias Pleroma.User    alias Pleroma.UserInviteToken    alias Pleroma.Web.CommonAPI @@ -24,6 +26,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          |> 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}" +        assert json_response(conn, 200) == user.nickname      end @@ -51,6 +61,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))        assert response == ["success", "success"] + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} created users: @lain2, @lain"      end      test "Cannot create user with exisiting email" do @@ -218,6 +233,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        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 @@ -241,6 +261,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        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 @@ -261,17 +286,30 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do            }&tags[]=foo&tags[]=bar"          ) -      %{conn: conn, user1: user1, user2: user2, user3: user3} +      %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}      end      test "it appends specified tags to users with specified nicknames", %{        conn: conn, +      admin: admin,        user1: user1,        user2: user2      } do        assert json_response(conn, :no_content)        assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]        assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"] + +      log_entry = Repo.one(ModerationLog) + +      users = +        [user1.nickname, user2.nickname] +        |> Enum.map(&"@#{&1}") +        |> Enum.join(", ") + +      tags = ["foo", "bar"] |> Enum.join(", ") + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} added tags: #{tags} to users: #{users}"      end      test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do @@ -297,17 +335,30 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do            }&tags[]=x&tags[]=z"          ) -      %{conn: conn, user1: user1, user2: user2, user3: user3} +      %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}      end      test "it removes specified tags from users with specified nicknames", %{        conn: conn, +      admin: admin,        user1: user1,        user2: user2      } do        assert json_response(conn, :no_content)        assert User.get_cached_by_id(user1.id).tags == []        assert User.get_cached_by_id(user2.id).tags == ["y"] + +      log_entry = Repo.one(ModerationLog) + +      users = +        [user1.nickname, user2.nickname] +        |> Enum.map(&"@#{&1}") +        |> Enum.join(", ") + +      tags = ["x", "z"] |> Enum.join(", ") + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} removed tags: #{tags} from users: #{users}"      end      test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do @@ -345,6 +396,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "is_admin" => true               } + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} made @#{user.nickname} admin"      end      test "/:right DELETE, can remove from a permission group" do @@ -360,6 +416,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "is_admin" => false               } + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} revoked admin role from @#{user.nickname}"      end    end @@ -372,10 +433,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          |> assign(:user, admin)          |> put_req_header("accept", "application/json") -      %{conn: conn} +      %{conn: conn, admin: admin}      end -    test "deactivates the user", %{conn: conn} do +    test "deactivates the user", %{conn: conn, admin: admin} do        user = insert(:user)        conn = @@ -385,9 +446,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        user = User.get_cached_by_id(user.id)        assert user.info.deactivated == true        assert json_response(conn, :no_content) + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} deactivated user @#{user.nickname}"      end -    test "activates the user", %{conn: conn} do +    test "activates the user", %{conn: conn, admin: admin} do        user = insert(:user, info: %{deactivated: true})        conn = @@ -397,6 +463,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        user = User.get_cached_by_id(user.id)        assert user.info.deactivated == false        assert json_response(conn, :no_content) + +      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 @@ -987,6 +1058,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "avatar" => User.avatar_url(user) |> MediaProxy.url(),                 "display_name" => HTML.strip_tags(user.name || user.nickname)               } + +    log_entry = Repo.one(ModerationLog) + +    assert ModerationLog.get_log_entry_message(log_entry) == +             "@#{admin.nickname} deactivated user @#{user.nickname}"    end    describe "GET /api/pleroma/admin/users/invite_token" do @@ -1172,25 +1248,35 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do            "status_ids" => [activity.id]          }) -      %{conn: assign(conn, :user, admin), id: report_id} +      %{conn: assign(conn, :user, admin), id: report_id, admin: admin}      end -    test "mark report as resolved", %{conn: conn, id: id} do +    test "mark report as resolved", %{conn: conn, id: id, admin: admin} do        response =          conn          |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"})          |> json_response(:ok)        assert response["state"] == "resolved" + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} updated report ##{id} with 'resolved' state"      end -    test "closes report", %{conn: conn, id: id} do +    test "closes report", %{conn: conn, id: id, admin: admin} do        response =          conn          |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"})          |> json_response(:ok)        assert response["state"] == "closed" + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} updated report ##{id} with 'closed' state"      end      test "returns 400 when state is unknown", %{conn: conn, id: id} do @@ -1321,14 +1407,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end +  #    describe "POST /api/pleroma/admin/reports/:id/respond" do      setup %{conn: conn} do        admin = insert(:user, info: %{is_admin: true}) -      %{conn: assign(conn, :user, admin)} +      %{conn: assign(conn, :user, admin), admin: admin}      end -    test "returns created dm", %{conn: conn} do +    test "returns created dm", %{conn: conn, admin: admin} do        [reporter, target_user] = insert_pair(:user)        activity = insert(:note_activity, user: target_user) @@ -1351,6 +1438,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert reporter.nickname in recipients        assert response["content"] == "I will check it out"        assert response["visibility"] == "direct" + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} responded with 'I will check it out' to report ##{ +                 response["id"] +               }"      end      test "returns 400 when status is missing", %{conn: conn} do @@ -1374,10 +1468,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        admin = insert(:user, info: %{is_admin: true})        activity = insert(:note_activity) -      %{conn: assign(conn, :user, admin), id: activity.id} +      %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}      end -    test "toggle sensitive flag", %{conn: conn, id: id} do +    test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do        response =          conn          |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"}) @@ -1385,6 +1479,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert response["sensitive"] +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'" +        response =          conn          |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"}) @@ -1393,7 +1492,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        refute response["sensitive"]      end -    test "change visibility flag", %{conn: conn, id: id} do +    test "change visibility flag", %{conn: conn, id: id, admin: admin} do        response =          conn          |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"}) @@ -1401,6 +1500,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert response["visibility"] == "public" +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} updated status ##{id}, set visibility: 'public'" +        response =          conn          |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"}) @@ -1430,15 +1534,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        admin = insert(:user, info: %{is_admin: true})        activity = insert(:note_activity) -      %{conn: assign(conn, :user, admin), id: activity.id} +      %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}      end -    test "deletes status", %{conn: conn, id: id} do +    test "deletes status", %{conn: conn, id: id, admin: admin} do        conn        |> delete("/api/pleroma/admin/statuses/#{id}")        |> json_response(:ok)        refute Activity.get_by_id(id) + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} deleted status ##{id}"      end      test "returns error when status is not exist", %{conn: conn} do @@ -2139,6 +2248,108 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) |> length() == 5      end    end + +  describe "GET /api/pleroma/admin/moderation_log" do +    setup %{conn: conn} do +      admin = insert(:user, info: %{is_admin: true}) + +      %{conn: assign(conn, :user, admin), admin: admin} +    end + +    test "returns the log", %{conn: conn, admin: admin} do +      Repo.insert(%ModerationLog{ +        data: %{ +          actor: %{ +            "id" => admin.id, +            "nickname" => admin.nickname, +            "type" => "user" +          }, +          action: "relay_follow", +          target: "https://example.org/relay" +        }, +        inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second) +      }) + +      Repo.insert(%ModerationLog{ +        data: %{ +          actor: %{ +            "id" => admin.id, +            "nickname" => admin.nickname, +            "type" => "user" +          }, +          action: "relay_unfollow", +          target: "https://example.org/relay" +        }, +        inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second) +      }) + +      conn = get(conn, "/api/pleroma/admin/moderation_log") + +      response = json_response(conn, 200) +      [first_entry, second_entry] = response + +      assert response |> length() == 2 +      assert first_entry["data"]["action"] == "relay_unfollow" + +      assert first_entry["message"] == +               "@#{admin.nickname} unfollowed relay: https://example.org/relay" + +      assert second_entry["data"]["action"] == "relay_follow" + +      assert second_entry["message"] == +               "@#{admin.nickname} followed relay: https://example.org/relay" +    end + +    test "returns the log with pagination", %{conn: conn, admin: admin} do +      Repo.insert(%ModerationLog{ +        data: %{ +          actor: %{ +            "id" => admin.id, +            "nickname" => admin.nickname, +            "type" => "user" +          }, +          action: "relay_follow", +          target: "https://example.org/relay" +        }, +        inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second) +      }) + +      Repo.insert(%ModerationLog{ +        data: %{ +          actor: %{ +            "id" => admin.id, +            "nickname" => admin.nickname, +            "type" => "user" +          }, +          action: "relay_unfollow", +          target: "https://example.org/relay" +        }, +        inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second) +      }) + +      conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1") + +      response1 = json_response(conn1, 200) +      [first_entry] = response1 + +      assert response1 |> length() == 1 +      assert first_entry["data"]["action"] == "relay_unfollow" + +      assert first_entry["message"] == +               "@#{admin.nickname} unfollowed relay: https://example.org/relay" + +      conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2") + +      response2 = json_response(conn2, 200) +      [second_entry] = response2 + +      assert response2 |> length() == 1 +      assert second_entry["data"]["action"] == "relay_follow" + +      assert second_entry["message"] == +               "@#{admin.nickname} followed relay: https://example.org/relay" +    end +  end  end  # Needed for testing | 
