tests MRF filters
authorMaksim <parallel588@gmail.com>
Wed, 10 Jul 2019 05:12:21 +0000 (05:12 +0000)
committerkaniini <nenolod@gmail.com>
Wed, 10 Jul 2019 05:12:21 +0000 (05:12 +0000)
13 files changed:
lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
lib/pleroma/web/activity_pub/mrf/tag_policy.ex
lib/pleroma/web/activity_pub/mrf/user_allowlist_policy.ex [moved from lib/pleroma/web/activity_pub/mrf/user_allowlist.ex with 86% similarity]
mix.lock
test/web/activity_pub/mrf/ensure_re_prepended_test.exs [new file with mode: 0644]
test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs [new file with mode: 0644]
test/web/activity_pub/mrf/normalize_markup_test.exs [new file with mode: 0644]
test/web/activity_pub/mrf/reject_non_public_test.exs [new file with mode: 0644]
test/web/activity_pub/mrf/tag_policy_test.exs [new file with mode: 0644]
test/web/activity_pub/mrf/user_allowlist_policy_test.exs [new file with mode: 0644]

index 15d8514be577f1117cae0e868d523b3412d79182..2d03df68afefd9943576d9ec5713d72015b2fd3a 100644 (file)
@@ -9,8 +9,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
   @behaviour Pleroma.Web.ActivityPub.MRF
 
   @reply_prefix Regex.compile!("^re:[[:space:]]*", [:caseless])
+
   def filter_by_summary(
-        %{"summary" => parent_summary} = _parent,
+        %{data: %{"summary" => parent_summary}} = _in_reply_to,
         %{"summary" => child_summary} = child
       )
       when not is_nil(child_summary) and byte_size(child_summary) > 0 and
@@ -24,17 +25,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
     end
   end
 
-  def filter_by_summary(_parent, child), do: child
-
-  def filter(%{"type" => activity_type} = object) when activity_type == "Create" do
-    child = object["object"]
-    in_reply_to = Object.normalize(child["inReplyTo"])
+  def filter_by_summary(_in_reply_to, child), do: child
 
+  def filter(%{"type" => "Create", "object" => child_object} = object) do
     child =
-      if(in_reply_to,
-        do: filter_by_summary(in_reply_to.data, child),
-        else: child
-      )
+      child_object["inReplyTo"]
+      |> Object.normalize(child_object["inReplyTo"])
+      |> filter_by_summary(child_object)
 
     object = Map.put(object, "object", child)
 
index f30fee0d506068cfdaa588c2c03515cdcb542ad1..86a48bda58dc4a0c9e2e2b2f63a2142fc587d7b1 100644 (file)
@@ -10,19 +10,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
   def filter(
         %{
           "type" => "Create",
-          "object" => %{"content" => content, "attachment" => _attachment} = child_object
+          "object" => %{"content" => content, "attachment" => _} = _child_object
         } = object
       )
       when content in [".", "<p>.</p>"] do
-    child_object =
-      child_object
-      |> Map.put("content", "")
-
-    object =
-      object
-      |> Map.put("object", child_object)
-
-    {:ok, object}
+    {:ok, put_in(object, ["object", "content"], "")}
   end
 
   @impl true
index 9c87c69638b080149fa4eb76150e7a157df8ce2d..c269d0f892a0f399c7a820c4d2781bc71bc327ae 100644 (file)
@@ -8,18 +8,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
 
   @behaviour Pleroma.Web.ActivityPub.MRF
 
-  def filter(%{"type" => activity_type} = object) when activity_type == "Create" do
+  def filter(%{"type" => "Create", "object" => child_object} = object) do
     scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
 
-    child = object["object"]
-
     content =
-      child["content"]
+      child_object["content"]
       |> HTML.filter_tags(scrub_policy)
 
-    child = Map.put(child, "content", content)
-
-    object = Map.put(object, "object", child)
+    object = put_in(object, ["object", "content"], content)
 
     {:ok, object}
   end
index ea3df1b4d0eb98a894f35144c64597bbac15930a..da13fd7c7b9308030f690b4f364fa7b8891340af 100644 (file)
@@ -3,46 +3,42 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
-  alias Pleroma.User
   @moduledoc "Rejects non-public (followers-only, direct) activities"
+
+  alias Pleroma.Config
+  alias Pleroma.User
+
   @behaviour Pleroma.Web.ActivityPub.MRF
 
+  @public "https://www.w3.org/ns/activitystreams#Public"
+
   @impl true
   def filter(%{"type" => "Create"} = object) do
     user = User.get_cached_by_ap_id(object["actor"])
-    public = "https://www.w3.org/ns/activitystreams#Public"
 
     # Determine visibility
     visibility =
       cond do
-        public in object["to"] -> "public"
-        public in object["cc"] -> "unlisted"
+        @public in object["to"] -> "public"
+        @public in object["cc"] -> "unlisted"
         user.follower_address in object["to"] -> "followers"
         true -> "direct"
       end
 
-    policy = Pleroma.Config.get(:mrf_rejectnonpublic)
+    policy = Config.get(:mrf_rejectnonpublic)
+
+    cond do
+      visibility in ["public", "unlisted"] ->
+        {:ok, object}
 
-    case visibility do
-      "public" ->
+      visibility == "followers" and Keyword.get(policy, :allow_followersonly) ->
         {:ok, object}
 
-      "unlisted" ->
+      visibility == "direct" and Keyword.get(policy, :allow_direct) ->
         {:ok, object}
 
-      "followers" ->
-        with true <- Keyword.get(policy, :allow_followersonly) do
-          {:ok, object}
-        else
-          _e -> {:reject, nil}
-        end
-
-      "direct" ->
-        with true <- Keyword.get(policy, :allow_direct) do
-          {:ok, object}
-        else
-          _e -> {:reject, nil}
-        end
+      true ->
+        {:reject, nil}
     end
   end
 
index 6683b8d8e6a294b6ab19797f5f4d495fdfd08e1a..b42c4ed76b01612335f1744d0da6740cff6d12c3 100644 (file)
@@ -19,12 +19,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
      - `mrf_tag:disable-any-subscription`: Reject any follow requests
   """
 
+  @public "https://www.w3.org/ns/activitystreams#Public"
+
   defp get_tags(%User{tags: tags}) when is_list(tags), do: tags
   defp get_tags(_), do: []
 
   defp process_tag(
          "mrf_tag:media-force-nsfw",
-         %{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
+         %{
+           "type" => "Create",
+           "object" => %{"attachment" => child_attachment} = object
+         } = message
        )
        when length(child_attachment) > 0 do
     tags = (object["tag"] || []) ++ ["nsfw"]
@@ -41,7 +46,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
 
   defp process_tag(
          "mrf_tag:media-strip",
-         %{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
+         %{
+           "type" => "Create",
+           "object" => %{"attachment" => child_attachment} = object
+         } = message
        )
        when length(child_attachment) > 0 do
     object = Map.delete(object, "attachment")
@@ -52,19 +60,22 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
 
   defp process_tag(
          "mrf_tag:force-unlisted",
-         %{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
+         %{
+           "type" => "Create",
+           "to" => to,
+           "cc" => cc,
+           "actor" => actor,
+           "object" => object
+         } = message
        ) do
     user = User.get_cached_by_ap_id(actor)
 
-    if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") do
-      to =
-        List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
-
-      cc =
-        List.delete(cc, user.follower_address) ++ ["https://www.w3.org/ns/activitystreams#Public"]
+    if Enum.member?(to, @public) do
+      to = List.delete(to, @public) ++ [user.follower_address]
+      cc = List.delete(cc, user.follower_address) ++ [@public]
 
       object =
-        message["object"]
+        object
         |> Map.put("to", to)
         |> Map.put("cc", cc)
 
@@ -82,19 +93,22 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
 
   defp process_tag(
          "mrf_tag:sandbox",
-         %{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
+         %{
+           "type" => "Create",
+           "to" => to,
+           "cc" => cc,
+           "actor" => actor,
+           "object" => object
+         } = message
        ) do
     user = User.get_cached_by_ap_id(actor)
 
-    if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") or
-         Enum.member?(cc, "https://www.w3.org/ns/activitystreams#Public") do
-      to =
-        List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
-
-      cc = List.delete(cc, "https://www.w3.org/ns/activitystreams#Public")
+    if Enum.member?(to, @public) or Enum.member?(cc, @public) do
+      to = List.delete(to, @public) ++ [user.follower_address]
+      cc = List.delete(cc, @public)
 
       object =
-        message["object"]
+        object
         |> Map.put("to", to)
         |> Map.put("cc", cc)
 
@@ -123,7 +137,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
     end
   end
 
-  defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow"}), do: {:reject, nil}
+  defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow"}),
+    do: {:reject, nil}
 
   defp process_tag(_, message), do: {:ok, message}
 
similarity index 86%
rename from lib/pleroma/web/activity_pub/mrf/user_allowlist.ex
rename to lib/pleroma/web/activity_pub/mrf/user_allowlist_policy.ex
index 47663414a38773e0b1a6e860ff6055a76f43d112..e35d2c422e1956971077397431c065da1c1944bf 100644 (file)
@@ -21,7 +21,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
   @impl true
   def filter(%{"actor" => actor} = object) do
     actor_info = URI.parse(actor)
-    allow_list = Config.get([:mrf_user_allowlist, String.to_atom(actor_info.host)], [])
+
+    allow_list =
+      Config.get(
+        [:mrf_user_allowlist, String.to_atom(actor_info.host)],
+        []
+      )
 
     filter_by_list(object, allow_list)
   end
index e711be635b801af7690f4ba9b4a181bae9aee6ca..bd6ab910088812f3387ef1b38ef6723e3e89fa5c 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -76,6 +76,7 @@
   "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
   "recon": {:git, "https://github.com/ferd/recon.git", "75d70c7c08926d2f24f1ee6de14ee50fe8a52763", [tag: "2.4.0"]},
   "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
+  "stream_data": {:hex, :stream_data, "0.4.3", "62aafd870caff0849a5057a7ec270fad0eb86889f4d433b937d996de99e3db25", [:mix], [], "hexpm"},
   "swoosh": {:hex, :swoosh, "0.20.0", "9a6c13822c9815993c03b6f8fccc370fcffb3c158d9754f67b1fdee6b3a5d928", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.12", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"},
   "syslog": {:git, "https://github.com/Vagabond/erlang-syslog.git", "4a6c6f2c996483e86c1320e9553f91d337bcb6aa", [tag: "1.0.5"]},
   "telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
diff --git a/test/web/activity_pub/mrf/ensure_re_prepended_test.exs b/test/web/activity_pub/mrf/ensure_re_prepended_test.exs
new file mode 100644 (file)
index 0000000..dbc8b9e
--- /dev/null
@@ -0,0 +1,82 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
+  use Pleroma.DataCase
+
+  alias Pleroma.Activity
+  alias Pleroma.Object
+  alias Pleroma.Web.ActivityPub.MRF.EnsureRePrepended
+
+  describe "rewrites summary" do
+    test "it adds `re:` to summary object when child summary and parent summary equal" do
+      message = %{
+        "type" => "Create",
+        "object" => %{
+          "summary" => "object-summary",
+          "inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
+        }
+      }
+
+      assert {:ok, res} = EnsureRePrepended.filter(message)
+      assert res["object"]["summary"] == "re: object-summary"
+    end
+
+    test "it adds `re:` to summary object when child summary containts re-subject of parent summary " do
+      message = %{
+        "type" => "Create",
+        "object" => %{
+          "summary" => "object-summary",
+          "inReplyTo" => %Activity{object: %Object{data: %{"summary" => "re: object-summary"}}}
+        }
+      }
+
+      assert {:ok, res} = EnsureRePrepended.filter(message)
+      assert res["object"]["summary"] == "re: object-summary"
+    end
+  end
+
+  describe "skip filter" do
+    test "it skip if type isn't 'Create'" do
+      message = %{
+        "type" => "Annotation",
+        "object" => %{"summary" => "object-summary"}
+      }
+
+      assert {:ok, res} = EnsureRePrepended.filter(message)
+      assert res == message
+    end
+
+    test "it skip if summary is empty" do
+      message = %{
+        "type" => "Create",
+        "object" => %{
+          "inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
+        }
+      }
+
+      assert {:ok, res} = EnsureRePrepended.filter(message)
+      assert res == message
+    end
+
+    test "it skip if inReplyTo is empty" do
+      message = %{"type" => "Create", "object" => %{"summary" => "summary"}}
+      assert {:ok, res} = EnsureRePrepended.filter(message)
+      assert res == message
+    end
+
+    test "it skip if parent and child summary isn't equal" do
+      message = %{
+        "type" => "Create",
+        "object" => %{
+          "summary" => "object-summary",
+          "inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
+        }
+      }
+
+      assert {:ok, res} = EnsureRePrepended.filter(message)
+      assert res == message
+    end
+  end
+end
diff --git a/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs b/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs
new file mode 100644 (file)
index 0000000..63ed711
--- /dev/null
@@ -0,0 +1,37 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do
+  use Pleroma.DataCase
+  alias Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy
+
+  test "it clears content object" do
+    message = %{
+      "type" => "Create",
+      "object" => %{"content" => ".", "attachment" => "image"}
+    }
+
+    assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
+    assert res["object"]["content"] == ""
+
+    message = put_in(message, ["object", "content"], "<p>.</p>")
+    assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
+    assert res["object"]["content"] == ""
+  end
+
+  @messages [
+    %{
+      "type" => "Create",
+      "object" => %{"content" => "test", "attachment" => "image"}
+    },
+    %{"type" => "Create", "object" => %{"content" => "."}},
+    %{"type" => "Create", "object" => %{"content" => "<p>.</p>"}}
+  ]
+  test "it skips filter" do
+    Enum.each(@messages, fn message ->
+      assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
+      assert res == message
+    end)
+  end
+end
diff --git a/test/web/activity_pub/mrf/normalize_markup_test.exs b/test/web/activity_pub/mrf/normalize_markup_test.exs
new file mode 100644 (file)
index 0000000..3916a1f
--- /dev/null
@@ -0,0 +1,42 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
+  use Pleroma.DataCase
+  alias Pleroma.Web.ActivityPub.MRF.NormalizeMarkup
+
+  @html_sample """
+  <b>this is in bold</b>
+  <p>this is a paragraph</p>
+  this is a linebreak<br />
+  this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
+  this is a link with not allowed "rel" attribute: <a href="http://example.com/" rel="tag noallowed">example.com</a>
+  this is an image: <img src="http://example.com/image.jpg"><br />
+  <script>alert('hacked')</script>
+  """
+
+  test "it filter html tags" do
+    expected = """
+    <b>this is in bold</b>
+    <p>this is a paragraph</p>
+    this is a linebreak<br />
+    this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
+    this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
+    this is an image: <img src="http://example.com/image.jpg" /><br />
+    alert('hacked')
+    """
+
+    message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
+
+    assert {:ok, res} = NormalizeMarkup.filter(message)
+    assert res["object"]["content"] == expected
+  end
+
+  test "it skips filter if type isn't `Create`" do
+    message = %{"type" => "Note", "object" => %{}}
+
+    assert {:ok, res} = NormalizeMarkup.filter(message)
+    assert res == message
+  end
+end
diff --git a/test/web/activity_pub/mrf/reject_non_public_test.exs b/test/web/activity_pub/mrf/reject_non_public_test.exs
new file mode 100644 (file)
index 0000000..fdf6b24
--- /dev/null
@@ -0,0 +1,105 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do
+  use Pleroma.DataCase
+  import Pleroma.Factory
+
+  alias Pleroma.Web.ActivityPub.MRF.RejectNonPublic
+
+  setup do
+    policy = Pleroma.Config.get([:mrf_rejectnonpublic])
+    on_exit(fn -> Pleroma.Config.put([:mrf_rejectnonpublic], policy) end)
+
+    :ok
+  end
+
+  describe "public message" do
+    test "it's allowed when address is public" do
+      actor = insert(:user, follower_address: "test-address")
+
+      message = %{
+        "actor" => actor.ap_id,
+        "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+        "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
+        "type" => "Create"
+      }
+
+      assert {:ok, message} = RejectNonPublic.filter(message)
+    end
+
+    test "it's allowed when cc address contain public address" do
+      actor = insert(:user, follower_address: "test-address")
+
+      message = %{
+        "actor" => actor.ap_id,
+        "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+        "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
+        "type" => "Create"
+      }
+
+      assert {:ok, message} = RejectNonPublic.filter(message)
+    end
+  end
+
+  describe "followers message" do
+    test "it's allowed when addrer of message in the follower addresses of user and it enabled in config" do
+      actor = insert(:user, follower_address: "test-address")
+
+      message = %{
+        "actor" => actor.ap_id,
+        "to" => ["test-address"],
+        "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
+        "type" => "Create"
+      }
+
+      Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], true)
+      assert {:ok, message} = RejectNonPublic.filter(message)
+    end
+
+    test "it's rejected when addrer of message in the follower addresses of user and it disabled in config" do
+      actor = insert(:user, follower_address: "test-address")
+
+      message = %{
+        "actor" => actor.ap_id,
+        "to" => ["test-address"],
+        "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
+        "type" => "Create"
+      }
+
+      Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], false)
+      assert {:reject, nil} = RejectNonPublic.filter(message)
+    end
+  end
+
+  describe "direct message" do
+    test "it's allows when direct messages are allow" do
+      actor = insert(:user)
+
+      message = %{
+        "actor" => actor.ap_id,
+        "to" => ["https://www.w3.org/ns/activitystreams#Publid"],
+        "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
+        "type" => "Create"
+      }
+
+      Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], true)
+      assert {:ok, message} = RejectNonPublic.filter(message)
+    end
+
+    test "it's reject when direct messages aren't allow" do
+      actor = insert(:user)
+
+      message = %{
+        "actor" => actor.ap_id,
+        "to" => ["https://www.w3.org/ns/activitystreams#Publid~~~"],
+        "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
+        "type" => "Create"
+      }
+
+      Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], false)
+      assert {:reject, nil} = RejectNonPublic.filter(message)
+    end
+  end
+end
diff --git a/test/web/activity_pub/mrf/tag_policy_test.exs b/test/web/activity_pub/mrf/tag_policy_test.exs
new file mode 100644 (file)
index 0000000..4aa3531
--- /dev/null
@@ -0,0 +1,123 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
+  use Pleroma.DataCase
+  import Pleroma.Factory
+
+  alias Pleroma.Web.ActivityPub.MRF.TagPolicy
+  @public "https://www.w3.org/ns/activitystreams#Public"
+
+  describe "mrf_tag:disable-any-subscription" do
+    test "rejects message" do
+      actor = insert(:user, tags: ["mrf_tag:disable-any-subscription"])
+      message = %{"object" => actor.ap_id, "type" => "Follow"}
+      assert {:reject, nil} = TagPolicy.filter(message)
+    end
+  end
+
+  describe "mrf_tag:disable-remote-subscription" do
+    test "rejects non-local follow requests" do
+      actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
+      follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: false)
+      message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
+      assert {:reject, nil} = TagPolicy.filter(message)
+    end
+
+    test "allows non-local follow requests" do
+      actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
+      follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: true)
+      message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
+      assert {:ok, message} = TagPolicy.filter(message)
+    end
+  end
+
+  describe "mrf_tag:sandbox" do
+    test "removes from public timelines" do
+      actor = insert(:user, tags: ["mrf_tag:sandbox"])
+
+      message = %{
+        "actor" => actor.ap_id,
+        "type" => "Create",
+        "object" => %{},
+        "to" => [@public, "f"],
+        "cc" => [@public, "d"]
+      }
+
+      except_message = %{
+        "actor" => actor.ap_id,
+        "type" => "Create",
+        "object" => %{"to" => ["f", actor.follower_address], "cc" => ["d"]},
+        "to" => ["f", actor.follower_address],
+        "cc" => ["d"]
+      }
+
+      assert TagPolicy.filter(message) == {:ok, except_message}
+    end
+  end
+
+  describe "mrf_tag:force-unlisted" do
+    test "removes from the federated timeline" do
+      actor = insert(:user, tags: ["mrf_tag:force-unlisted"])
+
+      message = %{
+        "actor" => actor.ap_id,
+        "type" => "Create",
+        "object" => %{},
+        "to" => [@public, "f"],
+        "cc" => [actor.follower_address, "d"]
+      }
+
+      except_message = %{
+        "actor" => actor.ap_id,
+        "type" => "Create",
+        "object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]},
+        "to" => ["f", actor.follower_address],
+        "cc" => ["d", @public]
+      }
+
+      assert TagPolicy.filter(message) == {:ok, except_message}
+    end
+  end
+
+  describe "mrf_tag:media-strip" do
+    test "removes attachments" do
+      actor = insert(:user, tags: ["mrf_tag:media-strip"])
+
+      message = %{
+        "actor" => actor.ap_id,
+        "type" => "Create",
+        "object" => %{"attachment" => ["file1"]}
+      }
+
+      except_message = %{
+        "actor" => actor.ap_id,
+        "type" => "Create",
+        "object" => %{}
+      }
+
+      assert TagPolicy.filter(message) == {:ok, except_message}
+    end
+  end
+
+  describe "mrf_tag:media-force-nsfw" do
+    test "Mark as sensitive on presence of attachments" do
+      actor = insert(:user, tags: ["mrf_tag:media-force-nsfw"])
+
+      message = %{
+        "actor" => actor.ap_id,
+        "type" => "Create",
+        "object" => %{"tag" => ["test"], "attachment" => ["file1"]}
+      }
+
+      except_message = %{
+        "actor" => actor.ap_id,
+        "type" => "Create",
+        "object" => %{"tag" => ["test", "nsfw"], "attachment" => ["file1"], "sensitive" => true}
+      }
+
+      assert TagPolicy.filter(message) == {:ok, except_message}
+    end
+  end
+end
diff --git a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
new file mode 100644 (file)
index 0000000..6519e23
--- /dev/null
@@ -0,0 +1,36 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
+  use Pleroma.DataCase
+  import Pleroma.Factory
+
+  alias Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy
+
+  setup do
+    policy = Pleroma.Config.get([:mrf_user_allowlist]) || []
+    on_exit(fn -> Pleroma.Config.put([:mrf_user_allowlist], policy) end)
+
+    :ok
+  end
+
+  test "pass filter if allow list is empty" do
+    actor = insert(:user)
+    message = %{"actor" => actor.ap_id}
+    assert UserAllowListPolicy.filter(message) == {:ok, message}
+  end
+
+  test "pass filter if allow list isn't empty and user in allow list" do
+    actor = insert(:user)
+    Pleroma.Config.put([:mrf_user_allowlist, :localhost], [actor.ap_id, "test-ap-id"])
+    message = %{"actor" => actor.ap_id}
+    assert UserAllowListPolicy.filter(message) == {:ok, message}
+  end
+
+  test "rejected if allow list isn't empty and user not in allow list" do
+    actor = insert(:user)
+    Pleroma.Config.put([:mrf_user_allowlist, :localhost], ["test-ap-id"])
+    message = %{"actor" => actor.ap_id}
+    assert UserAllowListPolicy.filter(message) == {:reject, nil}
+  end
+end