From 87566b6e2f48ee2b82d4af7ccb6200ff8bc721d1 Mon Sep 17 00:00:00 2001 From: eal Date: Sun, 3 Jun 2018 22:01:37 +0300 Subject: [PATCH 1/4] user.ex: add domain blocks. --- lib/pleroma/user.ex | 24 +++++++++++++++++++++++- test/user_test.exs | 21 +++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index b1b935a0f..c8e61f8a9 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -479,7 +479,29 @@ def unblock(user, %{ap_id: ap_id}) do def blocks?(user, %{ap_id: ap_id}) do blocks = user.info["blocks"] || [] - Enum.member?(blocks, ap_id) + domain_blocks = user.info["domain_blocks"] || [] + %{host: host} = URI.parse(ap_id) + Enum.member?(blocks, ap_id) || Enum.any?(domain_blocks, fn domain -> + host == domain + end) + end + + def block_domain(user, domain) do + domain_blocks = user.info["domain_blocks"] || [] + new_blocks = Enum.uniq([domain | domain_blocks]) + new_info = Map.put(user.info, "domain_blocks", new_blocks) + + cs = User.info_changeset(user, %{info: new_info}) + update_and_set_cache(cs) + end + + def unblock_domain(user, domain) do + blocks = user.info["domain_blocks"] || [] + new_blocks = List.delete(blocks, domain) + new_info = Map.put(user.info, "domain_blocks", new_blocks) + + cs = User.info_changeset(user, %{info: new_info}) + update_and_set_cache(cs) end def local_user_query() do diff --git a/test/user_test.exs b/test/user_test.exs index 8c8cfd673..200352981 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -361,6 +361,27 @@ test "it unblocks users" do end end + describe "domain blocking" do + test "blocks domains" do + user = insert(:user) + collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"}) + + {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com") + + assert User.blocks?(user, collateral_user) + end + + test "unblocks domains" do + user = insert(:user) + collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"}) + + {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com") + {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com") + + refute User.blocks?(user, collateral_user) + end + end + test "get recipients from activity" do actor = insert(:user) user = insert(:user, local: true) From 4856962434ffd36826a4fc3052b867e751efc828 Mon Sep 17 00:00:00 2001 From: eal Date: Sun, 3 Jun 2018 22:21:23 +0300 Subject: [PATCH 2/4] MastoAPI: add domain blocking. --- lib/pleroma/user.ex | 8 ++-- .../mastodon_api/mastodon_api_controller.ex | 14 +++++++ lib/pleroma/web/router.ex | 5 ++- .../mastodon_api_controller_test.exs | 40 +++++++++++++++++++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index c8e61f8a9..aecf96c36 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -481,9 +481,11 @@ def blocks?(user, %{ap_id: ap_id}) do blocks = user.info["blocks"] || [] domain_blocks = user.info["domain_blocks"] || [] %{host: host} = URI.parse(ap_id) - Enum.member?(blocks, ap_id) || Enum.any?(domain_blocks, fn domain -> - host == domain - end) + + Enum.member?(blocks, ap_id) || + Enum.any?(domain_blocks, fn domain -> + host == domain + end) end def block_domain(user, domain) do diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 5fb51e8fa..12f9b5f7c 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -533,6 +533,20 @@ def blocks(%{assigns: %{user: user}} = conn, _) do end end + def domain_blocks(%{assigns: %{user: %{info: info}}} = conn, _) do + json(conn, info["domain_blocks"] || []) + end + + def block_domain(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do + User.block_domain(blocker, domain) + json(conn, %{}) + end + + def unblock_domain(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do + User.unblock_domain(blocker, domain) + json(conn, %{}) + end + def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do accounts = User.search(query, params["resolve"] == "true") diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 924254895..57b10bff1 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -101,7 +101,6 @@ def user_fetcher(username) do get("/blocks", MastodonAPIController, :blocks) - get("/domain_blocks", MastodonAPIController, :empty_array) get("/follow_requests", MastodonAPIController, :empty_array) get("/mutes", MastodonAPIController, :empty_array) @@ -134,6 +133,10 @@ def user_fetcher(username) do get("/lists/:id/accounts", MastodonAPIController, :list_accounts) post("/lists/:id/accounts", MastodonAPIController, :add_to_list) delete("/lists/:id/accounts", MastodonAPIController, :remove_from_list) + + get("/domain_blocks", MastodonAPIController, :domain_blocks) + post("/domain_blocks", MastodonAPIController, :block_domain) + delete("/domain_blocks", MastodonAPIController, :unblock_domain) end scope "/api/web", Pleroma.Web.MastodonAPI do diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 2abcf0dfe..eaae0b54f 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -780,6 +780,46 @@ test "getting a list of blocks", %{conn: conn} do assert [%{"id" => ^other_user_id}] = json_response(conn, 200) end + test "blocking / unblocking a domain", %{conn: conn} do + user = insert(:user) + other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"}) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) + + assert %{} = json_response(conn, 200) + user = User.get_cached_by_ap_id(user.ap_id) + assert User.blocks?(user, other_user) + + conn = + build_conn() + |> assign(:user, user) + |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) + + assert %{} = json_response(conn, 200) + user = User.get_cached_by_ap_id(user.ap_id) + refute User.blocks?(user, other_user) + end + + test "getting a list of domain blocks" do + user = insert(:user) + + {:ok, user} = User.block_domain(user, "bad.site") + {:ok, user} = User.block_domain(user, "even.worse.site") + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/domain_blocks") + + domain_blocks = json_response(conn, 200) + + assert "bad.site" in domain_blocks + assert "even.worse.site" in domain_blocks + end + test "unimplemented mute endpoints" do user = insert(:user) other_user = insert(:user) From 9075b6d25b4b136bb8d8ae888bd52996a9f302e2 Mon Sep 17 00:00:00 2001 From: eal Date: Sun, 3 Jun 2018 23:33:33 +0300 Subject: [PATCH 3/4] ActivityPub.ex: filter domain blocked activities. --- lib/pleroma/web/activity_pub/activity_pub.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 4e0be5ba2..5c61920e5 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -439,11 +439,13 @@ defp restrict_recent(query, _) do defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do blocks = info["blocks"] || [] + domain_blocks = info["domain_blocks"] || [] from( activity in query, where: fragment("not (? = ANY(?))", activity.actor, ^blocks), - where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks) + where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks), + where: fragment("not (? ~ ANY(?))", activity.actor, ^domain_blocks) ) end From 29c9c8d93b263e57915158d09761bc6586826798 Mon Sep 17 00:00:00 2001 From: eal Date: Wed, 6 Jun 2018 21:13:40 +0300 Subject: [PATCH 4/4] Extract host from ap_id, add index --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- .../20180606173637_create_apid_host_extraction_index.exs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 priv/repo/migrations/20180606173637_create_apid_host_extraction_index.exs diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 5c61920e5..a5e42d9d0 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -445,7 +445,7 @@ defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do activity in query, where: fragment("not (? = ANY(?))", activity.actor, ^blocks), where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks), - where: fragment("not (? ~ ANY(?))", activity.actor, ^domain_blocks) + where: fragment("not (split_part(?, '/', 3) = ANY(?))", activity.actor, ^domain_blocks) ) end diff --git a/priv/repo/migrations/20180606173637_create_apid_host_extraction_index.exs b/priv/repo/migrations/20180606173637_create_apid_host_extraction_index.exs new file mode 100644 index 000000000..9831a1b82 --- /dev/null +++ b/priv/repo/migrations/20180606173637_create_apid_host_extraction_index.exs @@ -0,0 +1,8 @@ +defmodule Pleroma.Repo.Migrations.CreateApidHostExtractionIndex do + use Ecto.Migration + @disable_ddl_transaction true + + def change do + create index(:activities, ["(split_part(actor, '/', 3))"], concurrently: true, name: :activities_hosts) + end +end