ensure quote fetching obeys max thread distance (#119)
authorfloatingghost <hannah@coffee-and-dreams.uk>
Tue, 26 Jul 2022 17:28:47 +0000 (17:28 +0000)
committerfloatingghost <hannah@coffee-and-dreams.uk>
Tue, 26 Jul 2022 17:28:47 +0000 (17:28 +0000)
Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/119

lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
test/fixtures/misskey/recursive_quote.json [new file with mode: 0644]
test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs

index a0724ca55427d9f6ca0ef7dd0c4a4dab22b1ce6c..5e377c2946d7faa10eefb875c288fe071bdc5028 100644 (file)
@@ -156,7 +156,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
     |> fix_replies()
     |> fix_source()
     |> fix_misskey_content()
-    |> Transmogrifier.fix_quote_url()
     |> Transmogrifier.fix_attachments()
     |> Transmogrifier.fix_emoji()
     |> Transmogrifier.fix_content_map()
index b6ee24ee613bf479a53f73c1d9096e90f05cfe3b..eea785a5538216f7582be5bd1bf42d66c62eaa90 100644 (file)
@@ -38,6 +38,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     |> fix_attachments()
     |> fix_context()
     |> fix_in_reply_to(options)
+    |> fix_quote_url(options)
     |> fix_emoji()
     |> fix_tag()
     |> fix_content_map()
@@ -167,6 +168,50 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   def fix_in_reply_to(object, _options), do: object
 
+  def fix_quote_url(object, options \\ [])
+
+  def fix_quote_url(%{"quoteUri" => quote_url} = object, options)
+      when not is_nil(quote_url) do
+    depth = (options[:depth] || 0) + 1
+
+    if Federator.allowed_thread_distance?(depth) do
+      with {:ok, quoted_object} <- get_obj_helper(quote_url, options),
+           %Activity{} <- Activity.get_create_by_object_ap_id(quoted_object.data["id"]) do
+        object
+        |> Map.put("quoteUri", quoted_object.data["id"])
+      else
+        e ->
+          Logger.warn("Couldn't fetch #{inspect(quote_url)}, error: #{inspect(e)}")
+          object
+      end
+    else
+      object
+    end
+  end
+
+  # Soapbox
+  def fix_quote_url(%{"quoteUrl" => quote_url} = object, options) do
+    object
+    |> Map.put("quoteUri", quote_url)
+    |> fix_quote_url(options)
+  end
+
+  # Old Fedibird (bug)
+  # https://github.com/fedibird/mastodon/issues/9
+  def fix_quote_url(%{"quoteURL" => quote_url} = object, options) do
+    object
+    |> Map.put("quoteUri", quote_url)
+    |> fix_quote_url(options)
+  end
+
+  def fix_quote_url(%{"_misskey_quote" => quote_url} = object, options) do
+    object
+    |> Map.put("quoteUri", quote_url)
+    |> fix_quote_url(options)
+  end
+
+  def fix_quote_url(object, _), do: object
+
   defp prepare_in_reply_to(in_reply_to) do
     cond do
       is_bitstring(in_reply_to) ->
@@ -424,6 +469,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
       |> strip_internal_fields()
       |> fix_type(fetch_options)
       |> fix_in_reply_to(fetch_options)
+      |> fix_quote_url(fetch_options)
 
     data = Map.put(data, "object", object)
     options = Keyword.put(options, :local, false)
@@ -886,43 +932,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   defp strip_internal_tags(object), do: object
 
-  def fix_quote_url(object, options \\ [])
-
-  def fix_quote_url(%{"quoteUri" => quote_url} = object, options)
-      when not is_nil(quote_url) do
-    with {:ok, quoted_object} <- get_obj_helper(quote_url, options),
-         %Activity{} <- Activity.get_create_by_object_ap_id(quoted_object.data["id"]) do
-      Map.put(object, "quoteUri", quoted_object.data["id"])
-    else
-      e ->
-        Logger.warn("Couldn't fetch #{inspect(quote_url)}, error: #{inspect(e)}")
-        object
-    end
-  end
-
-  # Soapbox
-  def fix_quote_url(%{"quoteUrl" => quote_url} = object, options) do
-    object
-    |> Map.put("quoteUri", quote_url)
-    |> fix_quote_url(options)
-  end
-
-  # Old Fedibird (bug)
-  # https://github.com/fedibird/mastodon/issues/9
-  def fix_quote_url(%{"quoteURL" => quote_url} = object, options) do
-    object
-    |> Map.put("quoteUri", quote_url)
-    |> fix_quote_url(options)
-  end
-
-  def fix_quote_url(%{"_misskey_quote" => quote_url} = object, options) do
-    object
-    |> Map.put("quoteUri", quote_url)
-    |> fix_quote_url(options)
-  end
-
-  def fix_quote_url(object, _), do: object
-
   def perform(:user_upgrade, user) do
     # we pass a fake user so that the followers collection is stripped away
     old_follower_address = User.ap_followers(%User{nickname: user.nickname})
diff --git a/test/fixtures/misskey/recursive_quote.json b/test/fixtures/misskey/recursive_quote.json
new file mode 100644 (file)
index 0000000..f2f6652
--- /dev/null
@@ -0,0 +1,48 @@
+{
+  "@context": [
+    "https://www.w3.org/ns/activitystreams",
+    "https://w3id.org/security/v1",
+    {
+      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+      "sensitive": "as:sensitive",
+      "Hashtag": "as:Hashtag",
+      "quoteUrl": "as:quoteUrl",
+      "toot": "http://joinmastodon.org/ns#",
+      "Emoji": "toot:Emoji",
+      "featured": "toot:featured",
+      "discoverable": "toot:discoverable",
+      "schema": "http://schema.org#",
+      "PropertyValue": "schema:PropertyValue",
+      "value": "schema:value",
+      "misskey": "https://misskey-hub.net/ns#",
+      "_misskey_content": "misskey:_misskey_content",
+      "_misskey_quote": "misskey:_misskey_quote",
+      "_misskey_reaction": "misskey:_misskey_reaction",
+      "_misskey_votes": "misskey:_misskey_votes",
+      "_misskey_talk": "misskey:_misskey_talk",
+      "isCat": "misskey:isCat",
+      "vcard": "http://www.w3.org/2006/vcard/ns#"
+    }
+  ],
+  "id": "https://misskey.io/notes/934gok3482",
+  "type": "Note",
+  "attributedTo": "https://misskey.io/users/93492q0ip0",
+  "summary": null,
+  "content": "<p><span>i quompt u</p>",
+  "_misskey_content": "i quompt u",
+  "source": {
+    "content": "i quompt u",
+    "mediaType": "text/x.misskeymarkdown"
+  },
+  "_misskey_quote": "https://misskey.io/notes/934gok3482",
+  "quoteUrl": "https://misskey.io/notes/934gok3482",
+  "published": "2022-07-25T15:21:48.208Z",
+  "to": [
+    "https://www.w3.org/ns/activitystreams#Public"
+  ],
+  "cc": [],
+  "inReplyTo": null,
+  "attachment": [],
+  "sensitive": false,
+  "tag": []
+}
index 80290a6e315bd312d17fd1b9411a74bb840c8d1e..8b39829168bbd06de32a45dab570aeb5ec0807d6 100644 (file)
@@ -143,61 +143,5 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
         }
       } = ArticleNotePageValidator.cast_and_validate(note)
     end
-
-    test "a misskey quote should work", _ do
-      Tesla.Mock.mock(fn %{
-                           method: :get,
-                           url: "https://example.com/objects/43479e20-c0f8-4f49-bf7f-13fab8234924"
-                         } ->
-        %Tesla.Env{
-          status: 200,
-          body: File.read!("test/fixtures/quoted_status.json"),
-          headers: HttpRequestMock.activitypub_object_headers()
-        }
-      end)
-
-      insert(:user, %{ap_id: "https://misskey.io/users/93492q0ip0"})
-      insert(:user, %{ap_id: "https://example.com/users/user"})
-
-      note =
-        "test/fixtures/misskey/quote.json"
-        |> File.read!()
-        |> Jason.decode!()
-
-      %{
-        valid?: true,
-        changes: %{
-          quoteUri: "https://example.com/objects/43479e20-c0f8-4f49-bf7f-13fab8234924"
-        }
-      } = ArticleNotePageValidator.cast_and_validate(note)
-    end
-
-    test "a fedibird quote should work", _ do
-      Tesla.Mock.mock(fn %{
-                           method: :get,
-                           url: "https://example.com/objects/43479e20-c0f8-4f49-bf7f-13fab8234924"
-                         } ->
-        %Tesla.Env{
-          status: 200,
-          body: File.read!("test/fixtures/quoted_status.json"),
-          headers: HttpRequestMock.activitypub_object_headers()
-        }
-      end)
-
-      insert(:user, %{ap_id: "https://fedibird.com/users/akkoma_ap_integration_tester"})
-      insert(:user, %{ap_id: "https://example.com/users/user"})
-
-      note =
-        "test/fixtures/fedibird/quote.json"
-        |> File.read!()
-        |> Jason.decode!()
-
-      %{
-        valid?: true,
-        changes: %{
-          quoteUri: "https://example.com/objects/43479e20-c0f8-4f49-bf7f-13fab8234924"
-        }
-      } = ArticleNotePageValidator.cast_and_validate(note)
-    end
   end
 end
index 1846b229178fc428fb2972c9e62489a061a2c54a..24df5ea61c5d2f275340bc9bb595b388ce72fcaf 100644 (file)
@@ -707,4 +707,81 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
              }
            ]
   end
+
+  describe "fix_quote_url/1" do
+    test "a misskey quote should work", _ do
+      Tesla.Mock.mock(fn %{
+                           method: :get,
+                           url: "https://example.com/objects/43479e20-c0f8-4f49-bf7f-13fab8234924"
+                         } ->
+        %Tesla.Env{
+          status: 200,
+          body: File.read!("test/fixtures/quoted_status.json"),
+          headers: HttpRequestMock.activitypub_object_headers()
+        }
+      end)
+
+      insert(:user, %{ap_id: "https://misskey.io/users/93492q0ip0"})
+      insert(:user, %{ap_id: "https://example.com/users/user"})
+
+      note =
+        "test/fixtures/misskey/quote.json"
+        |> File.read!()
+        |> Jason.decode!()
+
+      %{"quoteUri" => "https://example.com/objects/43479e20-c0f8-4f49-bf7f-13fab8234924"} =
+        Transmogrifier.fix_quote_url(note)
+    end
+
+    test "a fedibird quote should work", _ do
+      Tesla.Mock.mock(fn %{
+                           method: :get,
+                           url: "https://example.com/objects/43479e20-c0f8-4f49-bf7f-13fab8234924"
+                         } ->
+        %Tesla.Env{
+          status: 200,
+          body: File.read!("test/fixtures/quoted_status.json"),
+          headers: HttpRequestMock.activitypub_object_headers()
+        }
+      end)
+
+      insert(:user, %{ap_id: "https://fedibird.com/users/akkoma_ap_integration_tester"})
+      insert(:user, %{ap_id: "https://example.com/users/user"})
+
+      note =
+        "test/fixtures/fedibird/quote.json"
+        |> File.read!()
+        |> Jason.decode!()
+
+      %{
+        "quoteUri" => "https://example.com/objects/43479e20-c0f8-4f49-bf7f-13fab8234924"
+      } = Transmogrifier.fix_quote_url(note)
+    end
+
+    test "quote fetching should stop after n levels", _ do
+      clear_config([:instance, :federation_incoming_replies_max_depth], 1)
+
+      Tesla.Mock.mock(fn %{
+                           method: :get,
+                           url: "https://misskey.io/notes/934gok3482"
+                         } ->
+        %Tesla.Env{
+          status: 200,
+          body: File.read!("test/fixtures/misskey/recursive_quote.json"),
+          headers: HttpRequestMock.activitypub_object_headers()
+        }
+      end)
+
+      insert(:user, %{ap_id: "https://misskey.io/users/93492q0ip0"})
+
+      note =
+        "test/fixtures/misskey/recursive_quote.json"
+        |> File.read!()
+        |> Jason.decode!()
+
+      %{
+        "quoteUri" => "https://misskey.io/notes/934gok3482"
+      } = Transmogrifier.fix_quote_url(note)
+    end
+  end
 end