ActivityPub: Don't show announces of your own objects in timeline.

This commit is contained in:
lain 2020-06-10 12:10:09 +02:00
parent 1b746cfbbb
commit 9e411372d0
3 changed files with 46 additions and 19 deletions

View File

@ -31,25 +31,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
require Logger require Logger
require Pleroma.Constants require Pleroma.Constants
# For Announce activities, we filter the recipients based on following status for any actors
# that match actual users. See issue #164 for more information about why this is necessary.
defp get_recipients(%{"type" => "Announce"} = data) do
to = Map.get(data, "to", [])
cc = Map.get(data, "cc", [])
bcc = Map.get(data, "bcc", [])
actor = User.get_cached_by_ap_id(data["actor"])
recipients =
Enum.filter(Enum.concat([to, cc, bcc]), fn recipient ->
case User.get_cached_by_ap_id(recipient) do
nil -> true
user -> User.following?(user, actor)
end
end)
{recipients, to, cc}
end
defp get_recipients(%{"type" => "Create"} = data) do defp get_recipients(%{"type" => "Create"} = data) do
to = Map.get(data, "to", []) to = Map.get(data, "to", [])
cc = Map.get(data, "cc", []) cc = Map.get(data, "cc", [])
@ -702,6 +683,26 @@ defp user_activities_recipients(%{reading_user: reading_user}) do
end end
end end
defp restrict_announce_object_actor(_query, %{announce_filtering_user: _, skip_preload: true}) do
raise "Can't use the child object without preloading!"
end
defp restrict_announce_object_actor(query, %{announce_filtering_user: %{ap_id: actor}}) do
from(
[activity, object] in query,
where:
fragment(
"?->>'type' != ? or ?->>'actor' != ?",
activity.data,
"Announce",
object.data,
^actor
)
)
end
defp restrict_announce_object_actor(query, _), do: query
defp restrict_since(query, %{since_id: ""}), do: query defp restrict_since(query, %{since_id: ""}), do: query
defp restrict_since(query, %{since_id: since_id}) do defp restrict_since(query, %{since_id: since_id}) do
@ -1113,6 +1114,7 @@ def fetch_activities_query(recipients, opts \\ %{}) do
|> restrict_pinned(opts) |> restrict_pinned(opts)
|> restrict_muted_reblogs(restrict_muted_reblogs_opts) |> restrict_muted_reblogs(restrict_muted_reblogs_opts)
|> restrict_instance(opts) |> restrict_instance(opts)
|> restrict_announce_object_actor(opts)
|> Activity.restrict_deactivated_users() |> Activity.restrict_deactivated_users()
|> exclude_poll_votes(opts) |> exclude_poll_votes(opts)
|> exclude_invisible_actors(opts) |> exclude_invisible_actors(opts)

View File

@ -48,6 +48,7 @@ def home(%{assigns: %{user: user}} = conn, params) do
|> Map.put(:blocking_user, user) |> Map.put(:blocking_user, user)
|> Map.put(:muting_user, user) |> Map.put(:muting_user, user)
|> Map.put(:reply_filtering_user, user) |> Map.put(:reply_filtering_user, user)
|> Map.put(:announce_filtering_user, user)
|> Map.put(:user, user) |> Map.put(:user, user)
activities = activities =

View File

@ -1643,6 +1643,30 @@ test "home timeline with reply_visibility `self`", %{
assert Enum.all?(visible_ids, &(&1 in activities_ids)) assert Enum.all?(visible_ids, &(&1 in activities_ids))
end end
test "filtering out announces where the user is the actor of the announced message" do
user = insert(:user)
other_user = insert(:user)
third_user = insert(:user)
User.follow(user, other_user)
{:ok, post} = CommonAPI.post(user, %{status: "yo"})
{:ok, other_post} = CommonAPI.post(third_user, %{status: "yo"})
{:ok, _announce} = CommonAPI.repeat(post.id, other_user)
{:ok, _announce} = CommonAPI.repeat(post.id, third_user)
{:ok, announce} = CommonAPI.repeat(other_post.id, other_user)
params = %{
type: ["Announce"],
announce_filtering_user: user
}
[result] =
[user.ap_id | User.following(user)]
|> ActivityPub.fetch_activities(params)
assert result.id == announce.id
end
end end
describe "replies filtering with private messages" do describe "replies filtering with private messages" do