Use delivery info when federating deletes
authorrinpatch <rinpatch@sdf.org>
Fri, 13 Sep 2019 08:36:49 +0000 (11:36 +0300)
committerrinpatch <rinpatch@sdf.org>
Fri, 13 Sep 2019 08:38:17 +0000 (11:38 +0300)
lib/pleroma/delivery.ex
lib/pleroma/user.ex
lib/pleroma/web/activity_pub/publisher.ex
test/web/activity_pub/publisher_test.exs

index f9a9e35cd2ed2570d9e563d3104a3109b94d09cc..2e7c019fabcd11607f262b9d86705a86c617681e 100644 (file)
@@ -46,6 +46,10 @@ defmodule Pleroma.Delivery do
     end
   end
 
+  # A hack because user delete activities have a fake id for whatever reason
+  # TODO: Get rid of this
+  def delete_all_by_object_id("pleroma:fake_object_id"), do: {0, []}
+
   def delete_all_by_object_id(object_id) do
     from(d in Delivery, where: d.object_id == ^object_id)
     |> Repo.delete_all()
index 9614acdaba1c3c94a523a14bd582b761bacec377..785b22643dc0ff33ca3db32b7b7061bf3297721f 100644 (file)
@@ -1627,6 +1627,10 @@ defmodule Pleroma.User do
   def is_internal_user?(%User{local: true, nickname: "internal." <> _}), do: true
   def is_internal_user?(_), do: false
 
+  # A hack because user delete activities have a fake id for whatever reason
+  # TODO: Get rid of this
+  def get_delivered_users_by_object_id("pleroma:fake_object_id"), do: []
+
   def get_delivered_users_by_object_id(object_id) do
     from(u in User,
       inner_join: delivery in assoc(u, :deliveries),
index c97405690b4cb54bf829fe1a2f05c7f0d6c6507d..db64fd2f6373c6f692c5f9c437fe75214ac2af53 100644 (file)
@@ -5,9 +5,11 @@
 defmodule Pleroma.Web.ActivityPub.Publisher do
   alias Pleroma.Activity
   alias Pleroma.Config
+  alias Pleroma.Delivery
   alias Pleroma.HTTP
   alias Pleroma.Instances
   alias Pleroma.User
+  alias Pleroma.Object
   alias Pleroma.Web.ActivityPub.Relay
   alias Pleroma.Web.ActivityPub.Transmogrifier
 
@@ -107,7 +109,18 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
         {:ok, []}
       end
 
-    Pleroma.Web.Salmon.remote_users(actor, activity) ++ followers
+    fetchers =
+      with %Activity{data: %{"type" => "Delete"}} <- activity,
+           %Object{id: object_id} <- Object.normalize(activity),
+           fetchers <- User.get_delivered_users_by_object_id(object_id),
+           _ <- Delivery.delete_all_by_object_id(object_id) do
+        fetchers
+      else
+        _ ->
+          []
+      end
+
+    Pleroma.Web.Salmon.remote_users(actor, activity) ++ followers ++ fetchers
   end
 
   defp get_cc_ap_ids(ap_id, recipients) do
index 36a39c84c9208a0f38e4eb9d86a2940fac6b4fe4..32b7a242c7470472ad579cadd500ccf0a841fca2 100644 (file)
@@ -3,15 +3,17 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.ActivityPub.PublisherTest do
-  use Pleroma.DataCase
+  use Pleroma.Web.ConnCase
 
   import Pleroma.Factory
   import Tesla.Mock
   import Mock
 
   alias Pleroma.Activity
+  alias Pleroma.Object
   alias Pleroma.Instances
   alias Pleroma.Web.ActivityPub.Publisher
+  alias Pleroma.Web.CommonAPI
 
   @as_public "https://www.w3.org/ns/activitystreams#Public"
 
@@ -262,5 +264,69 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
                })
              )
     end
+
+    test_with_mock "publishes a delete activity to peers who signed fetch requests to the create acitvity/object.",
+                   Pleroma.Web.Federator.Publisher,
+                   [:passthrough],
+                   [] do
+      fetcher =
+        insert(:user,
+          local: false,
+          info: %{
+            ap_enabled: true,
+            source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}
+          }
+        )
+
+      another_fetcher =
+        insert(:user,
+          local: false,
+          info: %{
+            ap_enabled: true,
+            source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"}
+          }
+        )
+
+      actor = insert(:user)
+
+      note_activity = insert(:note_activity, user: actor)
+      object = Object.normalize(note_activity)
+
+      activity_path = String.trim_leading(note_activity.data["id"], Pleroma.Web.Endpoint.url())
+      object_path = String.trim_leading(object.data["id"], Pleroma.Web.Endpoint.url())
+
+      build_conn()
+      |> put_req_header("accept", "application/activity+json")
+      |> assign(:user, fetcher)
+      |> get(object_path)
+      |> json_response(200)
+
+      build_conn()
+      |> put_req_header("accept", "application/activity+json")
+      |> assign(:user, another_fetcher)
+      |> get(activity_path)
+      |> json_response(200)
+
+      {:ok, delete} = CommonAPI.delete(note_activity.id, actor)
+
+      res = Publisher.publish(actor, delete)
+      assert res == :ok
+
+      assert called(
+               Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
+                 inbox: "https://domain.com/users/nick1/inbox",
+                 actor: actor,
+                 id: delete.data["id"]
+               })
+             )
+
+      assert called(
+               Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
+                 inbox: "https://domain2.com/users/nick1/inbox",
+                 actor: actor,
+                 id: delete.data["id"]
+               })
+             )
+    end
   end
 end