From 4a178b3d6589bbb9ab08e8a768cc0a3a5d5e9629 Mon Sep 17 00:00:00 2001
From: William Pitcock <nenolod@dereferenced.org>
Date: Sat, 14 Apr 2018 09:20:18 +0000
Subject: [PATCH 1/3] ActivityPub: implement MRF core hook and baseline noop
 policy object

---
 config/config.exs                               | 3 ++-
 lib/pleroma/web/activity_pub/activity_pub.ex    | 6 +++++-
 lib/pleroma/web/activity_pub/mrf/drop_policy.ex | 8 ++++++++
 lib/pleroma/web/activity_pub/mrf/noop_policy.ex | 5 +++++
 4 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 lib/pleroma/web/activity_pub/mrf/drop_policy.ex
 create mode 100644 lib/pleroma/web/activity_pub/mrf/noop_policy.ex

diff --git a/config/config.exs b/config/config.exs
index 68c054457..660ba1775 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -52,7 +52,8 @@ config :pleroma, :instance,
   limit: 5000,
   upload_limit: 16_000_000,
   registrations_open: true,
-  federating: true
+  federating: true,
+  rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy
 
 config :pleroma, :media_proxy,
   enabled: false,
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 04b50c1cc..bfb0e04be 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -10,6 +10,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   @httpoison Application.get_env(:pleroma, :httpoison)
 
+  @instance Application.get_env(:pleroma, :instance)
+  @rewrite_policy Keyword.get(@instance, :rewrite_policy)
+
   def get_recipients(data) do
     (data["to"] || []) ++ (data["cc"] || [])
   end
@@ -17,7 +20,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
   def insert(map, local \\ true) when is_map(map) do
     with nil <- Activity.get_by_ap_id(map["id"]),
          map <- lazy_put_activity_defaults(map),
-         :ok <- insert_full_object(map) do
+         :ok <- insert_full_object(map),
+         {:ok, map} <- @rewrite_policy.filter(map) do
       {:ok, activity} =
         Repo.insert(%Activity{
           data: map,
diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
new file mode 100644
index 000000000..4333bca28
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
@@ -0,0 +1,8 @@
+defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
+  require Logger
+
+  def filter(object) do
+    Logger.info("REJECTING #{inspect(object)}")
+    {:reject, object}
+  end
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/noop_policy.ex b/lib/pleroma/web/activity_pub/mrf/noop_policy.ex
new file mode 100644
index 000000000..9dd3acb04
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/noop_policy.ex
@@ -0,0 +1,5 @@
+defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
+  def filter(object) do
+    {:ok, object}
+  end
+end

From d24ddd9fb9fb5254b2e80cbe70ba9bc83f2cd0da Mon Sep 17 00:00:00 2001
From: William Pitcock <nenolod@dereferenced.org>
Date: Sat, 14 Apr 2018 11:31:12 +0000
Subject: [PATCH 2/3] ActivityPub MRF: implement the SimplePolicy policy

---
 config/config.exs                             |  6 ++
 .../web/activity_pub/mrf/simple_policy.ex     | 65 +++++++++++++++++++
 2 files changed, 71 insertions(+)
 create mode 100644 lib/pleroma/web/activity_pub/mrf/simple_policy.ex

diff --git a/config/config.exs b/config/config.exs
index 660ba1775..b0f4578d5 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -55,6 +55,12 @@ config :pleroma, :instance,
   federating: true,
   rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy
 
+config :pleroma, :mrf_simple,
+  media_removal: [],
+  media_nsfw: [],
+  federated_timeline_removal: [],
+  reject: []
+
 config :pleroma, :media_proxy,
   enabled: false,
   redirect_on_failure: true
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
new file mode 100644
index 000000000..1322744f1
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -0,0 +1,65 @@
+defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
+  alias Pleroma.User
+
+  @mrf_policy Application.get_env(:pleroma, :mrf_simple)
+
+  @reject Keyword.get(@mrf_policy, :reject)
+  defp check_reject(actor_info, object) do
+    if actor_info.host in @reject do
+      {:reject, nil}
+    else
+      {:ok, object}
+    end
+  end
+
+  @media_removal Keyword.get(@mrf_policy, :media_removal)
+  defp check_media_removal(actor_info, object) do
+    if actor_info.host in @media_removal do
+      object = Map.delete(object, "attachments")
+    end
+
+    {:ok, object}
+  end
+
+  @media_nsfw Keyword.get(@mrf_policy, :media_nsfw)
+  defp check_media_nsfw(actor_info, object) do
+    if actor_info.host in @media_nsfw and object["attachment"] != nil and length(object["attachment"]) > 0 do
+      tags = (object["tag"] || []) ++ ["nsfw"]
+      object = Map.put(object, "tags", tags)
+      object = Map.put(object, "sensitive", true)
+    end
+
+    {:ok, object}
+  end
+
+  @ftl_removal Keyword.get(@mrf_policy, :federated_timeline_removal)
+  defp check_ftl_removal(actor_info, object) do
+    if actor_info.host in @ftl_removal do
+      user = User.get_by_ap_id(object["actor"])
+
+      # flip to/cc relationship to make the post unlisted
+      if "https://www.w3.org/ns/activitystreams#Public" in object["to"] and user.follower_address in object["cc"] do
+        to = List.delete(object["to"], "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
+        cc = List.delete(object["cc"], user.follower_address) ++ ["https://www.w3.org/ns/activitystreams#Public"]
+
+        object = Map.put(object, "to", to)
+        object = Map.put(object, "cc", cc)
+      end
+    end
+
+    {:ok, object}
+  end
+
+  def filter(object) do
+    actor_info = URI.parse(object["actor"])
+
+    with {:ok, object} <- check_reject(actor_info, object),
+         {:ok, object} <- check_media_removal(actor_info, object),
+         {:ok, object} <- check_media_nsfw(actor_info, object),
+         {:ok, object} <- check_ftl_removal(actor_info, object) do
+      {:ok, object}
+    else
+      e -> {:reject, nil}
+    end
+  end
+end

From f08f9d449811d7a67b5c901889b0fef2e9ab8da9 Mon Sep 17 00:00:00 2001
From: "nenolod@dereferenced.org" <William Pitcock>
Date: Thu, 19 Apr 2018 12:29:35 +0000
Subject: [PATCH 3/3] ActivityPub MRF: fix nsfw tagging of objects with
 attachments by looking at the right object (the child in this case)

---
 lib/pleroma/web/activity_pub/mrf/simple_policy.ex | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index 1322744f1..cb8eaf1ec 100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -23,10 +23,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
 
   @media_nsfw Keyword.get(@mrf_policy, :media_nsfw)
   defp check_media_nsfw(actor_info, object) do
-    if actor_info.host in @media_nsfw and object["attachment"] != nil and length(object["attachment"]) > 0 do
-      tags = (object["tag"] || []) ++ ["nsfw"]
-      object = Map.put(object, "tags", tags)
-      object = Map.put(object, "sensitive", true)
+    child_object = object["object"]
+    if actor_info.host in @media_nsfw and child_object["attachment"] != nil and length(child_object["attachment"]) > 0 do
+      tags = (child_object["tag"] || []) ++ ["nsfw"]
+      child_object = Map.put(child_object, "tags", tags)
+      child_object = Map.put(child_object, "sensitive", true)
+      object = Map.put(object, "object", child_object)
     end
 
     {:ok, object}