Merge branch 'embedded-object-federation' into 'develop'
authorHaelwenn <contact+git.pleroma.social@hacktivis.me>
Mon, 27 Jul 2020 21:20:52 +0000 (21:20 +0000)
committerHaelwenn <contact+git.pleroma.social@hacktivis.me>
Mon, 27 Jul 2020 21:20:52 +0000 (21:20 +0000)
Embedded object federation

Closes #1959

See merge request pleroma/pleroma!2794

lib/pleroma/web/activity_pub/object_validator.ex
lib/pleroma/web/activity_pub/pipeline.ex
test/web/activity_pub/pipeline_test.exs
test/web/activity_pub/side_effects_test.exs
test/web/common_api/common_api_test.exs

index df926829c4eb42d36201df45f2c2dc13e7bfe6b5..0dcc7be4dbd778a1eebace51c8848e4f86cb76cd 100644 (file)
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
   the system.
   """
 
+  alias Pleroma.Activity
   alias Pleroma.EctoType.ActivityPub.ObjectValidators
   alias Pleroma.Object
   alias Pleroma.User
@@ -71,6 +72,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
            |> UndoValidator.cast_and_validate()
            |> Ecto.Changeset.apply_action(:insert) do
       object = stringify_keys(object)
+      undone_object = Activity.get_by_ap_id(object["object"])
+
+      meta =
+        meta
+        |> Keyword.put(:object_data, undone_object.data)
+
       {:ok, object, meta}
     end
   end
index 6875c47f67e230e412b1f1f050bbc1e170326256..36e325c373d1463c9ac21f7a51913bf440201617 100644 (file)
@@ -52,6 +52,13 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
       do_not_federate = meta[:do_not_federate] || !Config.get([:instance, :federating])
 
       if !do_not_federate && local do
+        activity =
+          if object = Keyword.get(meta, :object_data) do
+            %{activity | data: Map.put(activity.data, "object", object)}
+          else
+            activity
+          end
+
         Federator.publish(activity)
         {:ok, :federated}
       else
index 8deb64501380858e083e6757bd5d03a2e6391469..f2a231eaf1780e86d9433ccbc846f06eb5ee637f 100644 (file)
@@ -14,6 +14,51 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
       :ok
     end
 
+    test "when given an `object_data` in meta, Federation will receive a the original activity with the `object` field set to this embedded object" do
+      activity = insert(:note_activity)
+      object = %{"id" => "1", "type" => "Love"}
+      meta = [local: true, object_data: object]
+
+      activity_with_object = %{activity | data: Map.put(activity.data, "object", object)}
+
+      with_mocks([
+        {Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
+        {
+          Pleroma.Web.ActivityPub.MRF,
+          [],
+          [filter: fn o -> {:ok, o} end]
+        },
+        {
+          Pleroma.Web.ActivityPub.ActivityPub,
+          [],
+          [persist: fn o, m -> {:ok, o, m} end]
+        },
+        {
+          Pleroma.Web.ActivityPub.SideEffects,
+          [],
+          [
+            handle: fn o, m -> {:ok, o, m} end,
+            handle_after_transaction: fn m -> m end
+          ]
+        },
+        {
+          Pleroma.Web.Federator,
+          [],
+          [publish: fn _o -> :ok end]
+        }
+      ]) do
+        assert {:ok, ^activity, ^meta} =
+                 Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
+
+        assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
+        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity))
+        assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
+        assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
+        refute called(Pleroma.Web.Federator.publish(activity))
+        assert_called(Pleroma.Web.Federator.publish(activity_with_object))
+      end
+    end
+
     test "it goes through validation, filtering, persisting, side effects and federation for local activities" do
       activity = insert(:note_activity)
       meta = [local: true]
index 2649b060ab53f0881a4473670f50e64b83101b12..4a08eb7ee4c36329423e201b7794db9b242e126d 100644 (file)
@@ -312,8 +312,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
       }
     end
 
-    test "deletes the original block", %{block_undo: block_undo, block: block} do
-      {:ok, _block_undo, _} = SideEffects.handle(block_undo)
+    test "deletes the original block", %{
+      block_undo: block_undo,
+      block: block
+    } do
+      {:ok, _block_undo, _meta} = SideEffects.handle(block_undo)
+
       refute Activity.get_by_id(block.id)
     end
 
index 7e11fede3d8247563bfe38a7ae7bbc94a56971f3..313dda21b491006786b01aa2beef24b62e476fc8 100644 (file)
@@ -624,14 +624,27 @@ defmodule Pleroma.Web.CommonAPITest do
       user = insert(:user)
       other_user = insert(:user)
 
-      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
-      {:ok, reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍")
+      clear_config([:instance, :federating], true)
+
+      with_mock Pleroma.Web.Federator,
+        publish: fn _ -> nil end do
+        {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
+        {:ok, reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍")
+
+        {:ok, unreaction} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
 
-      {:ok, unreaction} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
+        assert unreaction.data["type"] == "Undo"
+        assert unreaction.data["object"] == reaction.data["id"]
+        assert unreaction.local
 
-      assert unreaction.data["type"] == "Undo"
-      assert unreaction.data["object"] == reaction.data["id"]
-      assert unreaction.local
+        # On federation, it contains the undone (and deleted) object
+        unreaction_with_object = %{
+          unreaction
+          | data: Map.put(unreaction.data, "object", reaction.data)
+        }
+
+        assert called(Pleroma.Web.Federator.publish(unreaction_with_object))
+      end
     end
 
     test "repeating a status" do