Merge branch 'feature/domain-blocks' into 'develop'
authorlambda <pleromagit@rogerbraun.net>
Mon, 11 Jun 2018 11:19:45 +0000 (11:19 +0000)
committerlambda <pleromagit@rogerbraun.net>
Mon, 11 Jun 2018 11:19:45 +0000 (11:19 +0000)
Domain blocks

See merge request pleroma/pleroma!190

lib/pleroma/user.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/router.ex
priv/repo/migrations/20180606173637_create_apid_host_extraction_index.exs [new file with mode: 0644]
test/user_test.exs
test/web/mastodon_api/mastodon_api_controller_test.exs

index 828370cabb43df0e61d206fddd87b292f9fdc8a2..00cac153d1d0dd10843d7f10a94f1660a8d21fba 100644 (file)
@@ -479,7 +479,31 @@ defmodule Pleroma.User 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
index 75a71da98bb85f25e91d1fafc0b986d81599f86e..43e96fe3779f3d1f08bb3339625269fb6d4f9f76 100644 (file)
@@ -439,11 +439,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub 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 (split_part(?, '/', 3) = ANY(?))", activity.actor, ^domain_blocks)
     )
   end
 
index 974da52032fa161ddbc6dcba154fe2fb69533f67..0f7d4bb6d85289d8e5075f5de9f2dc787194e497 100644 (file)
@@ -545,6 +545,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController 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")
 
index 924254895030a87bd512c8c53d18dd778a4ab19f..57b10bff1e5149efa445b5d23c47317aaaf4b985 100644 (file)
@@ -101,7 +101,6 @@ defmodule Pleroma.Web.Router 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 @@ defmodule Pleroma.Web.Router 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/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 (file)
index 0000000..9831a1b
--- /dev/null
@@ -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
index 8c8cfd673fe31237e3fddda45e21344e95c606d9..200352981cf12f98b91271fbcad45a9135c6b742 100644 (file)
@@ -361,6 +361,27 @@ defmodule Pleroma.UserTest 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)
index 1291c3693dd04135c7363dbb0d3d9403aba0e7dc..566f5acfcbcaa2f7276e02aed3d72902d12b4bc6 100644 (file)
@@ -792,6 +792,46 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest 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)