From df5e756862a52372a48d60652f594186a4704d71 Mon Sep 17 00:00:00 2001 From: Oneric Date: Wed, 17 Jun 2026 00:00:00 +0000 Subject: [PATCH] Do not notify users unable to access post Known implementations all intend to only tag users who are _also_ allowed to access the post, but this is not guaranteed by ActivityPub semantics, thus recheck against the authorative AP addressing fields. An alternative worth considering is directly using the addressing fields to decide whom to notify ignoring tags. However, MastoAPI later uses tags and thus this may lead to confusing results if a recipient is addressed but not tagged and receives a notification about being mentioned while the API claims they are not mentioned. Addresses the receiving side of: https://akkoma.dev/AkkomaGang/akkoma/issues/1135 (cherry picked from commit 5cff1fac24bb3e6c22160202a7b846f8a62f2477) --- lib/pleroma/web/common_api/utils.ex | 43 ++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 255803c14..64958e1f2 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -435,13 +435,54 @@ defmodule Pleroma.Web.CommonAPI.Utils do %{} end - tagged_mentions = maybe_extract_mentions(object_data) + tagged_mentions = + maybe_extract_mentions(object_data) + |> filter_tags_to_qualified(activity) recipients ++ tagged_mentions end def maybe_notify_mentioned_recipients(recipients, _), do: recipients + # Filter tagged mentions to ensure they can actually access the status + defp filter_tags_to_qualified(tagged_mentions, %Activity{ + recipients: recipients, + data: data, + actor: actor + }) do + recipients = + if recipients && recipients != [], + do: recipients, + else: + (data["to"] || []) ++ (data["cc"] || []) ++ (data["bto"] || []) ++ (data["bcc"] || []) + + cond do + recipients == [] -> + [] + + Pleroma.Constants.as_public() in recipients -> + tagged_mentions + + true -> + author = User.get_cached_by_ap_id(actor) + to_followers = author.follower_address in recipients + + Enum.filter(tagged_mentions, fn tagged -> + cond do + tagged in recipients -> + true + + to_followers -> + tagged_user = User.get_cached_by_ap_id(tagged) + User.following?(tagged_user, author) + + true -> + false + end + end) + end + end + def maybe_notify_followers(recipients, %Activity{data: %{"type" => "Move"}} = activity) do with %User{} = user <- User.get_cached_by_ap_id(activity.actor) do user