X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Factivity_pub%2Ftransmogrifier.ex;h=be7b57f13bb20ad9abe2f2c29b2b131a734cf4cc;hb=fbcc53760e6fcd393513c05a5bd7a4a6a6f3b731;hp=39feae285593400e358116a99fd9ffcd17de8840;hpb=a21baf89d874823137cc49052cfe8da769ac0748;p=akkoma diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 39feae285..be7b57f13 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do A module to handle coding from internal to wire ActivityPub and back. """ alias Pleroma.Activity + alias Pleroma.EarmarkRenderer alias Pleroma.FollowingRelationship alias Pleroma.Object alias Pleroma.Object.Containment @@ -14,7 +15,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ObjectValidator - alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator alias Pleroma.Web.ActivityPub.Pipeline alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Visibility @@ -43,6 +43,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> fix_addressing |> fix_summary |> fix_type(options) + |> fix_content end def fix_summary(%{"summary" => nil} = object) do @@ -357,6 +358,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def fix_type(object, _), do: object + defp fix_content(%{"mediaType" => "text/markdown", "content" => content} = object) + when is_binary(content) do + html_content = + content + |> Earmark.as_html!(%Earmark.Options{renderer: EarmarkRenderer}) + |> Pleroma.HTML.filter_tags() + + Map.merge(object, %{"content" => html_content, "mediaType" => "text/html"}) + end + + defp fix_content(object), do: object + defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do with true <- id =~ "follows", %User{local: true} = follower <- User.get_cached_by_ap_id(follower_id), @@ -643,44 +656,16 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> handle_incoming(options) end - def handle_incoming(%{"type" => "Like"} = data, _options) do - with {_, {:ok, cast_data_sym}} <- - {:casting_data, - data |> LikeValidator.cast_data() |> Ecto.Changeset.apply_action(:insert)}, - cast_data = ObjectValidator.stringify_keys(Map.from_struct(cast_data_sym)), - :ok <- ObjectValidator.fetch_actor_and_object(cast_data), - {_, {:ok, cast_data}} <- {:ensure_context_presence, ensure_context_presence(cast_data)}, - {_, {:ok, cast_data}} <- - {:ensure_recipients_presence, ensure_recipients_presence(cast_data)}, - {_, {:ok, activity, _meta}} <- - {:common_pipeline, Pipeline.common_pipeline(cast_data, local: false)} do + def handle_incoming(%{"type" => type} = data, _options) when type in ["Like", "EmojiReact"] do + with :ok <- ObjectValidator.fetch_actor_and_object(data), + {:ok, activity, _meta} <- + Pipeline.common_pipeline(data, local: false) do {:ok, activity} else e -> {:error, e} end end - def handle_incoming( - %{ - "type" => "EmojiReact", - "object" => object_id, - "actor" => _actor, - "id" => id, - "content" => emoji - } = data, - _options - ) do - 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, activity, _object} <- - ActivityPub.react_with_emoji(actor, object, emoji, activity_id: id, local: false) do - {:ok, activity} - else - _e -> :error - end - end - def handle_incoming( %{"type" => "Announce", "object" => object_id, "actor" => _actor, "id" => id} = data, _options @@ -711,7 +696,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) actor - |> User.upgrade_changeset(new_user_data, true) + |> User.remote_user_changeset(new_user_data) |> User.update_and_set_cache() ActivityPub.update(%{ @@ -729,55 +714,12 @@ 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, - _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 - {: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 - def handle_incoming( - %{ - "type" => "Undo", - "object" => %{"type" => "Announce", "object" => object_id}, - "actor" => _actor, - "id" => id - } = data, + %{"type" => "Delete"} = data, _options ) do - 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, activity, _} <- ActivityPub.unannounce(actor, object, id, false) do + with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do {:ok, activity} - else - _e -> :error end end @@ -803,39 +745,29 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def handle_incoming( %{ "type" => "Undo", - "object" => %{"type" => "EmojiReact", "id" => reaction_activity_id}, - "actor" => _actor, - "id" => id + "object" => %{"type" => type} } = data, _options - ) do - with actor <- Containment.get_actor(data), - {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor), - {:ok, activity, _} <- - ActivityPub.unreact_with_emoji(actor, reaction_activity_id, - activity_id: id, - local: false - ) do + ) + when type in ["Like", "EmojiReact", "Announce", "Block"] do + with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do {:ok, activity} - else - _e -> :error end end + # For Undos that don't have the complete object attached, try to find it in our database. def handle_incoming( %{ "type" => "Undo", - "object" => %{"type" => "Block", "object" => blocked}, - "actor" => blocker, - "id" => id - } = _data, - _options - ) do - with %User{local: true} = blocked <- User.get_cached_by_ap_id(blocked), - {:ok, %User{} = blocker} <- User.get_or_fetch_by_ap_id(blocker), - {:ok, activity} <- ActivityPub.unblock(blocker, blocked, id, false) do - User.unblock(blocker, blocked) - {:ok, activity} + "object" => object + } = activity, + options + ) + when is_binary(object) do + with %Activity{data: data} <- Activity.get_by_ap_id(object) do + activity + |> Map.put("object", data) + |> handle_incoming(options) else _e -> :error end @@ -856,43 +788,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end - def handle_incoming( - %{ - "type" => "Undo", - "object" => %{"type" => "Like", "object" => object_id}, - "actor" => _actor, - "id" => id - } = data, - _options - ) do - 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, activity, _, _} <- ActivityPub.unlike(actor, object, id, false) do - {:ok, activity} - else - _e -> :error - end - end - - # For Undos that don't have the complete object attached, try to find it in our database. - def handle_incoming( - %{ - "type" => "Undo", - "object" => object - } = activity, - options - ) - when is_binary(object) do - with %Activity{data: data} <- Activity.get_by_ap_id(object) do - activity - |> Map.put("object", data) - |> handle_incoming(options) - else - _e -> :error - end - end - def handle_incoming( %{ "type" => "Move", @@ -1160,7 +1055,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def take_emoji_tags(%User{emoji: emoji}) do emoji - |> Enum.flat_map(&Map.to_list/1) + |> Map.to_list() |> Enum.map(&build_emoji_tag/1) end @@ -1189,6 +1084,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do Map.put(object, "conversation", object["context"]) end + def set_sensitive(%{"sensitive" => true} = object) do + object + end + def set_sensitive(object) do tags = object["tag"] || [] Map.put(object, "sensitive", "nsfw" in tags) @@ -1207,18 +1106,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def prepare_attachments(object) do attachments = - (object["attachment"] || []) + object + |> Map.get("attachment", []) |> Enum.map(fn data -> [%{"mediaType" => media_type, "href" => href} | _] = data["url"] - %{"url" => href, "mediaType" => media_type, "name" => data["name"], "type" => "Document"} + + %{ + "url" => href, + "mediaType" => media_type, + "name" => data["name"], + "type" => "Document" + } end) Map.put(object, "attachment", attachments) end def strip_internal_fields(object) do - object - |> Map.drop(Pleroma.Constants.object_internal_fields()) + Map.drop(object, Pleroma.Constants.object_internal_fields()) end defp strip_internal_tags(%{"tag" => tags} = object) do @@ -1254,12 +1159,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def upgrade_user_from_ap_id(ap_id) do with %User{local: false} = user <- User.get_cached_by_ap_id(ap_id), {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id), - already_ap <- User.ap_enabled?(user), - {:ok, user} <- upgrade_user(user, data) do - if not already_ap do - TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id}) - end - + {:ok, user} <- update_user(user, data) do + TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id}) {:ok, user} else %User{} = user -> {:ok, user} @@ -1267,9 +1168,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end - defp upgrade_user(user, data) do + defp update_user(user, data) do user - |> User.upgrade_changeset(data, true) + |> User.remote_user_changeset(data) |> User.update_and_set_cache() end @@ -1280,45 +1181,4 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def maybe_fix_user_url(data), do: data def maybe_fix_user_object(data), do: maybe_fix_user_url(data) - - defp ensure_context_presence(%{"context" => context} = data) when is_binary(context), - do: {:ok, data} - - defp ensure_context_presence(%{"object" => object} = data) when is_binary(object) do - with %{data: %{"context" => context}} when is_binary(context) <- Object.normalize(object) do - {:ok, Map.put(data, "context", context)} - else - _ -> - {:error, :no_context} - end - end - - defp ensure_context_presence(_) do - {:error, :no_context} - end - - defp ensure_recipients_presence(%{"to" => [_ | _], "cc" => [_ | _]} = data), - do: {:ok, data} - - defp ensure_recipients_presence(%{"object" => object} = data) do - case Object.normalize(object) do - %{data: %{"actor" => actor}} -> - data = - data - |> Map.put("to", [actor]) - |> Map.put("cc", data["cc"] || []) - - {:ok, data} - - nil -> - {:error, :no_object} - - _ -> - {:error, :no_actor} - end - end - - defp ensure_recipients_presence(_) do - {:error, :no_object} - end end