X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Factivity_pub%2Ftransmogrifier.ex;h=a25bb1978b58de793f6b50a92efd7ad84a49dc1e;hb=1bd1f62af55e01613e6362661b36a19091c87424;hp=b56343beb619f330a195979a246b59517e807c54;hpb=e3b4a3e96b2ffbc6d920155cd41687414045d4d6;p=akkoma diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index b56343beb..a25bb1978 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -7,11 +7,15 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do A module to handle coding from internal to wire ActivityPub and back. """ alias Pleroma.Activity + alias Pleroma.FollowingRelationship alias Pleroma.Object alias Pleroma.Object.Containment alias Pleroma.Repo 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 alias Pleroma.Web.Federator @@ -474,7 +478,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {_, false} <- {:user_locked, User.locked?(followed)}, {_, {:ok, follower}} <- {:follow, User.follow(follower, followed)}, {_, {:ok, _}} <- - {:follow_state_update, Utils.update_follow_state_for_all(activity, "accept")} do + {:follow_state_update, Utils.update_follow_state_for_all(activity, "accept")}, + {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "accept") do ActivityPub.accept(%{ to: [follower.ap_id], actor: followed, @@ -484,6 +489,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do else {:user_blocked, true} -> {:ok, _} = Utils.update_follow_state_for_all(activity, "reject") + {:ok, _relationship} = FollowingRelationship.update(follower, followed, "reject") ActivityPub.reject(%{ to: [follower.ap_id], @@ -494,6 +500,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:follow, {:error, _}} -> {:ok, _} = Utils.update_follow_state_for_all(activity, "reject") + {:ok, _relationship} = FollowingRelationship.update(follower, followed, "reject") ActivityPub.reject(%{ to: [follower.ap_id], @@ -503,6 +510,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do }) {:user_locked, true} -> + {:ok, _relationship} = FollowingRelationship.update(follower, followed, "pending") :noop end @@ -522,7 +530,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, follow_activity} <- get_follow_activity(follow_object, followed), {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"), %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), - {:ok, _follower} = User.follow(follower, followed) do + {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "accept") do ActivityPub.accept(%{ to: follow_activity.data["to"], type: "Accept", @@ -545,6 +553,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, follow_activity} <- get_follow_activity(follow_object, followed), {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"), %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), + {:ok, _relationship} <- FollowingRelationship.update(follower, followed, "reject"), {:ok, activity} <- ActivityPub.reject(%{ to: follow_activity.data["to"], @@ -554,25 +563,27 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do local: false, activity_id: id }) do - User.unfollow(follower, followed) - {:ok, activity} else _e -> :error end end - def handle_incoming( - %{"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, _object} <- ActivityPub.like(actor, object, id, false) do + 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} <- + {:stringify_keys, ObjectValidator.stringify_keys(cast_data_sym |> Map.from_struct())}, + :ok <- ObjectValidator.fetch_actor_and_object(cast_data), + {_, {:ok, cast_data}} <- {:maybe_add_context, maybe_add_context_from_object(cast_data)}, + {_, {:ok, cast_data}} <- + {:maybe_add_recipients, maybe_add_recipients_from_object(cast_data)}, + {_, {:ok, activity, _meta}} <- + {:common_pipeline, Pipeline.common_pipeline(cast_data, local: false)} do {:ok, activity} else - _e -> :error + e -> {:error, e} end end @@ -596,13 +607,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do data, _options ) - when object_type in ["Person", "Application", "Service", "Organization"] do + when object_type in [ + "Person", + "Application", + "Service", + "Organization" + ] do with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) - banner = new_user_data[:info][:banner] - locked = new_user_data[:info][:locked] || false - attachment = get_in(new_user_data, [:info, :source_data, "attachment"]) || [] + locked = new_user_data[:locked] || false + attachment = get_in(new_user_data, [:source_data, "attachment"]) || [] + invisible = new_user_data[:invisible] || false fields = attachment @@ -611,8 +627,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do update_data = new_user_data - |> Map.take([:name, :bio, :avatar]) - |> Map.put(:info, %{banner: banner, locked: locked, fields: fields}) + |> Map.take([:avatar, :banner, :bio, :name]) + |> Map.put(:fields, fields) + |> Map.put(:locked, locked) + |> Map.put(:invisible, invisible) actor |> User.upgrade_changeset(update_data, true) @@ -979,7 +997,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do %{"type" => "Mention", "href" => ap_id, "name" => "@#{nickname}"} end - def take_emoji_tags(%User{info: %{emoji: emoji} = _user_info} = _user) do + def take_emoji_tags(%User{emoji: emoji}) do emoji |> Enum.flat_map(&Map.to_list/1) |> Enum.map(&build_emoji_tag/1) @@ -1054,45 +1072,22 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # we pass a fake user so that the followers collection is stripped away old_follower_address = User.ap_followers(%User{nickname: user.nickname}) - q = - from( - u in User, - where: ^old_follower_address in u.following, - update: [ - set: [ - following: - fragment( - "array_replace(?,?,?)", - u.following, - ^old_follower_address, - ^user.follower_address - ) - ] - ] - ) - - Repo.update_all(q, []) - - maybe_retire_websub(user.ap_id) - - q = - from( - a in Activity, - where: ^old_follower_address in a.recipients, - update: [ - set: [ - recipients: - fragment( - "array_replace(?,?,?)", - a.recipients, - ^old_follower_address, - ^user.follower_address - ) - ] + from( + a in Activity, + where: ^old_follower_address in a.recipients, + update: [ + set: [ + recipients: + fragment( + "array_replace(?,?,?)", + a.recipients, + ^old_follower_address, + ^user.follower_address + ) ] - ) - - Repo.update_all(q, []) + ] + ) + |> Repo.update_all([]) end def upgrade_user_from_ap_id(ap_id) do @@ -1117,19 +1112,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> User.update_and_set_cache() end - def maybe_retire_websub(ap_id) do - # some sanity checks - if is_binary(ap_id) && String.length(ap_id) > 8 do - q = - from( - ws in Pleroma.Web.Websub.WebsubClientSubscription, - where: fragment("? like ?", ws.topic, ^"#{ap_id}%") - ) - - Repo.delete_all(q) - end - end - def maybe_fix_user_url(%{"url" => url} = data) when is_map(url) do Map.put(data, "url", url["href"]) end @@ -1137,4 +1119,47 @@ 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 maybe_add_context_from_object(%{"context" => context} = data) when is_binary(context), + do: {:ok, data} + + defp maybe_add_context_from_object(%{"object" => object} = data) when is_binary(object) do + if object = Object.normalize(object) do + data = + data + |> Map.put("context", object.data["context"]) + + {:ok, data} + else + {:error, "No context on referenced object"} + end + end + + defp maybe_add_context_from_object(_) do + {:error, "No referenced object"} + end + + defp maybe_add_recipients_from_object(%{"object" => object} = data) do + to = data["to"] || [] + cc = data["cc"] || [] + + if to == [] && cc == [] do + if object = Object.normalize(object) do + data = + data + |> Map.put("to", [object.data["actor"]]) + |> Map.put("cc", cc) + + {:ok, data} + else + {:error, "No actor on referenced object"} + end + else + {:ok, data} + end + end + + defp maybe_add_recipients_from_object(_) do + {:error, "No referenced object"} + end end