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)
This commit is contained in:
Oneric 2026-06-17 00:00:00 +00:00 • committed by Lain Soykaf
commit df5e756862
No known key found for this signature in database

View file

@ -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