Merge pull request 'Notifications: do not notify tagged users who cannot see the post' (#8022) from lambadalambda/pleroma:fix/mention-notify-access into develop

Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8022
This commit is contained in:
lain 2026-10-27 12:38:20 +00:00
commit a4ce628a50
3 changed files with 143 additions and 1 deletions

View file

@ -0,0 +1 @@
Do not notify tagged users who cannot see the post

View file

@ -435,13 +435,56 @@ 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 = match?(%User{}, author) and author.follower_address in recipients
Enum.filter(tagged_mentions, fn tagged ->
cond do
tagged in recipients ->
true
to_followers ->
case User.get_cached_by_ap_id(tagged) do
%User{} = tagged_user -> User.following?(tagged_user, author)
_ -> false
end
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

View file

@ -7,6 +7,8 @@ defmodule Pleroma.NotificationTest do
import Pleroma.Factory
require Pleroma.Constants
alias Pleroma.FollowingRelationship
alias Pleroma.Notification
alias Pleroma.Object
@ -628,6 +630,102 @@ defmodule Pleroma.NotificationTest do
assert other_user in enabled_receivers
end
defp incoming_note_tagging(author, to, tagged_ap_ids) do
tags = Enum.map(tagged_ap_ids, &%{"type" => "Mention", "href" => &1, "name" => &1})
{:ok, activity} =
Transmogrifier.handle_incoming(%{
"@context" => "https://www.w3.org/ns/activitystreams",
"type" => "Create",
"to" => to,
"actor" => author.ap_id,
"object" => %{
"type" => "Note",
"id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
"to" => to,
"content" => "tagged",
"tag" => tags,
"attributedTo" => author.ap_id
}
})
activity
end
defp notified_ap_ids(activity),
do: activity |> Notification.get_notified_from_activity() |> Enum.map(& &1.ap_id)
test "it does not notify tagged users who cannot see a followers-only post" do
author = insert(:user)
tagged = insert(:user)
activity = incoming_note_tagging(author, [author.follower_address], [tagged.ap_id])
refute tagged.ap_id in notified_ap_ids(activity)
end
test "it notifies tagged followers of a followers-only post" do
author = insert(:user)
tagged = insert(:user)
{:ok, _, _} = Pleroma.User.follow(tagged, author)
activity = incoming_note_tagging(author, [author.follower_address], [tagged.ap_id])
assert tagged.ap_id in notified_ap_ids(activity)
end
test "it does not notify tagged users who are not addressed by a direct message" do
author = insert(:user)
addressed = insert(:user)
tagged = insert(:user)
activity = incoming_note_tagging(author, [addressed.ap_id], [tagged.ap_id])
receivers = notified_ap_ids(activity)
assert addressed.ap_id in receivers
refute tagged.ap_id in receivers
end
test "it notifies tagged users of a public post even if they are not addressed" do
author = insert(:user)
tagged = insert(:user)
activity =
incoming_note_tagging(author, [Pleroma.Constants.as_public()], [tagged.ap_id])
assert tagged.ap_id in notified_ap_ids(activity)
end
test "it does not notify tagged users with a pending follow request" do
author = insert(:user, is_locked: true)
tagged = insert(:user)
{:ok, _, _, _} = CommonAPI.follow(author, tagged)
activity = incoming_note_tagging(author, [author.follower_address], [tagged.ap_id])
refute tagged.ap_id in notified_ap_ids(activity)
end
test "it ignores tags of unknown users in a followers-only post" do
author = insert(:user)
tagged = insert(:user)
follower = insert(:user)
{:ok, _, _} = Pleroma.User.follow(follower, author)
activity =
incoming_note_tagging(author, [author.follower_address], [
"https://unknown.example/users/nobody",
tagged.ap_id,
follower.ap_id
])
receivers = notified_ap_ids(activity)
refute tagged.ap_id in receivers
assert follower.ap_id in receivers
end
test "it does not send notifications to users who are only cc in new messages" do
user = insert(:user)
other_user = insert(:user)