fix for mastodon forwarded reports
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Tue, 17 Nov 2020 16:57:57 +0000 (19:57 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Thu, 19 Nov 2020 06:53:14 +0000 (09:53 +0300)
lib/pleroma/activity.ex
lib/pleroma/web/activity_pub/utils.ex
test/fixtures/mastodon/application_actor.json [new file with mode: 0644]
test/pleroma/web/activity_pub/activity_pub_controller_test.exs

index 553834da0b786f905f1544fc9feb395c66bc0285..bda5aa616cf09665c9822703835ec8f1172ede71 100644 (file)
@@ -356,4 +356,14 @@ defmodule Pleroma.Activity do
     actor = user_actor(activity)
     activity.id in actor.pinned_activities
   end
+
+  @spec get_by_object_ap_id_with_object(String.t()) :: t() | nil
+  def get_by_object_ap_id_with_object(ap_id) when is_binary(ap_id) do
+    ap_id
+    |> Queries.by_object_id()
+    |> with_preloaded_object()
+    |> Repo.one()
+  end
+
+  def get_by_object_ap_id_with_object(_), do: nil
 end
index 46002bec28b34bb4f5a21d47ea073d7d55187a74..f93909a5008fbc59179c056e74b51bae365a3bf1 100644 (file)
@@ -710,6 +710,22 @@ defmodule Pleroma.Web.ActivityPub.Utils do
     Enum.map(statuses || [], &build_flag_object/1)
   end
 
+  defp build_flag_object(%Activity{} = activity) do
+    activity_actor = User.get_by_ap_id(activity.object.data["actor"])
+
+    %{
+      "type" => "Note",
+      "id" => activity.data["id"],
+      "content" => activity.object.data["content"],
+      "published" => activity.object.data["published"],
+      "actor" =>
+        AccountView.render(
+          "show.json",
+          %{user: activity_actor, skip_visibility_check: true}
+        )
+    }
+  end
+
   defp build_flag_object(act) when is_map(act) or is_binary(act) do
     id =
       case act do
@@ -720,22 +736,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
 
     case Activity.get_by_ap_id_with_object(id) do
       %Activity{} = activity ->
-        activity_actor = User.get_by_ap_id(activity.object.data["actor"])
-
-        %{
-          "type" => "Note",
-          "id" => activity.data["id"],
-          "content" => activity.object.data["content"],
-          "published" => activity.object.data["published"],
-          "actor" =>
-            AccountView.render(
-              "show.json",
-              %{user: activity_actor, skip_visibility_check: true}
-            )
-        }
-
-      _ ->
-        %{"id" => id, "deleted" => true}
+        build_flag_object(activity)
+
+      nil ->
+        if activity = Activity.get_by_object_ap_id_with_object(id) do
+          build_flag_object(activity)
+        else
+          %{"id" => id, "deleted" => true}
+        end
     end
   end
 
diff --git a/test/fixtures/mastodon/application_actor.json b/test/fixtures/mastodon/application_actor.json
new file mode 100644 (file)
index 0000000..2089ea0
--- /dev/null
@@ -0,0 +1,67 @@
+{
+  "@context": [
+    "https://www.w3.org/ns/activitystreams",
+    "https://w3id.org/security/v1",
+    {
+      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+      "toot": "http://joinmastodon.org/ns#",
+      "featured": {
+        "@id": "toot:featured",
+        "@type": "@id"
+      },
+      "alsoKnownAs": {
+        "@id": "as:alsoKnownAs",
+        "@type": "@id"
+      },
+      "movedTo": {
+        "@id": "as:movedTo",
+        "@type": "@id"
+      },
+      "schema": "http://schema.org#",
+      "PropertyValue": "schema:PropertyValue",
+      "value": "schema:value",
+      "IdentityProof": "toot:IdentityProof",
+      "discoverable": "toot:discoverable",
+      "Device": "toot:Device",
+      "Ed25519Signature": "toot:Ed25519Signature",
+      "Ed25519Key": "toot:Ed25519Key",
+      "Curve25519Key": "toot:Curve25519Key",
+      "EncryptedMessage": "toot:EncryptedMessage",
+      "publicKeyBase64": "toot:publicKeyBase64",
+      "deviceId": "toot:deviceId",
+      "claim": {
+        "@type": "@id",
+        "@id": "toot:claim"
+      },
+      "fingerprintKey": {
+        "@type": "@id",
+        "@id": "toot:fingerprintKey"
+      },
+      "identityKey": {
+        "@type": "@id",
+        "@id": "toot:identityKey"
+      },
+      "devices": {
+        "@type": "@id",
+        "@id": "toot:devices"
+      },
+      "messageFranking": "toot:messageFranking",
+      "messageType": "toot:messageType",
+      "cipherText": "toot:cipherText"
+    }
+  ],
+  "id": "https://{{DOMAIN}}/actor",
+  "type": "Application",
+  "inbox": "https://{{DOMAIN}}/actor/inbox",
+  "preferredUsername": "{{DOMAIN}}",
+  "url": "https://{{DOMAIN}}/about/more?instance_actor=true",
+  "manuallyApprovesFollowers": true,
+  "publicKey": {
+    "id": "https://{{DOMAIN}}/actor#main-key",
+    "owner": "https://{{DOMAIN}}/actor",
+    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAA0CA08AMIIBCgKCAQEAyi2T2FFZJgRPY+96YQrn\n6J6eF2P60J+nz+/pRc/acv/Nx+NLxxPyXby0F2s60MV7uALRQbBBnf7oNKCd/T4S\nvbr7UXMCWTdaJBpYubMKWT9uBlaUUkUfqL+WTV+IQnlcKtssQ4+AwrAKAZXza8ws\nZypevOsLHzayyEzztmm1KQC9GCUOITCLf7Q6qEhy8z/HuqLBEC0Own0pD7QsbfcS\no1peuZY7g1E/jJ9HR9GqJccMaR0H28KmJ7tT1Yzlyf5uZMRIdPxsoMR9sGLjR2B8\noegSwaf9SogR3ScP395Tt/9Ud1VVzuhpoS8Uy7jKSs+3CuLJsEGoMrib8VyOwadS\n9wIDAQAB\n-----END PUBLIC KEY-----\n"
+  },
+  "endpoints": {
+    "sharedInbox": "https://{{DOMAIN}}/inbox"
+  }
+}
index f05f7a487c020a5ede29cfc435734cb8853b6e3e..c3d4fcca7de2151529cdb5e128167fd784c40518 100644 (file)
@@ -874,6 +874,65 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
         html_body: ~r/Reported Account:/i
       )
     end
+
+    test "forwarded report from mastodon", %{conn: conn} do
+      admin = insert(:user, is_admin: true)
+      actor = insert(:user, local: false)
+      remote_domain = URI.parse(actor.ap_id).host
+      remote_actor = "https://#{remote_domain}/actor"
+      reported_user = insert(:user)
+
+      note = insert(:note_activity, user: reported_user)
+
+      mock_json_body =
+        "test/fixtures/mastodon/application_actor.json"
+        |> File.read!()
+        |> String.replace("{{DOMAIN}}", remote_domain)
+
+      Tesla.Mock.mock(fn %{url: ^remote_actor} ->
+        %Tesla.Env{
+          status: 200,
+          body: mock_json_body,
+          headers: [{"content-type", "application/activity+json"}]
+        }
+      end)
+
+      data = %{
+        "@context" => "https://www.w3.org/ns/activitystreams",
+        "actor" => remote_actor,
+        "content" => "test report",
+        "id" => "https://#{remote_domain}/e3b12fd1-948c-446e-b93b-a5e67edbe1d8",
+        "nickname" => reported_user.nickname,
+        "object" => [
+          reported_user.ap_id,
+          note.data["object"]
+        ],
+        "type" => "Flag"
+      }
+
+      conn
+      |> assign(:valid_signature, true)
+      |> put_req_header("content-type", "application/activity+json")
+      |> post("/users/#{reported_user.nickname}/inbox", data)
+      |> json_response(200)
+
+      ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
+
+      assert Pleroma.Repo.aggregate(Activity, :count, :id) == 2
+
+      flag_activity = "Flag" |> Pleroma.Activity.Queries.by_type() |> Pleroma.Repo.one()
+      reported_user_ap_id = reported_user.ap_id
+
+      [^reported_user_ap_id, flag_data] = flag_activity.data["object"]
+
+      Enum.each(~w(actor content id published type), &Map.has_key?(flag_data, &1))
+      ObanHelpers.perform_all()
+
+      Swoosh.TestAssertions.assert_email_sent(
+        to: {admin.name, admin.email},
+        html_body: ~r/#{note.data["object"]}/i
+      )
+    end
   end
 
   describe "GET /users/:nickname/outbox" do