Transmogrifier: Handle incoming deletes for non-user objects.
authorlain <lain@soykaf.club>
Thu, 30 Apr 2020 13:26:23 +0000 (15:26 +0200)
committerlain <lain@soykaf.club>
Thu, 30 Apr 2020 13:26:23 +0000 (15:26 +0200)
lib/pleroma/web/activity_pub/object_validator.ex
lib/pleroma/web/activity_pub/side_effects.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
test/web/activity_pub/side_effects_test.exs
test/web/activity_pub/transmogrifier/delete_handling_test.exs

index 016f6e7a2d253bf5fac5aec49b50774edca13f3e..32f606917beb95ac400cd0e2cb5bf32d4717f620 100644 (file)
@@ -11,8 +11,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
 
   alias Pleroma.Object
   alias Pleroma.User
-  alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator
+  alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
+  alias Pleroma.Web.ActivityPub.ObjectValidators.Types
 
   @spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
   def validate(object, meta)
index 5981e754567e0c098340a1c77395b4402c87dc1f..93698a8348617cf1d69e7d21fc13deae92c8ad07 100644 (file)
@@ -28,6 +28,18 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
     result
   end
 
+  # Tasks this handles:
+  # - Delete create activity
+  # - Replace object with Tombstone
+  # - Set up notification
+  def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
+    with %Object{} = deleted_object <- Object.normalize(deleted_object),
+         {:ok, _, _} <- Object.delete(deleted_object) do
+      Notification.create_notifications(object)
+      {:ok, object, meta}
+    end
+  end
+
   # Nothing to do
   def handle(object, meta) do
     {:ok, object, meta}
index 09119137b70ad41a0d84e7ccd2a2488e75962bc4..855aab8d46a2857b135b5a866787a01b306f832d 100644 (file)
@@ -729,36 +729,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     end
   end
 
-  # TODO: We presently assume that any actor on the same origin domain as the object being
-  # deleted has the rights to delete that object.  A better way to validate whether or not
-  # the object should be deleted is to refetch the object URI, which should return either
-  # an error or a tombstone.  This would allow us to verify that a deletion actually took
-  # place.
   def handle_incoming(
-        %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data,
+        %{"type" => "Delete"} = data,
         _options
       ) do
-    object_id = Utils.get_ap_id(object_id)
-
-    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 <- Containment.contain_origin(actor.ap_id, object.data),
-         {:ok, activity} <-
-           ActivityPub.delete(object, local: false, activity_id: id, actor: actor.ap_id) do
+    with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
+         {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
       {:ok, activity}
-    else
-      nil ->
-        case User.get_cached_by_ap_id(object_id) do
-          %User{ap_id: ^actor} = user ->
-            User.delete(user)
-
-          nil ->
-            :error
-        end
-
-      _e ->
-        :error
     end
   end
 
index 0b6b551564723da5d3869fe1be0ca053f68d80c8..eec9488e72709c17c2e4699dfcf496383f20761d 100644 (file)
@@ -5,6 +5,7 @@
 defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
   use Pleroma.DataCase
 
+  alias Pleroma.Activity
   alias Pleroma.Notification
   alias Pleroma.Object
   alias Pleroma.Repo
@@ -15,6 +16,28 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
 
   import Pleroma.Factory
 
+  describe "delete objects" do
+    setup do
+      user = insert(:user)
+      {:ok, post} = CommonAPI.post(user, %{"status" => "hey"})
+      object = Object.normalize(post)
+      {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
+      {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
+      %{user: user, delete: delete, post: post, object: object}
+    end
+
+    test "it handles object deletions", %{delete: delete, post: post, object: object} do
+      # In object deletions, the object is replaced by a tombstone and the
+      # create activity is deleted
+
+      {:ok, _delete, _} = SideEffects.handle(delete)
+
+      object = Object.get_by_id(object.id)
+      assert object.data["type"] == "Tombstone"
+      refute Activity.get_by_id(post.id)
+    end
+  end
+
   describe "like objects" do
     setup do
       poster = insert(:user)
index c15de5a950e0d1a5e2101b231e081109e475592b..64c908a05f8cc96c3df74c18597d790f97137cbe 100644 (file)
@@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do
       |> Map.put("object", object)
 
     assert capture_log(fn ->
-             :error = Transmogrifier.handle_incoming(data)
+             {:error, _} = Transmogrifier.handle_incoming(data)
            end) =~
              "[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, :nxdomain}"
 
@@ -97,9 +97,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do
       |> Poison.decode!()
       |> Map.put("actor", ap_id)
 
-    assert capture_log(fn ->
-             assert :error == Transmogrifier.handle_incoming(data)
-           end) =~ "Object containment failed"
+    assert match?({:error, _}, Transmogrifier.handle_incoming(data))
 
     assert User.get_cached_by_ap_id(ap_id)
   end