From e9e6f37bda2620147a18eb0edb472a1aec46e8f9 Mon Sep 17 00:00:00 2001
From: href <href@random.sh>
Date: Thu, 10 May 2018 18:34:09 +0200
Subject: [PATCH] Chain policies

- The `:pleroma, :instance, :rewrite_policy` can now be either a policy
or a list of policies
- Made a behaviour for MRF policies
---
 lib/pleroma/web/activity_pub/activity_pub.ex      |  5 ++---
 lib/pleroma/web/activity_pub/mrf.ex               | 21 +++++++++++++++++++++
 lib/pleroma/web/activity_pub/mrf/drop_policy.ex   |  2 ++
 lib/pleroma/web/activity_pub/mrf/noop_policy.ex   |  3 +++
 lib/pleroma/web/activity_pub/mrf/simple_policy.ex |  2 ++
 5 files changed, 30 insertions(+), 3 deletions(-)
 create mode 100644 lib/pleroma/web/activity_pub/mrf.ex

diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index fde6e12d7..956c223ee 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -1,6 +1,6 @@
 defmodule Pleroma.Web.ActivityPub.ActivityPub do
   alias Pleroma.{Activity, Repo, Object, Upload, User, Notification}
-  alias Pleroma.Web.ActivityPub.Transmogrifier
+  alias Pleroma.Web.ActivityPub.{Transmogrifier, MRF}
   alias Pleroma.Web.WebFinger
   alias Pleroma.Web.Federator
   alias Pleroma.Web.OStatus
@@ -11,7 +11,6 @@ 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"] || [])
@@ -20,7 +19,7 @@ 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, map} <- @rewrite_policy.filter(map),
+         {:ok, map} <- MRF.filter(map),
          :ok <- insert_full_object(map) do
       {:ok, activity} =
         Repo.insert(%Activity{
diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex
new file mode 100644
index 000000000..6d5aa9515
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf.ex
@@ -0,0 +1,21 @@
+defmodule Pleroma.Web.ActivityPub.MRF do
+
+  @callback filter(Map.t) :: {:ok | :reject, Map.t}
+
+  def filter(object) do
+    get_policies()
+    |> Enum.reduce({:ok, object}, fn
+      (policy, {:ok, object}) ->
+        policy.filter(object)
+      (_, error) -> error
+    end)
+  end
+
+  def get_policies() do
+    Application.get_env(:pleroma, :instance, [])
+    |> Keyword.get(:rewrite_policy, [])
+    |> get_policies()
+  end
+  def get_policies(policy) when is_atom(policy), do: [policy]
+  def get_policies(policies) when is_list(policies), do: policies
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
index 4333bca28..811947943 100644
--- a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
@@ -1,6 +1,8 @@
 defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
   require Logger
+  @behaviour Pleroma.Web.ActivityPub.MRF
 
+  @impl true
   def filter(object) do
     Logger.info("REJECTING #{inspect(object)}")
     {:reject, object}
diff --git a/lib/pleroma/web/activity_pub/mrf/noop_policy.ex b/lib/pleroma/web/activity_pub/mrf/noop_policy.ex
index 9dd3acb04..e26f60d26 100644
--- a/lib/pleroma/web/activity_pub/mrf/noop_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/noop_policy.ex
@@ -1,4 +1,7 @@
 defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
+  @behaviour Pleroma.Web.ActivityPub.MRF
+
+  @impl true
   def filter(object) do
     {:ok, object}
   end
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index d840d759d..8d770387d 100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -1,5 +1,6 @@
 defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
   alias Pleroma.User
+  @behaviour Pleroma.Web.ActivityPub.MRF
 
   @mrf_policy Application.get_env(:pleroma, :mrf_simple)
 
@@ -69,6 +70,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
     end
   end
 
+  @impl true
   def filter(object) do
     actor_info = URI.parse(object["actor"])