From 10ef532c63431811b3998ed7b14aea21755a2b57 Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
Date: Tue, 7 Jul 2020 07:06:29 +0200
Subject: [PATCH] AP C2S: Restrict character limit on Note

---
 .../activity_pub/activity_pub_controller.ex   | 35 ++++++++++++-------
 .../activity_pub_controller_test.exs          | 16 +++++++++
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 220c4fe52..732c44271 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -399,21 +399,30 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
 
   defp handle_user_activity(
          %User{} = user,
-         %{"type" => "Create", "object" => %{"type" => "Note"}} = params
+         %{"type" => "Create", "object" => %{"type" => "Note"} = object} = params
        ) do
-    object =
-      params["object"]
-      |> Map.merge(Map.take(params, ["to", "cc"]))
-      |> Map.put("attributedTo", user.ap_id())
-      |> Transmogrifier.fix_object()
+    content = if is_binary(object["content"]), do: object["content"], else: ""
+    name = if is_binary(object["name"]), do: object["name"], else: ""
+    summary = if is_binary(object["summary"]), do: object["summary"], else: ""
+    length = String.length(content <> name <> summary)
 
-    ActivityPub.create(%{
-      to: params["to"],
-      actor: user,
-      context: object["context"],
-      object: object,
-      additional: Map.take(params, ["cc"])
-    })
+    if length > Pleroma.Config.get([:instance, :limit]) do
+      {:error, dgettext("errors", "Note is over the character limit")}
+    else
+      object =
+        object
+        |> Map.merge(Map.take(params, ["to", "cc"]))
+        |> Map.put("attributedTo", user.ap_id())
+        |> Transmogrifier.fix_object()
+
+      ActivityPub.create(%{
+        to: params["to"],
+        actor: user,
+        context: object["context"],
+        object: object,
+        additional: Map.take(params, ["cc"])
+      })
+    end
   end
 
   defp handle_user_activity(%User{} = user, %{"type" => "Delete"} = params) do
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index 57988dc1e..0517571f2 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -905,6 +905,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
   end
 
   describe "POST /users/:nickname/outbox (C2S)" do
+    setup do: clear_config([:instance, :limit])
+
     setup do
       [
         activity: %{
@@ -1121,6 +1123,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
       assert cirno_object.data["actor"] == cirno.ap_id
       assert cirno_object.data["attributedTo"] == cirno.ap_id
     end
+
+    test "Character limitation", %{conn: conn, activity: activity} do
+      Pleroma.Config.put([:instance, :limit], 5)
+      user = insert(:user)
+
+      result =
+        conn
+        |> assign(:user, user)
+        |> put_req_header("content-type", "application/activity+json")
+        |> post("/users/#{user.nickname}/outbox", activity)
+        |> json_response(400)
+
+      assert result == "Note is over the character limit"
+    end
   end
 
   describe "/relay/followers" do