From fefbd31c6e60e25778ed01c522273375d4f04266 Mon Sep 17 00:00:00 2001
From: rinpatch <rinpatch@sdf.org>
Date: Sun, 6 Oct 2019 16:22:35 +0300
Subject: [PATCH 1/2] Move local keys out of `user.info`

---
 lib/pleroma/signature.ex                                 | 2 +-
 lib/pleroma/user.ex                                      | 8 ++++++--
 lib/pleroma/web/activity_pub/views/user_view.ex          | 4 ++--
 lib/pleroma/web/salmon/salmon.ex                         | 4 ++--
 priv/repo/migrations/20191006123824_add_keys_column.exs  | 9 +++++++++
 .../20191006135457_move_keys_to_separate_column.exs      | 7 +++++++
 test/signature_test.exs                                  | 5 ++---
 test/user_test.exs                                       | 8 ++++----
 8 files changed, 33 insertions(+), 14 deletions(-)
 create mode 100644 priv/repo/migrations/20191006123824_add_keys_column.exs
 create mode 100644 priv/repo/migrations/20191006135457_move_keys_to_separate_column.exs

diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex
index f20aeb0d5..1e7c9ae86 100644
--- a/lib/pleroma/signature.ex
+++ b/lib/pleroma/signature.ex
@@ -48,7 +48,7 @@ defmodule Pleroma.Signature do
   end
 
   def sign(%User{} = user, headers) do
-    with {:ok, %{info: %{keys: keys}}} <- User.ensure_keys_present(user),
+    with {:ok, %{keys: keys}} <- User.ensure_keys_present(user),
          {:ok, private_key, _} <- Keys.keys_from_pem(keys) do
       HTTPSignatures.sign(private_key, user.ap_id <> "#main-key", headers)
     end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 0d665afa6..2cfb13a8c 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -51,6 +51,7 @@ defmodule Pleroma.User do
     field(:password_hash, :string)
     field(:password, :string, virtual: true)
     field(:password_confirmation, :string, virtual: true)
+    field(:keys, :string)
     field(:following, {:array, :string}, default: [])
     field(:ap_id, :string)
     field(:avatar, :map)
@@ -1554,11 +1555,14 @@ defmodule Pleroma.User do
     }
   end
 
-  def ensure_keys_present(%{info: %{keys: keys}} = user) when not is_nil(keys), do: {:ok, user}
+  def ensure_keys_present(%{keys: keys} = user) when not is_nil(keys), do: {:ok, user}
 
   def ensure_keys_present(%User{} = user) do
     with {:ok, pem} <- Keys.generate_rsa_pem() do
-      update_info(user, &User.Info.set_keys(&1, pem))
+      user
+      |> cast(%{keys: pem}, [:keys])
+      |> validate_required([:keys])
+      |> update_and_set_cache()
     end
   end
 
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 6bc55c85b..9b39d1629 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
 
   def render("service.json", %{user: user}) do
     {:ok, user} = User.ensure_keys_present(user)
-    {:ok, _, public_key} = Keys.keys_from_pem(user.info.keys)
+    {:ok, _, public_key} = Keys.keys_from_pem(user.keys)
     public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
     public_key = :public_key.pem_encode([public_key])
 
@@ -69,7 +69,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
 
   def render("user.json", %{user: user}) do
     {:ok, user} = User.ensure_keys_present(user)
-    {:ok, _, public_key} = Keys.keys_from_pem(user.info.keys)
+    {:ok, _, public_key} = Keys.keys_from_pem(user.keys)
     public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
     public_key = :public_key.pem_encode([public_key])
 
diff --git a/lib/pleroma/web/salmon/salmon.ex b/lib/pleroma/web/salmon/salmon.ex
index 8ba7380c0..0ffe903cd 100644
--- a/lib/pleroma/web/salmon/salmon.ex
+++ b/lib/pleroma/web/salmon/salmon.ex
@@ -202,7 +202,7 @@ defmodule Pleroma.Web.Salmon do
   @spec publish(User.t(), Pleroma.Activity.t()) :: none
   def publish(user, activity)
 
-  def publish(%{info: %{keys: keys}} = user, %{data: %{"type" => type}} = activity)
+  def publish(%{keys: keys} = user, %{data: %{"type" => type}} = activity)
       when type in @supported_activities do
     feed = ActivityRepresenter.to_simple_form(activity, user, true)
 
@@ -238,7 +238,7 @@ defmodule Pleroma.Web.Salmon do
   def publish(%{id: id}, _), do: Logger.debug(fn -> "Keys missing for user #{id}" end)
 
   def gather_webfinger_links(%User{} = user) do
-    {:ok, _private, public} = Keys.keys_from_pem(user.info.keys)
+    {:ok, _private, public} = Keys.keys_from_pem(user.keys)
     magic_key = encode_key(public)
 
     [
diff --git a/priv/repo/migrations/20191006123824_add_keys_column.exs b/priv/repo/migrations/20191006123824_add_keys_column.exs
new file mode 100644
index 000000000..b6c615646
--- /dev/null
+++ b/priv/repo/migrations/20191006123824_add_keys_column.exs
@@ -0,0 +1,9 @@
+defmodule Pleroma.Repo.Migrations.AddKeysColumn do
+  use Ecto.Migration
+
+  def change do
+    alter table("users") do
+      add_if_not_exists :keys, :text
+    end
+  end
+end
diff --git a/priv/repo/migrations/20191006135457_move_keys_to_separate_column.exs b/priv/repo/migrations/20191006135457_move_keys_to_separate_column.exs
new file mode 100644
index 000000000..504dde53a
--- /dev/null
+++ b/priv/repo/migrations/20191006135457_move_keys_to_separate_column.exs
@@ -0,0 +1,7 @@
+defmodule Pleroma.Repo.Migrations.MoveKeysToSeparateColumn do
+  use Ecto.Migration
+
+  def change do
+    execute("update users set keys = info->>'keys' where local", "update users set info = jsonb_set(info, '{keys}'::text[], to_jsonb(keys)) where local")
+  end
+end
diff --git a/test/signature_test.exs b/test/signature_test.exs
index d5bf63d7d..96c8ba07a 100644
--- a/test/signature_test.exs
+++ b/test/signature_test.exs
@@ -80,7 +80,7 @@ defmodule Pleroma.SignatureTest do
       user =
         insert(:user, %{
           ap_id: "https://mastodon.social/users/lambadalambda",
-          info: %{keys: @private_key}
+          keys: @private_key
         })
 
       assert Signature.sign(
@@ -94,8 +94,7 @@ defmodule Pleroma.SignatureTest do
     end
 
     test "it returns error" do
-      user =
-        insert(:user, %{ap_id: "https://mastodon.social/users/lambadalambda", info: %{keys: ""}})
+      user = insert(:user, %{ap_id: "https://mastodon.social/users/lambadalambda", keys: ""})
 
       assert Signature.sign(
                user,
diff --git a/test/user_test.exs b/test/user_test.exs
index 1bc853c94..ae21286e4 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -1457,15 +1457,15 @@ defmodule Pleroma.UserTest do
   describe "ensure_keys_present" do
     test "it creates keys for a user and stores them in info" do
       user = insert(:user)
-      refute is_binary(user.info.keys)
+      refute is_binary(user.keys)
       {:ok, user} = User.ensure_keys_present(user)
-      assert is_binary(user.info.keys)
+      assert is_binary(user.keys)
     end
 
     test "it doesn't create keys if there already are some" do
-      user = insert(:user, %{info: %{keys: "xxx"}})
+      user = insert(:user, keys: "xxx")
       {:ok, user} = User.ensure_keys_present(user)
-      assert user.info.keys == "xxx"
+      assert user.keys == "xxx"
     end
   end
 

From 125f96e7064aa0d714c91bf4a0c78c25734c64ef Mon Sep 17 00:00:00 2001
From: rinpatch <rinpatch@sdf.org>
Date: Sun, 6 Oct 2019 17:05:51 +0300
Subject: [PATCH 2/2] Fix the use of queries with a schema in a migration

---
 .../20190711042024_copy_muted_to_muted_notifications.exs | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs b/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs
index 50669902e..815d66549 100644
--- a/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs
+++ b/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs
@@ -1,15 +1,10 @@
 defmodule Pleroma.Repo.Migrations.CopyMutedToMutedNotifications do
   use Ecto.Migration
+  import Ecto.Query
   alias Pleroma.User
 
   def change do
-    query =
-      User.Query.build(%{
-        local: true,
-        active: true,
-        order_by: :id
-      })
-
+    query = from(u in "users", where: fragment("not (?->'deactivated' @> 'true')", u.info), select: %{info: u.info}, where: u.local == true, order_by: u.id)
     Pleroma.Repo.stream(query)
     |> Enum.each(fn
       %{info: %{mutes: mutes} = info} = user ->