replies filtering for blocked domains

This commit is contained in:
Alexander Strizhakov 2020-06-02 08:50:24 +03:00
parent 7e6ec778d9
commit 19f468c5bc
No known key found for this signature in database
GPG key ID: 022896A53AEF1381
5 changed files with 15 additions and 95 deletions

View file

@ -228,24 +228,16 @@ defmodule Pleroma.LoadTesting.Fetcher do
fetch_public_timeline(opts, "public timeline only media") fetch_public_timeline(opts, "public timeline only media")
end end
# TODO: remove using `:method` after benchmarks
defp fetch_public_timeline(user, :with_blocks) do defp fetch_public_timeline(user, :with_blocks) do
opts = opts_for_public_timeline(user) opts = opts_for_public_timeline(user)
remote_non_friends = Agent.get(:non_friends_remote, & &1) remote_non_friends = Agent.get(:non_friends_remote, & &1)
Benchee.run( Benchee.run(%{
%{ "public timeline without blocks" => fn ->
"public timeline without blocks" => fn opts ->
ActivityPub.fetch_public_activities(opts) ActivityPub.fetch_public_activities(opts)
end end
}, })
inputs: %{
"old filtering" => Map.delete(opts, :method),
"with psql fun" => Map.put(opts, :method, :fun),
"with unnest" => Map.put(opts, :method, :unnest)
}
)
Enum.each(remote_non_friends, fn non_friend -> Enum.each(remote_non_friends, fn non_friend ->
{:ok, _} = User.block(user, non_friend) {:ok, _} = User.block(user, non_friend)
@ -257,15 +249,10 @@ defmodule Pleroma.LoadTesting.Fetcher do
Benchee.run( Benchee.run(
%{ %{
"public timeline with user block" => fn opts -> "public timeline with user block" => fn ->
ActivityPub.fetch_public_activities(opts) ActivityPub.fetch_public_activities(opts)
end end
}, },
inputs: %{
"old filtering" => Map.delete(opts, :method),
"with psql fun" => Map.put(opts, :method, :fun),
"with unnest" => Map.put(opts, :method, :unnest)
}
) )
domains = domains =
@ -289,11 +276,6 @@ defmodule Pleroma.LoadTesting.Fetcher do
"public timeline with domain block" => fn opts -> "public timeline with domain block" => fn opts ->
ActivityPub.fetch_public_activities(opts) ActivityPub.fetch_public_activities(opts)
end end
},
inputs: %{
"old filtering" => Map.delete(opts, :method),
"with psql fun" => Map.put(opts, :method, :fun),
"with unnest" => Map.put(opts, :method, :unnest)
} }
) )
end end

View file

@ -932,37 +932,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
query = query =
if has_named_binding?(query, :object), do: query, else: Activity.with_joined_object(query) if has_named_binding?(query, :object), do: query, else: Activity.with_joined_object(query)
# TODO: update after benchmarks
query =
case opts[:method] do
:fun ->
from(a in query,
where:
fragment(
"recipients_contain_blocked_domains(?, ?) = false",
a.recipients,
^domain_blocks
)
)
:unnest ->
from(a in query,
where:
fragment(
"NOT ? && (SELECT ARRAY(SELECT split_part(UNNEST(?), '/', 3)))",
^domain_blocks,
a.recipients
)
)
_ ->
query
end
from( from(
[activity, object: o] in query, [activity, object: o] in query,
where: fragment("not (? = ANY(?))", activity.actor, ^blocked_ap_ids), where: fragment("not (? = ANY(?))", activity.actor, ^blocked_ap_ids),
where: fragment("not (? && ?)", activity.recipients, ^blocked_ap_ids), where: fragment("not (? && ?)", activity.recipients, ^blocked_ap_ids),
where:
fragment(
"recipients_contain_blocked_domains(?, ?) = false",
activity.recipients,
^domain_blocks
),
where: where:
fragment( fragment(
"not (?->>'type' = 'Announce' and ?->'to' \\?| ?)", "not (?->>'type' = 'Announce' and ?->'to' \\?| ?)",

View file

@ -62,13 +62,6 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do
only_media_param(), only_media_param(),
with_muted_param(), with_muted_param(),
exclude_visibilities_param(), exclude_visibilities_param(),
# TODO: remove after benchmarks
Operation.parameter(
:method,
:query,
%Schema{type: :string},
"Temp parameter"
),
reply_visibility_param() | pagination_params() reply_visibility_param() | pagination_params()
], ],
operationId: "TimelineController.public", operationId: "TimelineController.public",

View file

@ -109,23 +109,14 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
if restrict? and is_nil(user) do if restrict? and is_nil(user) do
render_error(conn, :unauthorized, "authorization required for timeline view") render_error(conn, :unauthorized, "authorization required for timeline view")
else else
# TODO: return back after benchmarks activities =
params =
params params
|> Map.put("type", ["Create", "Announce"]) |> Map.put("type", ["Create", "Announce"])
|> Map.put("local_only", local_only) |> Map.put("local_only", local_only)
|> 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)
|> ActivityPub.fetch_public_activities()
params =
if params["method"] do
Map.put(params, :method, String.to_existing_atom(params["method"]))
else
params
end
activities = ActivityPub.fetch_public_activities(params)
conn conn
|> add_link_headers(activities, %{"local" => local_only}) |> add_link_headers(activities, %{"local" => local_only})

View file

@ -111,7 +111,6 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
[%{"id" => ^activity_id}] = json_response_and_validate_schema(res_conn, 200) [%{"id" => ^activity_id}] = json_response_and_validate_schema(res_conn, 200)
end end
# TODO: update after benchmarks
test "doesn't return replies if follow is posting with users from blocked domain" do test "doesn't return replies if follow is posting with users from blocked domain" do
%{conn: conn, user: blocker} = oauth_access(["read:statuses"]) %{conn: conn, user: blocker} = oauth_access(["read:statuses"])
friend = insert(:user) friend = insert(:user)
@ -129,31 +128,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
{:ok, _reply_from_friend} = {:ok, _reply_from_friend} =
CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee}) CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee})
res_conn = get(conn, "/api/v1/timelines/public?method=fun") res_conn = get(conn, "/api/v1/timelines/public")
activities = json_response_and_validate_schema(res_conn, 200)
[%{"id" => ^activity_id}] = activities
end
# TODO: update after benchmarks
test "doesn't return replies if follow is posting with users from blocked domain with unnest param" do
%{conn: conn, user: blocker} = oauth_access(["read:statuses"])
friend = insert(:user)
blockee = insert(:user, ap_id: "https://example.com/users/blocked")
{:ok, blocker} = User.follow(blocker, friend)
{:ok, blocker} = User.block_domain(blocker, "example.com")
conn = assign(conn, :user, blocker)
{:ok, %{id: activity_id} = activity} = CommonAPI.post(friend, %{status: "hey!"})
{:ok, reply_from_blockee} =
CommonAPI.post(blockee, %{status: "heya", in_reply_to_status_id: activity})
{:ok, _reply_from_friend} =
CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee})
res_conn = get(conn, "/api/v1/timelines/public?method=unnest")
activities = json_response_and_validate_schema(res_conn, 200) activities = json_response_and_validate_schema(res_conn, 200)
[%{"id" => ^activity_id}] = activities [%{"id" => ^activity_id}] = activities