Merge branch 'remake-remodel' into develop
[akkoma] / test / web / activity_pub / transmogrifier_test.exs
index 1910de6e0bdb02f022ec3ad52f6d20ac50218d60..83372ec7ef1fe6678961cd34dd1bb0de1054f255 100644 (file)
@@ -1,9 +1,11 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
+  use Oban.Testing, repo: Pleroma.Repo
   use Pleroma.DataCase
+
   alias Pleroma.Activity
   alias Pleroma.Object
   alias Pleroma.Object.Fetcher
@@ -40,7 +42,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
     end
 
     @tag capture_log: true
-    test "it fetches replied-to activities if we don't have them" do
+    test "it fetches reply-to activities if we don't have them" do
       data =
         File.read!("test/fixtures/mastodon-post-activity.json")
         |> Poison.decode!()
@@ -61,7 +63,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
     end
 
-    test "it does not fetch replied-to activities beyond max_replies_depth" do
+    test "it does not fetch reply-to activities beyond max replies depth limit" do
       data =
         File.read!("test/fixtures/mastodon-post-activity.json")
         |> Poison.decode!()
@@ -73,7 +75,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       data = Map.put(data, "object", object)
 
       with_mock Pleroma.Web.Federator,
-        allowed_incoming_reply_depth?: fn _ -> false end do
+        allowed_thread_distance?: fn _ -> false end do
         {:ok, returned_activity} = Transmogrifier.handle_incoming(data)
 
         returned_object = Object.normalize(returned_activity, false)
@@ -342,7 +344,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert data["object"] == activity.data["object"]
     end
 
-    test "it works for incoming misskey likes, turning them into EmojiReactions" do
+    test "it works for incoming misskey likes, turning them into EmojiReacts" do
       user = insert(:user)
       {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
 
@@ -354,13 +356,13 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
 
       assert data["actor"] == data["actor"]
-      assert data["type"] == "EmojiReaction"
+      assert data["type"] == "EmojiReact"
       assert data["id"] == data["id"]
       assert data["object"] == activity.data["object"]
       assert data["content"] == "🍮"
     end
 
-    test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReactions" do
+    test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReacts" do
       user = insert(:user)
       {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
 
@@ -373,7 +375,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
 
       assert data["actor"] == data["actor"]
-      assert data["type"] == "EmojiReaction"
+      assert data["type"] == "EmojiReact"
       assert data["id"] == data["id"]
       assert data["object"] == activity.data["object"]
       assert data["content"] == "⭐"
@@ -391,12 +393,31 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
 
       assert data["actor"] == "http://mastodon.example.org/users/admin"
-      assert data["type"] == "EmojiReaction"
+      assert data["type"] == "EmojiReact"
       assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
       assert data["object"] == activity.data["object"]
       assert data["content"] == "👌"
     end
 
+    test "it reject invalid emoji reactions" do
+      user = insert(:user)
+      {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+      data =
+        File.read!("test/fixtures/emoji-reaction-too-long.json")
+        |> Poison.decode!()
+        |> Map.put("object", activity.data["object"])
+
+      assert :error = Transmogrifier.handle_incoming(data)
+
+      data =
+        File.read!("test/fixtures/emoji-reaction-no-emoji.json")
+        |> Poison.decode!()
+        |> Map.put("object", activity.data["object"])
+
+      assert :error = Transmogrifier.handle_incoming(data)
+    end
+
     test "it works for incoming emoji reaction undos" do
       user = insert(:user)
 
@@ -1331,6 +1352,101 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
     end
   end
 
+  describe "`handle_incoming/2`, Mastodon format `replies` handling" do
+    clear_config([:activitypub, :note_replies_output_limit]) do
+      Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5)
+    end
+
+    clear_config([:instance, :federation_incoming_replies_max_depth])
+
+    setup do
+      data =
+        "test/fixtures/mastodon-post-activity.json"
+        |> File.read!()
+        |> Poison.decode!()
+
+      items = get_in(data, ["object", "replies", "first", "items"])
+      assert length(items) > 0
+
+      %{data: data, items: items}
+    end
+
+    test "schedules background fetching of `replies` items if max thread depth limit allows", %{
+      data: data,
+      items: items
+    } do
+      Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10)
+
+      {:ok, _activity} = Transmogrifier.handle_incoming(data)
+
+      for id <- items do
+        job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1}
+        assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args)
+      end
+    end
+
+    test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows",
+         %{data: data} do
+      Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
+
+      {:ok, _activity} = Transmogrifier.handle_incoming(data)
+
+      assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == []
+    end
+  end
+
+  describe "`handle_incoming/2`, Pleroma format `replies` handling" do
+    clear_config([:activitypub, :note_replies_output_limit]) do
+      Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5)
+    end
+
+    clear_config([:instance, :federation_incoming_replies_max_depth])
+
+    setup do
+      user = insert(:user)
+
+      {:ok, activity} = CommonAPI.post(user, %{"status" => "post1"})
+
+      {:ok, reply1} =
+        CommonAPI.post(user, %{"status" => "reply1", "in_reply_to_status_id" => activity.id})
+
+      {:ok, reply2} =
+        CommonAPI.post(user, %{"status" => "reply2", "in_reply_to_status_id" => activity.id})
+
+      replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end)
+
+      {:ok, federation_output} = Transmogrifier.prepare_outgoing(activity.data)
+
+      Repo.delete(activity.object)
+      Repo.delete(activity)
+
+      %{federation_output: federation_output, replies_uris: replies_uris}
+    end
+
+    test "schedules background fetching of `replies` items if max thread depth limit allows", %{
+      federation_output: federation_output,
+      replies_uris: replies_uris
+    } do
+      Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 1)
+
+      {:ok, _activity} = Transmogrifier.handle_incoming(federation_output)
+
+      for id <- replies_uris do
+        job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1}
+        assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args)
+      end
+    end
+
+    test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows",
+         %{federation_output: federation_output} do
+      Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
+
+      {:ok, _activity} = Transmogrifier.handle_incoming(federation_output)
+
+      assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == []
+    end
+  end
+
   describe "prepare outgoing" do
     test "it inlines private announced objects" do
       user = insert(:user)
@@ -2029,4 +2145,49 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
              }
     end
   end
+
+  describe "set_replies/1" do
+    clear_config([:activitypub, :note_replies_output_limit]) do
+      Pleroma.Config.put([:activitypub, :note_replies_output_limit], 2)
+    end
+
+    test "returns unmodified object if activity doesn't have self-replies" do
+      data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
+      assert Transmogrifier.set_replies(data) == data
+    end
+
+    test "sets `replies` collection with a limited number of self-replies" do
+      [user, another_user] = insert_list(2, :user)
+
+      {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{"status" => "1"})
+
+      {:ok, %{id: id2} = self_reply1} =
+        CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => id1})
+
+      {:ok, self_reply2} =
+        CommonAPI.post(user, %{"status" => "self-reply 2", "in_reply_to_status_id" => id1})
+
+      # Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2
+      {:ok, _} =
+        CommonAPI.post(user, %{"status" => "self-reply 3", "in_reply_to_status_id" => id1})
+
+      {:ok, _} =
+        CommonAPI.post(user, %{
+          "status" => "self-reply to self-reply",
+          "in_reply_to_status_id" => id2
+        })
+
+      {:ok, _} =
+        CommonAPI.post(another_user, %{
+          "status" => "another user's reply",
+          "in_reply_to_status_id" => id1
+        })
+
+      object = Object.normalize(activity)
+      replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end)
+
+      assert %{"type" => "Collection", "items" => ^replies_uris} =
+               Transmogrifier.set_replies(object.data)["replies"]
+    end
+  end
 end