fix(notifications): handle unknown users when filtering tagged mentions

The access check from the previous commit crashed on tags of unknown
users in followers-only posts, so such posts failed to be received.
Also add tests for the check.
This commit is contained in:
Lain Soykaf 2026-10-27 12:31:18 +04:00
commit cccbb39309
No known key found for this signature in database
3 changed files with 104 additions and 3 deletions

View file

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

View file

@ -465,7 +465,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
true -> true ->
author = User.get_cached_by_ap_id(actor) author = User.get_cached_by_ap_id(actor)
to_followers = author.follower_address in recipients to_followers = match?(%User{}, author) and author.follower_address in recipients
Enum.filter(tagged_mentions, fn tagged -> Enum.filter(tagged_mentions, fn tagged ->
cond do cond do
@ -473,8 +473,10 @@ defmodule Pleroma.Web.CommonAPI.Utils do
true true
to_followers -> to_followers ->
tagged_user = User.get_cached_by_ap_id(tagged) case User.get_cached_by_ap_id(tagged) do
User.following?(tagged_user, author) %User{} = tagged_user -> User.following?(tagged_user, author)
_ -> false
end
true -> true ->
false false

View file

@ -7,6 +7,8 @@ defmodule Pleroma.NotificationTest do
import Pleroma.Factory import Pleroma.Factory
require Pleroma.Constants
alias Pleroma.FollowingRelationship alias Pleroma.FollowingRelationship
alias Pleroma.Notification alias Pleroma.Notification
alias Pleroma.Repo alias Pleroma.Repo
@ -611,6 +613,102 @@ defmodule Pleroma.NotificationTest do
assert other_user in enabled_receivers assert other_user in enabled_receivers
end 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 test "it does not send notifications to users who are only cc in new messages" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)