MRF Policies: Return a {:reject, reason} instead of {:reject, nil}
[akkoma] / test / web / activity_pub / mrf / simple_policy_test.exs
index 0fd68e103814e73f57bdf0d8753cc8d0cf01ec17..e842d8d8de023fb3d3cdfbae9b5bf6ab5a11d096 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
@@ -8,24 +8,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
   alias Pleroma.Config
   alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
 
-  setup do
-    orig = Config.get!(:mrf_simple)
-
-    Config.put(:mrf_simple,
-      media_removal: [],
-      media_nsfw: [],
-      federated_timeline_removal: [],
-      report_removal: [],
-      reject: [],
-      accept: [],
-      avatar_removal: [],
-      banner_removal: []
-    )
-
-    on_exit(fn ->
-      Config.put(:mrf_simple, orig)
-    end)
-  end
+  setup do:
+          clear_config(:mrf_simple,
+            media_removal: [],
+            media_nsfw: [],
+            federated_timeline_removal: [],
+            report_removal: [],
+            reject: [],
+            accept: [],
+            avatar_removal: [],
+            banner_removal: [],
+            reject_deletes: []
+          )
 
   describe "when :media_removal" do
     test "is empty" do
@@ -49,6 +43,19 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
 
       assert SimplePolicy.filter(local_message) == {:ok, local_message}
     end
+
+    test "match with wildcard domain" do
+      Config.put([:mrf_simple, :media_removal], ["*.remote.instance"])
+      media_message = build_media_message()
+      local_message = build_local_message()
+
+      assert SimplePolicy.filter(media_message) ==
+               {:ok,
+                media_message
+                |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
+
+      assert SimplePolicy.filter(local_message) == {:ok, local_message}
+    end
   end
 
   describe "when :media_nsfw" do
@@ -74,6 +81,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
 
       assert SimplePolicy.filter(local_message) == {:ok, local_message}
     end
+
+    test "match with wildcard domain" do
+      Config.put([:mrf_simple, :media_nsfw], ["*.remote.instance"])
+      media_message = build_media_message()
+      local_message = build_local_message()
+
+      assert SimplePolicy.filter(media_message) ==
+               {:ok,
+                media_message
+                |> put_in(["object", "tag"], ["foo", "nsfw"])
+                |> put_in(["object", "sensitive"], true)}
+
+      assert SimplePolicy.filter(local_message) == {:ok, local_message}
+    end
   end
 
   defp build_media_message do
@@ -103,7 +124,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
       report_message = build_report_message()
       local_message = build_local_message()
 
-      assert SimplePolicy.filter(report_message) == {:reject, nil}
+      assert {:reject, _} = SimplePolicy.filter(report_message)
+      assert SimplePolicy.filter(local_message) == {:ok, local_message}
+    end
+
+    test "match with wildcard domain" do
+      Config.put([:mrf_simple, :report_removal], ["*.remote.instance"])
+      report_message = build_report_message()
+      local_message = build_local_message()
+
+      assert {:reject, _} = SimplePolicy.filter(report_message)
       assert SimplePolicy.filter(local_message) == {:ok, local_message}
     end
   end
@@ -146,6 +176,27 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
       assert SimplePolicy.filter(local_message) == {:ok, local_message}
     end
 
+    test "match with wildcard domain" do
+      {actor, ftl_message} = build_ftl_actor_and_message()
+
+      ftl_message_actor_host =
+        ftl_message
+        |> Map.fetch!("actor")
+        |> URI.parse()
+        |> Map.fetch!(:host)
+
+      Config.put([:mrf_simple, :federated_timeline_removal], ["*." <> ftl_message_actor_host])
+      local_message = build_local_message()
+
+      assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
+      assert actor.follower_address in ftl_message["to"]
+      refute actor.follower_address in ftl_message["cc"]
+      refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
+      assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
+
+      assert SimplePolicy.filter(local_message) == {:ok, local_message}
+    end
+
     test "has a matching host but only as:Public in to" do
       {_actor, ftl_message} = build_ftl_actor_and_message()
 
@@ -185,12 +236,28 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
       assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
     end
 
-    test "has a matching host" do
+    test "activity has a matching host" do
       Config.put([:mrf_simple, :reject], ["remote.instance"])
 
       remote_message = build_remote_message()
 
-      assert SimplePolicy.filter(remote_message) == {:reject, nil}
+      assert {:reject, _} = SimplePolicy.filter(remote_message)
+    end
+
+    test "activity matches with wildcard domain" do
+      Config.put([:mrf_simple, :reject], ["*.remote.instance"])
+
+      remote_message = build_remote_message()
+
+      assert {:reject, _} = SimplePolicy.filter(remote_message)
+    end
+
+    test "actor has a matching host" do
+      Config.put([:mrf_simple, :reject], ["remote.instance"])
+
+      remote_user = build_remote_user()
+
+      assert {:reject, _} = SimplePolicy.filter(remote_user)
     end
   end
 
@@ -205,17 +272,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
       assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
     end
 
-    test "is not empty but it doesn't have a matching host" do
+    test "is not empty but activity doesn't have a matching host" do
       Config.put([:mrf_simple, :accept], ["non.matching.remote"])
 
       local_message = build_local_message()
       remote_message = build_remote_message()
 
       assert SimplePolicy.filter(local_message) == {:ok, local_message}
-      assert SimplePolicy.filter(remote_message) == {:reject, nil}
+      assert {:reject, _} = SimplePolicy.filter(remote_message)
     end
 
-    test "has a matching host" do
+    test "activity has a matching host" do
       Config.put([:mrf_simple, :accept], ["remote.instance"])
 
       local_message = build_local_message()
@@ -224,6 +291,24 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
       assert SimplePolicy.filter(local_message) == {:ok, local_message}
       assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
     end
+
+    test "activity matches with wildcard domain" do
+      Config.put([:mrf_simple, :accept], ["*.remote.instance"])
+
+      local_message = build_local_message()
+      remote_message = build_remote_message()
+
+      assert SimplePolicy.filter(local_message) == {:ok, local_message}
+      assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
+    end
+
+    test "actor has a matching host" do
+      Config.put([:mrf_simple, :accept], ["remote.instance"])
+
+      remote_user = build_remote_user()
+
+      assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
+    end
   end
 
   describe "when :avatar_removal" do
@@ -251,6 +336,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
 
       refute filtered["icon"]
     end
+
+    test "match with wildcard domain" 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
@@ -278,6 +372,75 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
 
       refute filtered["image"]
     end
+
+    test "match with wildcard domain" 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
+
+  describe "when :reject_deletes is empty" do
+    setup do: Config.put([:mrf_simple, :reject_deletes], [])
+
+    test "it accepts deletions even from rejected servers" do
+      Config.put([:mrf_simple, :reject], ["remote.instance"])
+
+      deletion_message = build_remote_deletion_message()
+
+      assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+    end
+
+    test "it accepts deletions even from non-whitelisted servers" do
+      Config.put([:mrf_simple, :accept], ["non.matching.remote"])
+
+      deletion_message = build_remote_deletion_message()
+
+      assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+    end
+  end
+
+  describe "when :reject_deletes is not empty but it doesn't have a matching host" do
+    setup do: Config.put([:mrf_simple, :reject_deletes], ["non.matching.remote"])
+
+    test "it accepts deletions even from rejected servers" do
+      Config.put([:mrf_simple, :reject], ["remote.instance"])
+
+      deletion_message = build_remote_deletion_message()
+
+      assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+    end
+
+    test "it accepts deletions even from non-whitelisted servers" do
+      Config.put([:mrf_simple, :accept], ["non.matching.remote"])
+
+      deletion_message = build_remote_deletion_message()
+
+      assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+    end
+  end
+
+  describe "when :reject_deletes has a matching host" do
+    setup do: Config.put([:mrf_simple, :reject_deletes], ["remote.instance"])
+
+    test "it rejects the deletion" do
+      deletion_message = build_remote_deletion_message()
+
+      assert {:reject, _} = SimplePolicy.filter(deletion_message)
+    end
+  end
+
+  describe "when :reject_deletes match with wildcard domain" do
+    setup do: Config.put([:mrf_simple, :reject_deletes], ["*.remote.instance"])
+
+    test "it rejects the deletion" do
+      deletion_message = build_remote_deletion_message()
+
+      assert {:reject, _} = SimplePolicy.filter(deletion_message)
+    end
   end
 
   defp build_local_message do
@@ -306,4 +469,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
       "type" => "Person"
     }
   end
+
+  defp build_remote_deletion_message do
+    %{
+      "type" => "Delete",
+      "actor" => "https://remote.instance/users/bob"
+    }
+  end
 end