From 35ef470d000c53e21c6f867d53ca3a83260d93b8 Mon Sep 17 00:00:00 2001
From: Sadposter <hannah+pleroma@coffee-and-dreams.uk>
Date: Mon, 2 Sep 2019 12:15:21 +0100
Subject: [PATCH 1/6] truncate fields for remote users instead

---
 lib/pleroma/user/info.ex |  7 +++++++
 test/user_test.exs       | 17 +++++++++++++----
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex
index 779bfbc18..0beb2f721 100644
--- a/lib/pleroma/user/info.ex
+++ b/lib/pleroma/user/info.ex
@@ -242,6 +242,7 @@ defmodule Pleroma.User.Info do
   end
 
   def remote_user_creation(info, params) do
+    params = Map.put(params, "fields", Enum.map(params["fields"], &truncate_field/1))
     info
     |> cast(params, [
       :ap_enabled,
@@ -326,6 +327,12 @@ defmodule Pleroma.User.Info do
 
   defp valid_field?(_), do: false
 
+  defp truncate_field(%{"name" => name, "value" => value}) do
+    {name, _chopped} = String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255))
+    {value, _chopped} = String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255))
+    %{"name" => name, "value" => value}
+  end
+
   @spec confirmation_changeset(Info.t(), keyword()) :: Changeset.t()
   def confirmation_changeset(info, opts) do
     need_confirmation? = Keyword.get(opts, :need_confirmation)
diff --git a/test/user_test.exs b/test/user_test.exs
index 2cbc1f525..68a469fe3 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -1117,11 +1117,20 @@ defmodule Pleroma.UserTest do
     assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
   end
 
-  test "insert or update a user from given data" do
-    user = insert(:user, %{nickname: "nick@name.de"})
-    data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
+  describe "insert or update a user from given data" do
+    test "with normal data" do
+        user = insert(:user, %{nickname: "nick@name.de"})
+        data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
 
-    assert {:ok, %User{}} = User.insert_or_update_user(data)
+        assert {:ok, %User{}} = User.insert_or_update_user(data)
+    end
+
+    test "with overly long fields" do
+        current_max_length = Pleroma.Config.get([:instance, :account_field_value_length], 255)
+        user = insert(:user, nickname: "nickname@supergood.domain")
+        data = %{ap_id: user.ap_id, info: %{ fields: [%{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}] }}
+        assert {:ok, %User{}} = User.insert_or_update_user(data)
+    end
   end
 
   describe "per-user rich-text filtering" do

From 05c935c3961e4c1a20c7713611920318d45d4b57 Mon Sep 17 00:00:00 2001
From: Sadposter <hannah+pleroma@coffee-and-dreams.uk>
Date: Mon, 2 Sep 2019 12:15:40 +0100
Subject: [PATCH 2/6] mix format

---
 lib/pleroma/user/info.ex |  9 +++++++--
 test/user_test.exs       | 23 ++++++++++++++++-------
 2 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex
index 0beb2f721..ca1282d02 100644
--- a/lib/pleroma/user/info.ex
+++ b/lib/pleroma/user/info.ex
@@ -243,6 +243,7 @@ defmodule Pleroma.User.Info do
 
   def remote_user_creation(info, params) do
     params = Map.put(params, "fields", Enum.map(params["fields"], &truncate_field/1))
+
     info
     |> cast(params, [
       :ap_enabled,
@@ -328,8 +329,12 @@ defmodule Pleroma.User.Info do
   defp valid_field?(_), do: false
 
   defp truncate_field(%{"name" => name, "value" => value}) do
-    {name, _chopped} = String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255))
-    {value, _chopped} = String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255))
+    {name, _chopped} =
+      String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255))
+
+    {value, _chopped} =
+      String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255))
+
     %{"name" => name, "value" => value}
   end
 
diff --git a/test/user_test.exs b/test/user_test.exs
index 68a469fe3..0ca310331 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -1119,17 +1119,26 @@ defmodule Pleroma.UserTest do
 
   describe "insert or update a user from given data" do
     test "with normal data" do
-        user = insert(:user, %{nickname: "nick@name.de"})
-        data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
+      user = insert(:user, %{nickname: "nick@name.de"})
+      data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
 
-        assert {:ok, %User{}} = User.insert_or_update_user(data)
+      assert {:ok, %User{}} = User.insert_or_update_user(data)
     end
 
     test "with overly long fields" do
-        current_max_length = Pleroma.Config.get([:instance, :account_field_value_length], 255)
-        user = insert(:user, nickname: "nickname@supergood.domain")
-        data = %{ap_id: user.ap_id, info: %{ fields: [%{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}] }}
-        assert {:ok, %User{}} = User.insert_or_update_user(data)
+      current_max_length = Pleroma.Config.get([:instance, :account_field_value_length], 255)
+      user = insert(:user, nickname: "nickname@supergood.domain")
+
+      data = %{
+        ap_id: user.ap_id,
+        info: %{
+          fields: [
+            %{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}
+          ]
+        }
+      }
+
+      assert {:ok, %User{}} = User.insert_or_update_user(data)
     end
   end
 

From d0f07e55d28d25684130cb1090d0bdbb48807548 Mon Sep 17 00:00:00 2001
From: Sadposter <hannah+pleroma@coffee-and-dreams.uk>
Date: Mon, 2 Sep 2019 12:31:23 +0100
Subject: [PATCH 3/6] use atom key for fields

---
 lib/pleroma/user/info.ex | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex
index ca1282d02..151e025de 100644
--- a/lib/pleroma/user/info.ex
+++ b/lib/pleroma/user/info.ex
@@ -242,7 +242,12 @@ defmodule Pleroma.User.Info do
   end
 
   def remote_user_creation(info, params) do
-    params = Map.put(params, "fields", Enum.map(params["fields"], &truncate_field/1))
+    params =
+      if Map.has_key?(params, :fields) do
+        Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
+      else
+        params
+      end
 
     info
     |> cast(params, [

From e73685834c1797404c943f66417ffa30add87e04 Mon Sep 17 00:00:00 2001
From: Sadposter <hannah+pleroma@coffee-and-dreams.uk>
Date: Mon, 2 Sep 2019 12:35:55 +0100
Subject: [PATCH 4/6] add mandatory fields for user update

---
 test/user_test.exs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/test/user_test.exs b/test/user_test.exs
index 0ca310331..92a48f630 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -1131,6 +1131,8 @@ defmodule Pleroma.UserTest do
 
       data = %{
         ap_id: user.ap_id,
+        name: user.name,
+        nickname: user.nickname,
         info: %{
           fields: [
             %{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}

From 2975da284b75c846a99a56ce70a91ebc3cc43f33 Mon Sep 17 00:00:00 2001
From: Sadposter <hannah+pleroma@coffee-and-dreams.uk>
Date: Wed, 4 Sep 2019 15:45:40 +0100
Subject: [PATCH 5/6] truncate remote user bio/display name

---
 lib/pleroma/user.ex | 16 +++++++++++++++-
 test/user_test.exs  | 45 +++++++++++++++++++++++++++++----------------
 2 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 29fd6d2ea..87e56b5b4 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -174,11 +174,25 @@ defmodule Pleroma.User do
     |> Repo.aggregate(:count, :id)
   end
 
+  defp truncate_if_exists(params, key, max_length) do
+    if Map.has_key?(params, key) do
+      {value, _chopped} = String.split_at(params[key], max_length)
+      Map.put(params, key, value)
+    else
+      params
+    end
+  end
+
   def remote_user_creation(params) do
     bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
     name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
 
-    params = Map.put(params, :info, params[:info] || %{})
+    params =
+      params
+      |> Map.put(:info, params[:info] || %{})
+      |> truncate_if_exists(:name, name_limit)
+      |> truncate_if_exists(:bio, bio_limit)
+
     info_cng = User.Info.remote_user_creation(%User.Info{}, params[:info])
 
     changes =
diff --git a/test/user_test.exs b/test/user_test.exs
index 92a48f630..45f998ff8 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -570,22 +570,6 @@ defmodule Pleroma.UserTest do
         refute cs.valid?
       end)
     end
-
-    test "it restricts some sizes" do
-      bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
-      name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
-
-      [bio: bio_limit, name: name_limit]
-      |> Enum.each(fn {field, size} ->
-        string = String.pad_leading(".", size)
-        cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
-        assert cs.valid?
-
-        string = String.pad_leading(".", size + 1)
-        cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
-        refute cs.valid?
-      end)
-    end
   end
 
   describe "followers and friends" do
@@ -1142,6 +1126,35 @@ defmodule Pleroma.UserTest do
 
       assert {:ok, %User{}} = User.insert_or_update_user(data)
     end
+
+    test "with an overly long bio" do
+      current_max_length = Pleroma.Config.get([:instance, :user_bio_length], 5000)
+      user = insert(:user, nickname: "nickname@supergood.domain")
+
+      data = %{
+        ap_id: user.ap_id,
+        name: user.name,
+        nickname: user.nickname,
+        bio: String.duplicate("h", current_max_length + 1),
+        info: %{}
+      }
+
+      assert {:ok, %User{}} = User.insert_or_update_user(data)
+    end
+
+    test "with an overly long display name" do
+      current_max_length = Pleroma.Config.get([:instance, :user_name_length], 100)
+      user = insert(:user, nickname: "nickname@supergood.domain")
+
+      data = %{
+        ap_id: user.ap_id,
+        name: String.duplicate("h", current_max_length + 1),
+        nickname: user.nickname,
+        info: %{}
+      }
+
+      assert {:ok, %User{}} = User.insert_or_update_user(data)
+    end
   end
 
   describe "per-user rich-text filtering" do

From cb99cfcc65f57f0044117ebd12d040488343d9ef Mon Sep 17 00:00:00 2001
From: Sadposter <hannah+pleroma@coffee-and-dreams.uk>
Date: Wed, 4 Sep 2019 15:57:42 +0100
Subject: [PATCH 6/6] don't try to truncate non-strings

---
 lib/pleroma/user.ex | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 87e56b5b4..e2ebce6fc 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -175,7 +175,7 @@ defmodule Pleroma.User do
   end
 
   defp truncate_if_exists(params, key, max_length) do
-    if Map.has_key?(params, key) do
+    if Map.has_key?(params, key) and is_binary(params[key]) do
       {value, _chopped} = String.split_at(params[key], max_length)
       Map.put(params, key, value)
     else