From 977e711e22dd5171cbff241c7e763de8d34eef26 Mon Sep 17 00:00:00 2001
From: Thibaut Girka <thib@sitedethib.com>
Date: Wed, 2 Oct 2019 13:18:51 +0200
Subject: [PATCH 1/3] Import object from self-Announce whenever possible

---
 lib/pleroma/web/activity_pub/transmogrifier.ex | 25 +++++++++++++++++-
 test/fixtures/mastodon-announce-private.json   | 35 ++++++++++++++++++++++++++
 test/support/http_request_mock.ex              |  8 ++++++
 test/web/activity_pub/transmogrifier_test.exs  | 20 ++++++++++++++-
 4 files changed, 86 insertions(+), 2 deletions(-)
 create mode 100644 test/fixtures/mastodon-announce-private.json

diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 64c470fc8..8f9bf5525 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -580,7 +580,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
       ) do
     with actor <- Containment.get_actor(data),
          {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor),
-         {:ok, object} <- get_obj_helper(object_id),
+         {:ok, object} <- get_embedded_obj_helper(object_id, actor),
          public <- Visibility.is_public?(data),
          {:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false, public) do
       {:ok, activity}
@@ -781,6 +781,29 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     end
   end
 
+  @spec get_embedded_obj_helper(String.t() | Object.t(), User.t()) :: {:ok, Object.t()} | nil
+  def get_embedded_obj_helper(%{"attributedTo" => attributedTo, "id" => object_id} = data, %User{
+        ap_id: ap_id
+      })
+      when attributedTo == ap_id do
+    with {:ok, activity} <-
+           handle_incoming(%{
+             "type" => "Create",
+             "to" => data["to"],
+             "cc" => data["cc"],
+             "actor" => data["attributedTo"],
+             "object" => data
+           }) do
+      {:ok, Object.normalize(activity)}
+    else
+      _ -> get_obj_helper(object_id)
+    end
+  end
+
+  def get_embedded_obj_helper(object_id, _) do
+    get_obj_helper(object_id)
+  end
+
   def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_reply_to) do
     with false <- String.starts_with?(in_reply_to, "http"),
          {:ok, %{data: replied_to_object}} <- get_obj_helper(in_reply_to) do
diff --git a/test/fixtures/mastodon-announce-private.json b/test/fixtures/mastodon-announce-private.json
new file mode 100644
index 000000000..9b868b13d
--- /dev/null
+++ b/test/fixtures/mastodon-announce-private.json
@@ -0,0 +1,35 @@
+{
+  "type": "Announce",
+  "to": [
+    "http://mastodon.example.org/users/admin/followers"
+  ],
+  "published": "2018-02-17T19:39:15Z",
+  "object": {
+    "type": "Note",
+    "id": "http://mastodon.example.org/@admin/99541947525187368",
+    "attributedTo": "http://mastodon.example.org/users/admin",
+    "content": "this is a private toot",
+    "to": [
+      "http://mastodon.example.org/users/admin/followers"
+    ]
+  },
+  "id": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity",
+  "atomUri": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity",
+  "actor": "http://mastodon.example.org/users/admin",
+  "@context": [
+    "https://www.w3.org/ns/activitystreams",
+    "https://w3id.org/security/v1",
+    {
+      "toot": "http://joinmastodon.org/ns#",
+      "sensitive": "as:sensitive",
+      "ostatus": "http://ostatus.org#",
+      "movedTo": "as:movedTo",
+      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+      "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+      "conversation": "ostatus:conversation",
+      "atomUri": "ostatus:atomUri",
+      "Hashtag": "as:Hashtag",
+      "Emoji": "toot:Emoji"
+    }
+  ]
+}
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
index 5506c0626..7a87a2b35 100644
--- a/test/support/http_request_mock.ex
+++ b/test/support/http_request_mock.ex
@@ -349,6 +349,14 @@ defmodule HttpRequestMock do
      }}
   end
 
+  def get("http://mastodon.example.org/@admin/99541947525187368", _, _, _) do
+    {:ok,
+     %Tesla.Env{
+       status: 404,
+       body: ""
+     }}
+  end
+
   def get("https://shitposter.club/notice/7369654", _, _, _) do
     {:ok,
      %Tesla.Env{
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index b995f0224..d25334104 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -442,6 +442,25 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id
     end
 
+    test "it works for incoming announces with an inlined activity" do
+      data =
+        File.read!("test/fixtures/mastodon-announce-private.json")
+        |> Poison.decode!()
+
+      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+      assert data["actor"] == "http://mastodon.example.org/users/admin"
+      assert data["type"] == "Announce"
+
+      assert data["id"] ==
+               "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
+
+      object = Object.normalize(data["object"])
+
+      assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368"
+      assert object.data["content"] == "this is a private toot"
+    end
+
     test "it does not clobber the addressing on announce activities" do
       user = insert(:user)
       {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
@@ -1084,7 +1103,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       {:ok, announce_activity, _} = CommonAPI.repeat(activity.id, user)
 
       {:ok, modified} = Transmogrifier.prepare_outgoing(announce_activity.data)
-      object = modified["object"]
 
       assert modified["object"]["content"] == "hey"
       assert modified["object"]["actor"] == modified["object"]["attributedTo"]

From 791d93ff0ecb304e3278b786e66689521e9ad19d Mon Sep 17 00:00:00 2001
From: Thibaut Girka <thib@sitedethib.com>
Date: Wed, 2 Oct 2019 13:46:06 +0200
Subject: [PATCH 2/3] Make credo happy

---
 lib/pleroma/web/activity_pub/transmogrifier.ex | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 8f9bf5525..449c777dc 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -782,16 +782,16 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   end
 
   @spec get_embedded_obj_helper(String.t() | Object.t(), User.t()) :: {:ok, Object.t()} | nil
-  def get_embedded_obj_helper(%{"attributedTo" => attributedTo, "id" => object_id} = data, %User{
+  def get_embedded_obj_helper(%{"attributedTo" => attributed_to, "id" => object_id} = data, %User{
         ap_id: ap_id
       })
-      when attributedTo == ap_id do
+      when attributed_to == ap_id do
     with {:ok, activity} <-
            handle_incoming(%{
              "type" => "Create",
              "to" => data["to"],
              "cc" => data["cc"],
-             "actor" => data["attributedTo"],
+             "actor" => attributed_to,
              "object" => data
            }) do
       {:ok, Object.normalize(activity)}

From b1ff66dc5f0f3915152314677bcd2379be0dd43b Mon Sep 17 00:00:00 2001
From: Thibaut Girka <thib@sitedethib.com>
Date: Sat, 5 Oct 2019 12:46:06 +0200
Subject: [PATCH 3/3] Add test for handling Announces with inlined object from
 different origin

---
 test/fixtures/bogus-mastodon-announce.json    | 43 +++++++++++++++++++++++++++
 test/support/http_request_mock.ex             |  8 +++++
 test/web/activity_pub/transmogrifier_test.exs |  8 +++++
 3 files changed, 59 insertions(+)
 create mode 100644 test/fixtures/bogus-mastodon-announce.json

diff --git a/test/fixtures/bogus-mastodon-announce.json b/test/fixtures/bogus-mastodon-announce.json
new file mode 100644
index 000000000..0485b80b9
--- /dev/null
+++ b/test/fixtures/bogus-mastodon-announce.json
@@ -0,0 +1,43 @@
+{
+  "type": "Announce",
+  "to": [
+    "https://www.w3.org/ns/activitystreams#Public"
+  ],
+  "published": "2018-02-17T19:39:15Z",
+  "object": {
+    "type": "Note",
+    "id": "https://mastodon.social/users/emelie/statuses/101849165031453404",
+    "attributedTo": "https://mastodon.social/users/emelie",
+    "content": "this is a public toot",
+    "to": [
+      "https://www.w3.org/ns/activitystreams#Public"
+    ],
+    "cc": [
+      "https://mastodon.social/users/emelie",
+      "https://mastodon.social/users/emelie/followers"
+    ]
+  },
+  "id": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity",
+  "cc": [
+    "http://mastodon.example.org/users/admin",
+    "http://mastodon.example.org/users/admin/followers"
+  ],
+  "atomUri": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity",
+  "actor": "http://mastodon.example.org/users/admin",
+  "@context": [
+    "https://www.w3.org/ns/activitystreams",
+    "https://w3id.org/security/v1",
+    {
+      "toot": "http://joinmastodon.org/ns#",
+      "sensitive": "as:sensitive",
+      "ostatus": "http://ostatus.org#",
+      "movedTo": "as:movedTo",
+      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+      "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+      "conversation": "ostatus:conversation",
+      "atomUri": "ostatus:atomUri",
+      "Hashtag": "as:Hashtag",
+      "Emoji": "toot:Emoji"
+    }
+  ]
+}
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
index 7a87a2b35..b825a9307 100644
--- a/test/support/http_request_mock.ex
+++ b/test/support/http_request_mock.ex
@@ -46,6 +46,14 @@ defmodule HttpRequestMock do
      }}
   end
 
+  def get("https://mastodon.social/users/emelie/statuses/101849165031453404", _, _, _) do
+    {:ok,
+     %Tesla.Env{
+       status: 404,
+       body: ""
+     }}
+  end
+
   def get("https://mastodon.social/users/emelie", _, _, _) do
     {:ok,
      %Tesla.Env{
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index d25334104..02f606709 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -461,6 +461,14 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert object.data["content"] == "this is a private toot"
     end
 
+    test "it rejects incoming announces with an inlined activity from another origin" do
+      data =
+        File.read!("test/fixtures/bogus-mastodon-announce.json")
+        |> Poison.decode!()
+
+      assert :error = Transmogrifier.handle_incoming(data)
+    end
+
     test "it does not clobber the addressing on announce activities" do
       user = insert(:user)
       {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})