Merge branch 'feature/mrf-user-filter' into 'develop'
authorkaniini <nenolod@gmail.com>
Wed, 22 May 2019 19:03:14 +0000 (19:03 +0000)
committerkaniini <nenolod@gmail.com>
Wed, 22 May 2019 19:03:14 +0000 (19:03 +0000)
mrf: add support for filtering users

See merge request pleroma/pleroma!1188

CHANGELOG.md
config/config.exs
docs/config.md
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/mrf/simple_policy.ex
lib/pleroma/web/activity_pub/mrf/user_allowlist.ex
test/web/activity_pub/mrf/simple_policy_test.exs

index 6c94669dbec254281d790de455f748b9158646cb..7869e299bb293169083653f83fcba907f8af71bc 100644 (file)
@@ -43,6 +43,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Emoji packs and emoji pack manager
 - Object pruning (`mix pleroma.database prune_objects`)
 - OAuth: added job to clean expired access tokens
+- MRF: Support for rejecting reports from specific instances (`mrf_simple`)
+- MRF: Support for stripping avatars and banner images from specific instances (`mrf_simple`)
 
 ### Changed
 - **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer
index 33b7e713d9a69878acadf76883e355247573e74c..e90821d66daf9ae4361703579d16ec24a83da6ef 100644 (file)
@@ -314,7 +314,9 @@ config :pleroma, :mrf_simple,
   federated_timeline_removal: [],
   report_removal: [],
   reject: [],
-  accept: []
+  accept: [],
+  avatar_removal: [],
+  banner_removal: []
 
 config :pleroma, :mrf_keyword,
   reject: [],
index be0cbc2dcd51791b0b8a59c9e8a7f01fcf46cb9c..67b062fe930b776112f680eae2ac24161cbbc1dc 100644 (file)
@@ -220,6 +220,9 @@ relates to mascots on the mastodon frontend
 * `federated_timeline_removal`: List of instances to remove from Federated (aka The Whole Known Network) Timeline
 * `reject`: List of instances to reject any activities from
 * `accept`: List of instances to accept any activities from
+* `report_removal`: List of instances to reject reports from
+* `avatar_removal`: List of instances to strip avatars from
+* `banner_removal`: List of instances to strip banners from
 
 ## :mrf_rejectnonpublic
 * `allow_followersonly`: whether to allow followers-only posts
index 3d9679ec0d03728f7606c6fcd6875bf5996d0795..aa0229db7f3e77d89620c6f329d6ed3cb2acbb0e 100644 (file)
@@ -909,7 +909,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end
   end
 
-  def user_data_from_user_object(data) do
+  defp object_to_user_data(data) do
     avatar =
       data["icon"]["url"] &&
         %{
@@ -956,9 +956,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     {:ok, user_data}
   end
 
+  def user_data_from_user_object(data) do
+    with {:ok, data} <- MRF.filter(data),
+         {:ok, data} <- object_to_user_data(data) do
+      {:ok, data}
+    else
+      e -> {:error, e}
+    end
+  end
+
   def fetch_and_prepare_user_from_ap_id(ap_id) do
-    with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id) do
-      user_data_from_user_object(data)
+    with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id),
+         {:ok, data} <- user_data_from_user_object(data) do
+      {:ok, data}
     else
       e -> Logger.error("Could not decode user at fetch #{ap_id}, #{inspect(e)}")
     end
index 7190652d2c832611d47c4aeffabb363f0496451a..890d70a7a807cca0ca7756d244f2cf3b2fcf79e0 100644 (file)
@@ -104,9 +104,29 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
 
   defp check_report_removal(_actor_info, object), do: {:ok, object}
 
+  defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = object) do
+    if actor_host in Pleroma.Config.get([:mrf_simple, :avatar_removal]) do
+      {:ok, Map.delete(object, "icon")}
+    else
+      {:ok, object}
+    end
+  end
+
+  defp check_avatar_removal(_actor_info, object), do: {:ok, object}
+
+  defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = object) do
+    if actor_host in Pleroma.Config.get([:mrf_simple, :banner_removal]) do
+      {:ok, Map.delete(object, "image")}
+    else
+      {:ok, object}
+    end
+  end
+
+  defp check_banner_removal(_actor_info, object), do: {:ok, object}
+
   @impl true
-  def filter(object) do
-    actor_info = URI.parse(object["actor"])
+  def filter(%{"actor" => actor} = object) do
+    actor_info = URI.parse(actor)
 
     with {:ok, object} <- check_accept(actor_info, object),
          {:ok, object} <- check_reject(actor_info, object),
@@ -119,4 +139,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
       _e -> {:reject, nil}
     end
   end
+
+  def filter(%{"id" => actor, "type" => obj_type} = object)
+      when obj_type in ["Application", "Group", "Organization", "Person", "Service"] do
+    actor_info = URI.parse(actor)
+
+    with {:ok, object} <- check_avatar_removal(actor_info, object),
+         {:ok, object} <- check_banner_removal(actor_info, object) do
+      {:ok, object}
+    else
+      _e -> {:reject, nil}
+    end
+  end
+
+  def filter(object), do: {:ok, object}
 end
index f5078d8182a60d35b441f5d68536bc4994653904..47663414a38773e0b1a6e860ff6055a76f43d112 100644 (file)
@@ -19,10 +19,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
   end
 
   @impl true
-  def filter(object) do
-    actor_info = URI.parse(object["actor"])
+  def filter(%{"actor" => actor} = object) do
+    actor_info = URI.parse(actor)
     allow_list = Config.get([:mrf_user_allowlist, String.to_atom(actor_info.host)], [])
 
     filter_by_list(object, allow_list)
   end
+
+  def filter(object), do: {:ok, object}
 end
index 74af7dcde8701413a0f0baad05b172ed8172ad43..3d1f26e60343c63f09e06c723350b5d67f894c35 100644 (file)
@@ -17,7 +17,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
       federated_timeline_removal: [],
       report_removal: [],
       reject: [],
-      accept: []
+      accept: [],
+      avatar_removal: [],
+      banner_removal: []
     )
 
     on_exit(fn ->
@@ -206,6 +208,60 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
     end
   end
 
+  describe "when :avatar_removal" do
+    test "is empty" do
+      Config.put([:mrf_simple, :avatar_removal], [])
+
+      remote_user = build_remote_user()
+
+      assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
+    end
+
+    test "is not empty but it doesn't have a matching host" do
+      Config.put([:mrf_simple, :avatar_removal], ["non.matching.remote"])
+
+      remote_user = build_remote_user()
+
+      assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
+    end
+
+    test "has a matching host" do
+      Config.put([:mrf_simple, :avatar_removal], ["remote.instance"])
+
+      remote_user = build_remote_user()
+      {:ok, filtered} = SimplePolicy.filter(remote_user)
+
+      refute filtered["icon"]
+    end
+  end
+
+  describe "when :banner_removal" do
+    test "is empty" do
+      Config.put([:mrf_simple, :banner_removal], [])
+
+      remote_user = build_remote_user()
+
+      assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
+    end
+
+    test "is not empty but it doesn't have a matching host" do
+      Config.put([:mrf_simple, :banner_removal], ["non.matching.remote"])
+
+      remote_user = build_remote_user()
+
+      assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
+    end
+
+    test "has a matching host" do
+      Config.put([:mrf_simple, :banner_removal], ["remote.instance"])
+
+      remote_user = build_remote_user()
+      {:ok, filtered} = SimplePolicy.filter(remote_user)
+
+      refute filtered["image"]
+    end
+  end
+
   defp build_local_message do
     %{
       "actor" => "#{Pleroma.Web.base_url()}/users/alice",
@@ -217,4 +273,19 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
   defp build_remote_message do
     %{"actor" => "https://remote.instance/users/bob"}
   end
+
+  defp build_remote_user do
+    %{
+      "id" => "https://remote.instance/users/bob",
+      "icon" => %{
+        "url" => "http://example.com/image.jpg",
+        "type" => "Image"
+      },
+      "image" => %{
+        "url" => "http://example.com/image.jpg",
+        "type" => "Image"
+      },
+      "type" => "Person"
+    }
+  end
 end