diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 51912c6a8..e75542eb4 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -604,6 +604,20 @@ defp handle_incoming_normalised( when type in ["Like", "EmojiReact", "Announce", "Block"] do with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do {:ok, activity} + else + {:error, {:validate, {:error, %Ecto.Changeset{errors: errors}}}} = e -> + # If we never saw the activity being undone, no need to do anything. + # Inspectinging the validation error content is a bit akward, but looking up the Activity + # ahead of time here would be too costly since Activity queries are not cached + # and there's no way atm to pass the retrieved result along along + if errors[:object] == {"can't find object", []} do + {:error, :ignore} + else + e + end + + e -> + e end end diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs index 94df25100..be07a0fe4 100644 --- a/test/pleroma/web/activity_pub/transmogrifier_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs @@ -52,6 +52,25 @@ test "it works for incoming unfollows with an existing follow" do refute User.following?(User.get_cached_by_ap_id(data["actor"]), user) end + test "it ignores Undo activities for unknown objects" do + undo_data = %{ + "id" => "https://remote.com/undo", + "type" => "Undo", + "actor" => "https:://remote.com/users/unknown", + "object" => %{ + "id" => "https://remote.com/undone_activity/unknown", + "type" => "Like" + } + } + + assert {:error, :ignore} == Transmogrifier.handle_incoming(undo_data) + + user = insert(:user, local: false, ap_id: "https://remote.com/users/known") + undo_data = %{undo_data | "actor" => user.ap_id} + + assert {:error, :ignore} == Transmogrifier.handle_incoming(undo_data) + end + test "it accepts Flag activities" do user = insert(:user) other_user = insert(:user)