forked from AkkomaGang/akkoma
Merge branch 'dm-optimizations' into 'develop'
Add activity visibility index. See merge request pleroma/pleroma!646
This commit is contained in:
commit
d203b0b4d3
3 changed files with 95 additions and 14 deletions
|
@ -364,21 +364,18 @@ def fetch_public_activities(opts \\ %{}) do
|
||||||
|
|
||||||
@valid_visibilities ~w[direct unlisted public private]
|
@valid_visibilities ~w[direct unlisted public private]
|
||||||
|
|
||||||
defp restrict_visibility(query, %{visibility: "direct"}) do
|
defp restrict_visibility(query, %{visibility: visibility})
|
||||||
public = "https://www.w3.org/ns/activitystreams#Public"
|
when visibility in @valid_visibilities do
|
||||||
|
query =
|
||||||
|
from(
|
||||||
|
a in query,
|
||||||
|
where:
|
||||||
|
fragment("activity_visibility(?, ?, ?) = ?", a.actor, a.recipients, a.data, ^visibility)
|
||||||
|
)
|
||||||
|
|
||||||
from(
|
Ecto.Adapters.SQL.to_sql(:all, Repo, query)
|
||||||
activity in query,
|
|
||||||
join: sender in User,
|
query
|
||||||
on: sender.ap_id == activity.actor,
|
|
||||||
# Are non-direct statuses with no to/cc possible?
|
|
||||||
where:
|
|
||||||
fragment(
|
|
||||||
"not (? && ?)",
|
|
||||||
[^public, sender.follower_address],
|
|
||||||
activity.recipients
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict_visibility(_query, %{visibility: visibility})
|
defp restrict_visibility(_query, %{visibility: visibility})
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddVisibilityFunction do
|
||||||
|
use Ecto.Migration
|
||||||
|
@disable_ddl_transaction true
|
||||||
|
|
||||||
|
def up do
|
||||||
|
definition = """
|
||||||
|
create or replace function activity_visibility(actor varchar, recipients varchar[], data jsonb) returns varchar as $$
|
||||||
|
DECLARE
|
||||||
|
fa varchar;
|
||||||
|
public varchar := 'https://www.w3.org/ns/activitystreams#Public';
|
||||||
|
BEGIN
|
||||||
|
SELECT COALESCE(users.follower_address, '') into fa from users where users.ap_id = actor;
|
||||||
|
|
||||||
|
IF data->'to' ? public THEN
|
||||||
|
RETURN 'public';
|
||||||
|
ELSIF data->'cc' ? public THEN
|
||||||
|
RETURN 'unlisted';
|
||||||
|
ELSIF ARRAY[fa] && recipients THEN
|
||||||
|
RETURN 'private';
|
||||||
|
ELSIF not(ARRAY[fa, public] && recipients) THEN
|
||||||
|
RETURN 'direct';
|
||||||
|
ELSE
|
||||||
|
RETURN 'unknown';
|
||||||
|
END IF;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
"""
|
||||||
|
|
||||||
|
execute(definition)
|
||||||
|
|
||||||
|
create(
|
||||||
|
index(:activities, ["activity_visibility(actor, recipients, data)"],
|
||||||
|
name: :activities_visibility_index,
|
||||||
|
concurrently: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
drop(
|
||||||
|
index(:activities, ["activity_visibility(actor, recipients, data)"],
|
||||||
|
name: :activities_visibility_index
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
execute("drop function activity_visibility(actor varchar, recipients varchar[], data jsonb)")
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,6 +18,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "fetching restricted by visibility" do
|
||||||
|
test "it restricts by the appropriate visibility" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
|
||||||
|
|
||||||
|
{:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||||
|
|
||||||
|
{:ok, unlisted_activity} =
|
||||||
|
CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
|
||||||
|
|
||||||
|
{:ok, private_activity} =
|
||||||
|
CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
|
||||||
|
|
||||||
|
activities =
|
||||||
|
ActivityPub.fetch_activities([], %{:visibility => "direct", "actor_id" => user.ap_id})
|
||||||
|
|
||||||
|
assert activities == [direct_activity]
|
||||||
|
|
||||||
|
activities =
|
||||||
|
ActivityPub.fetch_activities([], %{:visibility => "unlisted", "actor_id" => user.ap_id})
|
||||||
|
|
||||||
|
assert activities == [unlisted_activity]
|
||||||
|
|
||||||
|
activities =
|
||||||
|
ActivityPub.fetch_activities([], %{:visibility => "private", "actor_id" => user.ap_id})
|
||||||
|
|
||||||
|
assert activities == [private_activity]
|
||||||
|
|
||||||
|
activities =
|
||||||
|
ActivityPub.fetch_activities([], %{:visibility => "public", "actor_id" => user.ap_id})
|
||||||
|
|
||||||
|
assert activities == [public_activity]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "building a user from his ap id" do
|
describe "building a user from his ap id" do
|
||||||
test "it returns a user" do
|
test "it returns a user" do
|
||||||
user_id = "http://mastodon.example.org/users/admin"
|
user_id = "http://mastodon.example.org/users/admin"
|
||||||
|
|
Loading…
Reference in a new issue