From 1a17cef083ffd210469847c2bb81702e26ed9ec9 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 25 Jun 2022 11:20:46 -0400 Subject: [PATCH] Make outbound transmogrifier aware of edit history --- lib/pleroma/constants.ex | 12 +++ lib/pleroma/web/activity_pub/side_effects.ex | 3 +- .../web/activity_pub/transmogrifier.ex | 52 ++++++++----- .../web/activity_pub/transmogrifier_test.exs | 75 ++++++++++--------- test/pleroma/web/common_api_test.exs | 21 ++++++ 5 files changed, 109 insertions(+), 54 deletions(-) diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index e65dd2f77..7343ef8c3 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -42,6 +42,18 @@ defmodule Pleroma.Constants do ] ) + const(updatable_object_types, + do: [ + "Note", + "Question", + "Audio", + "Video", + "Event", + "Article", + "Page" + ] + ) + const(actor_types, do: [ "Application", diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 72db68ab6..7995e2a4a 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -416,7 +416,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do {:ok, object, meta} end - @updatable_object_types ["Note", "Question"] defp handle_update_object( %{data: %{"type" => "Update", "object" => updated_object}} = object, meta @@ -434,7 +433,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do meta[:object_data] end - if orig_object_data["type"] in @updatable_object_types do + if orig_object_data["type"] in Pleroma.Constants.updatable_object_types() do %{ updated_data: updated_object_data, updated: updated, diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 83ab478ba..b9d853610 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -699,6 +699,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> strip_internal_fields |> strip_internal_tags |> set_type + |> maybe_process_history + end + + defp maybe_process_history(%{"formerRepresentations" => %{"orderedItems" => history}} = object) do + processed_history = + Enum.map( + history, + fn + item when is_map(item) -> prepare_object(item) + item -> item + end + ) + + put_in(object, ["formerRepresentations", "orderedItems"], processed_history) + end + + defp maybe_process_history(object) do + object end # @doc @@ -723,6 +741,21 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, data} end + def prepare_outgoing(%{"type" => "Update", "object" => %{"type" => objtype} = object} = data) + when objtype in Pleroma.Constants.updatable_object_types() do + object = + object + |> prepare_object + + data = + data + |> Map.put("object", object) + |> Map.merge(Utils.make_json_ld_header()) + |> Map.delete("bcc") + + {:ok, data} + end + def prepare_outgoing(%{"type" => "Announce", "actor" => ap_id, "object" => object_id} = data) do object = object_id @@ -911,24 +944,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def strip_internal_fields(object) do - outer = Map.drop(object, Pleroma.Constants.object_internal_fields()) - - case outer do - %{"formerRepresentations" => %{"orderedItems" => list}} when is_list(list) -> - update_in( - outer["formerRepresentations"]["orderedItems"], - &Enum.map( - &1, - fn - item when is_map(item) -> Map.drop(item, Pleroma.Constants.object_internal_fields()) - item -> item - end - ) - ) - - _ -> - outer - end + Map.drop(object, Pleroma.Constants.object_internal_fields()) end defp strip_internal_tags(%{"tag" => tags} = object) do diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs index 3bc0af345..a10708481 100644 --- a/test/pleroma/web/activity_pub/transmogrifier_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs @@ -301,6 +301,28 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert url == "http://localhost:4001/emoji/dino%20walking.gif" end + + test "Updates of Notes are handled" do + user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{status: "everybody do the dinosaur :dinosaur:"}) + {:ok, update} = CommonAPI.update(user, activity, %{status: "mew mew :blank:"}) + + {:ok, prepared} = Transmogrifier.prepare_outgoing(update.data) + + assert %{ + "content" => "mew mew :blank:", + "tag" => [%{"name" => ":blank:", "type" => "Emoji"}], + "formerRepresentations" => %{ + "orderedItems" => [ + %{ + "content" => "everybody do the dinosaur :dinosaur:", + "tag" => [%{"name" => ":dinosaur:", "type" => "Emoji"}] + } + ] + } + } = prepared["object"] + end end describe "user upgrade" do @@ -565,57 +587,42 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do end end - describe "strip_internal_fields/1" do - test "it strips internal fields in formerRepresentations" do + describe "prepare_object/1" do + test "it processes history" do original = %{ "formerRepresentations" => %{ "orderedItems" => [ - %{"generator" => %{}} + %{ + "generator" => %{}, + "emoji" => %{"blobcat" => "http://localhost:4001/emoji/blobcat.png"} + } ] } } - stripped = Transmogrifier.strip_internal_fields(original) + processed = Transmogrifier.prepare_object(original) - refute Map.has_key?( - Enum.at(stripped["formerRepresentations"]["orderedItems"], 0), - "generator" - ) + history_item = Enum.at(processed["formerRepresentations"]["orderedItems"], 0) + + refute Map.has_key?(history_item, "generator") + + assert [%{"name" => ":blobcat:"}] = history_item["tag"] end - test "it strips internal fields in maybe badly-formed formerRepresentations" do - original = %{ - "formerRepresentations" => %{ - "orderedItems" => [ - %{"generator" => %{}}, - "https://example.com/1" - ] - } - } - - stripped = Transmogrifier.strip_internal_fields(original) - - refute Map.has_key?( - Enum.at(stripped["formerRepresentations"]["orderedItems"], 0), - "generator" - ) - - assert Enum.at(stripped["formerRepresentations"]["orderedItems"], 1) == - "https://example.com/1" - end - - test "it ignores if formerRepresentations does not look like an OrderedCollection" do + test "it works when there is no or bad history" do original = %{ "formerRepresentations" => %{ "items" => [ - %{"generator" => %{}} + %{ + "generator" => %{}, + "emoji" => %{"blobcat" => "http://localhost:4001/emoji/blobcat.png"} + } ] } } - stripped = Transmogrifier.strip_internal_fields(original) - - assert Map.has_key?(Enum.at(stripped["formerRepresentations"]["items"], 0), "generator") + processed = Transmogrifier.prepare_object(original) + assert processed["formerRepresentations"] == original["formerRepresentations"] end end end diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index 42fdd753c..242d71756 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -1356,5 +1356,26 @@ defmodule Pleroma.Web.CommonAPITest do assert updated_object.data["content"] == "updated 2 :#{emoji2}:" assert %{^emoji2 => _} = updated_object.data["emoji"] end + + test "updates a post with emoji and federate properly" do + [{emoji1, _}, {emoji2, _} | _] = Pleroma.Emoji.get_all() + + user = insert(:user) + + {:ok, activity} = + CommonAPI.post(user, %{status: "foo1", spoiler_text: "title 1 :#{emoji1}:"}) + + clear_config([:instance, :federating], true) + + with_mock Pleroma.Web.Federator, + publish: fn p -> nil end do + {:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2 :#{emoji2}:"}) + + assert updated.data["object"]["content"] == "updated 2 :#{emoji2}:" + assert %{^emoji2 => _} = updated.data["object"]["emoji"] + + assert called(Pleroma.Web.Federator.publish(updated)) + end + end end end