ActivityPub MRF: implement the SimplePolicy policy
authorWilliam Pitcock <nenolod@dereferenced.org>
Sat, 14 Apr 2018 11:31:12 +0000 (11:31 +0000)
committerWilliam Pitcock <nenolod@dereferenced.org>
Sat, 14 Apr 2018 11:32:45 +0000 (06:32 -0500)
config/config.exs
lib/pleroma/web/activity_pub/mrf/simple_policy.ex [new file with mode: 0644]

index 660ba17755413cb21ff5c3dcf5a572cd80b95308..b0f4578d5e537b27c62c3ce1a0f83c7a0d27fc8f 100644 (file)
@@ -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 (file)
index 0000000..1322744
--- /dev/null
@@ -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