summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--config/config.exs1
-rw-r--r--config/description.exs5
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex50
-rw-r--r--test/pleroma/web/activity_pub/activity_pub_test.exs27
-rw-r--r--test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs18
6 files changed, 98 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a82f7d6c..853b3aaae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Account backup
- Configuration: Add `:instance, autofollowing_nicknames` setting to provide a way to make accounts automatically follow new users that register on the local Pleroma instance.
- Ability to view remote timelines, with ex. `/api/v1/timelines/public?instance=lain.com` and streams `public:remote` and `public:remote:media`
+- `[:activitypub, :blockers_visible]` config to control visibility of blockers.
### Changed
@@ -63,6 +64,7 @@ switched to a new configuration mechanism, however it was not officially removed
- OStatus / static FE endpoints: fixed inaccessibility for anonymous users on non-federating instances, switched to handling per `:restrict_unauthenticated` setting.
- Mastodon API: Current user is now included in conversation if it's the only participant
- Mastodon API: Fixed last_status.account being not filled with account data
+- See your own post when addressing a user from a blocked domain.
## Unreleased (Patch)
diff --git a/config/config.exs b/config/config.exs
index c0b6ac1d6..471f5d22a 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -363,6 +363,7 @@ config :pleroma, :manifest,
config :pleroma, :activitypub,
unfollow_blocked: true,
outgoing_blocks: true,
+ blockers_visible: true,
follow_handshake_timeout: 500,
note_replies_output_limit: 5,
sign_object_fetches: true,
diff --git a/config/description.exs b/config/description.exs
index 0b651696b..8a49d1b66 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -2102,6 +2102,11 @@ config :pleroma, :config_description, [
description: "Whether to federate blocks to other instances"
},
%{
+ key: :blockers_visible,
+ type: :boolean,
+ description: "Whether a user can see someone who has blocked them"
+ },
+ %{
key: :sign_object_fetches,
type: :boolean,
description: "Sign object fetches with HTTP signatures"
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index d8f685d38..a67a203d0 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -410,6 +410,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> maybe_preload_bookmarks(opts)
|> maybe_set_thread_muted_field(opts)
|> restrict_blocked(opts)
+ |> restrict_blockers_visibility(opts)
|> restrict_recipients(recipients, opts[:user])
|> restrict_filtered(opts)
|> where(
@@ -791,10 +792,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
where:
fragment(
"""
- ?->>'type' != 'Create' -- This isn't a Create
+ ?->>'type' != 'Create' -- This isn't a Create
OR ?->>'inReplyTo' is null -- this isn't a reply
- OR ? && array_remove(?, ?) -- The recipient is us or one of our friends,
- -- unless they are the author (because authors
+ OR ? && array_remove(?, ?) -- The recipient is us or one of our friends,
+ -- unless they are the author (because authors
-- are also part of the recipients). This leads
-- to a bug that self-replies by friends won't
-- show up.
@@ -857,7 +858,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
from(
[activity, object: o] in query,
+ # You don't block the author
where: fragment("not (? = ANY(?))", activity.actor, ^blocked_ap_ids),
+
+ # You don't block any recipients, and didn't author the post
where:
fragment(
"((not (? && ?)) or ? = ?)",
@@ -866,12 +870,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
activity.actor,
^user.ap_id
),
+
+ # You don't block the domain of any recipients, and didn't author the post
where:
fragment(
- "recipients_contain_blocked_domains(?, ?) = false",
+ "(recipients_contain_blocked_domains(?, ?) = false) or ? = ?",
activity.recipients,
- ^domain_blocks
+ ^domain_blocks,
+ activity.actor,
+ ^user.ap_id
),
+
+ # It's not a boost of a user you block
where:
fragment(
"not (?->>'type' = 'Announce' and ?->'to' \\?| ?)",
@@ -879,6 +889,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
activity.data,
^blocked_ap_ids
),
+
+ # You don't block the author's domain, and also don't follow the author
where:
fragment(
"(not (split_part(?, '/', 3) = ANY(?))) or ? = ANY(?)",
@@ -887,6 +899,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
activity.actor,
^following_ap_ids
),
+
+ # Same as above, but checks the Object
where:
fragment(
"(not (split_part(?->>'actor', '/', 3) = ANY(?))) or (?->>'actor') = ANY(?)",
@@ -900,6 +914,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_blocked(query, _), do: query
+ defp restrict_blockers_visibility(query, %{blocking_user: %User{} = user}) do
+ if Config.get([:activitypub, :blockers_visible]) == true do
+ query
+ else
+ blocker_ap_ids = User.incoming_relationships_ungrouped_ap_ids(user, [:block])
+
+ from(
+ activity in query,
+ # The author doesn't block you
+ where: fragment("not (? = ANY(?))", activity.actor, ^blocker_ap_ids),
+
+ # It's not a boost of a user that blocks you
+ where:
+ fragment(
+ "not (?->>'type' = 'Announce' and ?->'to' \\?| ?)",
+ activity.data,
+ activity.data,
+ ^blocker_ap_ids
+ )
+ )
+ end
+ end
+
+ defp restrict_blockers_visibility(query, _), do: query
+
defp restrict_unlisted(query, %{restrict_unlisted: true}) do
from(
activity in query,
@@ -1095,6 +1134,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_state(opts)
|> restrict_favorited_by(opts)
|> restrict_blocked(restrict_blocked_opts)
+ |> restrict_blockers_visibility(opts)
|> restrict_muted(restrict_muted_opts)
|> restrict_filtered(opts)
|> restrict_media(opts)
diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs
index 43bd14ee6..a14895104 100644
--- a/test/pleroma/web/activity_pub/activity_pub_test.exs
+++ b/test/pleroma/web/activity_pub/activity_pub_test.exs
@@ -622,6 +622,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Enum.member?(activities, activity_one)
end
+ test "always see your own posts even when they address people you block" do
+ user = insert(:user)
+ blockee = insert(:user)
+
+ {:ok, _} = User.block(user, blockee)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey! @#{blockee.nickname}"})
+
+ activities = ActivityPub.fetch_activities([], %{blocking_user: user})
+
+ assert Enum.member?(activities, activity)
+ end
+
test "doesn't return transitive interactions concerning blocked users" do
blocker = insert(:user)
blockee = insert(:user)
@@ -721,6 +733,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
refute repeat_activity in activities
end
+ test "see your own posts even when they adress actors from blocked domains" do
+ user = insert(:user)
+
+ domain = "dogwhistle.zone"
+ domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"})
+
+ {:ok, user} = User.block_domain(user, domain)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey! @#{domain_user.nickname}"})
+
+ activities = ActivityPub.fetch_activities([], %{blocking_user: user})
+
+ assert Enum.member?(activities, activity)
+ end
+
test "does return activities from followed users on blocked domains" do
domain = "meanies.social"
domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"})
diff --git a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs
index 4c08ad60a..c6d72f6cc 100644
--- a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs
@@ -125,6 +125,24 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
[%{"id" => ^reply_from_me}, %{"id" => ^activity_id}] = response
end
+ test "doesn't return posts from users who blocked you when :blockers_visible is disabled" do
+ clear_config([:activitypub, :blockers_visible], false)
+
+ %{conn: conn, user: blockee} = oauth_access(["read:statuses"])
+ blocker = insert(:user)
+ {:ok, _} = User.block(blocker, blockee)
+
+ conn = assign(conn, :user, blockee)
+
+ {:ok, _} = CommonAPI.post(blocker, %{status: "hey!"})
+
+ response =
+ get(conn, "/api/v1/timelines/public")
+ |> json_response_and_validate_schema(200)
+
+ assert length(response) == 0
+ end
+
test "doesn't return replies if follow is posting with users from blocked domain" do
%{conn: conn, user: blocker} = oauth_access(["read:statuses"])
friend = insert(:user)