Merge branch 'refactor/db-not-null-constraints-for-oauth_tokens' into 'develop'
authorkaniini <ariadne@dereferenced.org>
Sun, 27 Oct 2019 05:30:25 +0000 (05:30 +0000)
committerkaniini <ariadne@dereferenced.org>
Sun, 27 Oct 2019 05:30:25 +0000 (05:30 +0000)
Add NOT NULL constraints for oauth_tokens table

See merge request pleroma/pleroma!1901

22 files changed:
README.md
lib/pleroma/conversation.ex
lib/pleroma/conversation/participation.ex
lib/pleroma/object/fetcher.ex
lib/pleroma/user.ex
lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
priv/repo/migrations/20191026190317_set_not_null_for_activities.exs [new file with mode: 0644]
priv/repo/migrations/20191026190415_set_not_null_for_activity_expirations.exs [new file with mode: 0644]
priv/repo/migrations/20191026190500_set_not_null_for_apps.exs [new file with mode: 0644]
priv/repo/migrations/20191026190533_set_not_null_for_bookmarks.exs [new file with mode: 0644]
priv/repo/migrations/20191026190622_set_not_null_for_config.exs [new file with mode: 0644]
priv/repo/migrations/20191026190712_set_not_null_for_conversation_participation_recipient_ships.exs [new file with mode: 0644]
priv/repo/migrations/20191026190759_set_not_null_for_conversation_participations.exs [new file with mode: 0644]
priv/repo/migrations/20191026190841_set_not_null_for_filters.exs [new file with mode: 0644]
priv/repo/migrations/20191026191023_set_not_null_for_instances.exs [new file with mode: 0644]
priv/repo/migrations/20191026191100_set_not_null_for_lists.exs [new file with mode: 0644]
priv/repo/migrations/20191026191134_set_not_null_for_markers.exs [new file with mode: 0644]
priv/repo/migrations/20191026191218_set_not_null_for_moderation_log.exs [new file with mode: 0644]
priv/repo/migrations/20191026191249_set_not_null_for_notifications.exs [new file with mode: 0644]
rel/files/bin/pleroma_ctl
test/conversation/participation_test.exs
test/web/activity_pub/transmogrifier_test.exs

index c8420c81344726a0bc3c16993d26a2e1cd595a3c..dd49822e9c1530e9302abf048936880d7011e74e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ While we don’t provide docker files, other people have written very good ones.
 
 ### Dependencies
 
-* Postgresql version 9.6 or newer
+* Postgresql version 9.6 or newer, including the contrib modules
 * Elixir version 1.7 or newer. If your distribution only has an old version available, check [Elixir’s install page](https://elixir-lang.org/install.html) or use a tool like [asdf](https://github.com/asdf-vm/asdf).
 * Build-essential tools
 
index 098016af28c7b839bd6f019d4d61ea6e59ab3c7a..ade3a526a57e52b1f69006eb383dd438c03f2df6 100644 (file)
@@ -67,7 +67,13 @@ defmodule Pleroma.Conversation do
 
       participations =
         Enum.map(users, fn user ->
-          User.increment_unread_conversation_count(conversation, user)
+          invisible_conversation = Enum.any?(users, &User.blocks?(user, &1))
+
+          unless invisible_conversation do
+            User.increment_unread_conversation_count(conversation, user)
+          end
+
+          opts = Keyword.put(opts, :invisible_conversation, invisible_conversation)
 
           {:ok, participation} =
             Participation.create_for_user_and_conversation(user, conversation, opts)
index 41918fa78e4cd21962c902563b95fa004ebe50d9..176b82a2092e46cd48745c719a5f4c6fd4dd206d 100644 (file)
@@ -32,11 +32,20 @@ defmodule Pleroma.Conversation.Participation do
 
   def create_for_user_and_conversation(user, conversation, opts \\ []) do
     read = !!opts[:read]
+    invisible_conversation = !!opts[:invisible_conversation]
+
+    update_on_conflict =
+      if(invisible_conversation, do: [], else: [read: read])
+      |> Keyword.put(:updated_at, NaiveDateTime.utc_now())
 
     %__MODULE__{}
-    |> creation_cng(%{user_id: user.id, conversation_id: conversation.id, read: read})
+    |> creation_cng(%{
+      user_id: user.id,
+      conversation_id: conversation.id,
+      read: invisible_conversation || read
+    })
     |> Repo.insert(
-      on_conflict: [set: [read: read, updated_at: NaiveDateTime.utc_now()]],
+      on_conflict: [set: update_on_conflict],
       returning: true,
       conflict_target: [:user_id, :conversation_id]
     )
@@ -69,7 +78,26 @@ defmodule Pleroma.Conversation.Participation do
     end
   end
 
-  def mark_all_as_read(user) do
+  def mark_all_as_read(%User{local: true} = user, %User{} = target_user) do
+    target_conversation_ids =
+      __MODULE__
+      |> where([p], p.user_id == ^target_user.id)
+      |> select([p], p.conversation_id)
+      |> Repo.all()
+
+    __MODULE__
+    |> where([p], p.user_id == ^user.id)
+    |> where([p], p.conversation_id in ^target_conversation_ids)
+    |> update([p], set: [read: true])
+    |> Repo.update_all([])
+
+    {:ok, user} = User.set_unread_conversation_count(user)
+    {:ok, user, []}
+  end
+
+  def mark_all_as_read(%User{} = user, %User{}), do: {:ok, user, []}
+
+  def mark_all_as_read(%User{} = user) do
     {_, participations} =
       __MODULE__
       |> where([p], p.user_id == ^user.id)
@@ -78,8 +106,8 @@ defmodule Pleroma.Conversation.Participation do
       |> select([p], p)
       |> Repo.update_all([])
 
-    User.set_unread_conversation_count(user)
-    {:ok, participations}
+    {:ok, user} = User.set_unread_conversation_count(user)
+    {:ok, user, participations}
   end
 
   def mark_as_unread(participation) do
index 7758cb90b1f6637d5fdb406a5fb0fe474713c903..441ae8b6557e9601e19ab0fd3c781b3812f35b8c 100644 (file)
@@ -90,6 +90,9 @@ defmodule Pleroma.Object.Fetcher do
       {:fetch_object, %Object{} = object} ->
         {:ok, object}
 
+      {:fetch, {:error, error}} ->
+        {:error, error}
+
       e ->
         e
     end
@@ -110,6 +113,9 @@ defmodule Pleroma.Object.Fetcher do
     with {:ok, object} <- fetch_object_from_id(id, options) do
       object
     else
+      {:error, %Tesla.Mock.Error{}} ->
+        nil
+
       e ->
         Logger.error("Error while fetching #{id}: #{inspect(e)}")
         nil
@@ -170,6 +176,9 @@ defmodule Pleroma.Object.Fetcher do
       {:scheme, _} ->
         {:error, "Unsupported URI scheme"}
 
+      {:error, e} ->
+        {:error, e}
+
       e ->
         {:error, e}
     end
index 7bef6e2810c5ed08071933df8d46b9e1dc8fa157..5d3f5572192966b7fff3d0c99a678e25b3058c2d 100644 (file)
@@ -224,54 +224,6 @@ defmodule Pleroma.User do
     |> Repo.aggregate(:count, :id)
   end
 
-  @info_fields [
-    :banner,
-    :background,
-    :source_data,
-    :note_count,
-    :follower_count,
-    :following_count,
-    :locked,
-    :confirmation_pending,
-    :password_reset_pending,
-    :confirmation_token,
-    :default_scope,
-    :blocks,
-    :domain_blocks,
-    :mutes,
-    :muted_reblogs,
-    :muted_notifications,
-    :subscribers,
-    :deactivated,
-    :no_rich_text,
-    :ap_enabled,
-    :is_moderator,
-    :is_admin,
-    :show_role,
-    :settings,
-    :magic_key,
-    :uri,
-    :hide_followers_count,
-    :hide_follows_count,
-    :hide_followers,
-    :hide_follows,
-    :hide_favorites,
-    :unread_conversation_count,
-    :pinned_activities,
-    :email_notifications,
-    :mascot,
-    :emoji,
-    :pleroma_settings_store,
-    :fields,
-    :raw_fields,
-    :discoverable,
-    :invisible,
-    :skip_thread_containment,
-    :notification_settings
-  ]
-
-  def info_fields, do: @info_fields
-
   defp truncate_fields_param(params) do
     if Map.has_key?(params, :fields) do
       Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
@@ -1019,7 +971,7 @@ defmodule Pleroma.User do
     end
   end
 
-  def set_unread_conversation_count(_), do: :noop
+  def set_unread_conversation_count(user), do: {:ok, user}
 
   def increment_unread_conversation_count(conversation, %User{local: true} = user) do
     unread_query =
@@ -1041,7 +993,7 @@ defmodule Pleroma.User do
     end
   end
 
-  def increment_unread_conversation_count(_, _), do: :noop
+  def increment_unread_conversation_count(_, user), do: {:ok, user}
 
   def remove_duplicated_following(%User{following: following} = user) do
     uniq_following = Enum.uniq(following)
@@ -1125,7 +1077,7 @@ defmodule Pleroma.User do
     if following?(blocked, blocker), do: unfollow(blocked, blocker)
 
     {:ok, blocker} = update_follower_count(blocker)
-
+    {:ok, blocker, _} = Participation.mark_all_as_read(blocker, blocked)
     add_to_block(blocker, ap_id)
   end
 
index fc39abf053ee658b90b846e708bebf080636e79e..651a9942382355871610cc687cb7dec48ab20199 100644 (file)
@@ -80,7 +80,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
   end
 
   def read_conversations(%{assigns: %{user: user}} = conn, _params) do
-    with {:ok, participations} <- Participation.mark_all_as_read(user) do
+    with {:ok, _, participations} <- Participation.mark_all_as_read(user) do
       conn
       |> add_link_headers(participations)
       |> put_view(ConversationView)
diff --git a/priv/repo/migrations/20191026190317_set_not_null_for_activities.exs b/priv/repo/migrations/20191026190317_set_not_null_for_activities.exs
new file mode 100644 (file)
index 0000000..9b66f3c
--- /dev/null
@@ -0,0 +1,17 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForActivities do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE activities
+    ALTER COLUMN data SET NOT NULL,
+    ALTER COLUMN local SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE activities
+    ALTER COLUMN data DROP NOT NULL,
+    ALTER COLUMN local DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026190415_set_not_null_for_activity_expirations.exs b/priv/repo/migrations/20191026190415_set_not_null_for_activity_expirations.exs
new file mode 100644 (file)
index 0000000..e41c69e
--- /dev/null
@@ -0,0 +1,15 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForActivityExpirations do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE activity_expirations
+    ALTER COLUMN activity_id SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE activity_expirations
+    ALTER COLUMN activity_id DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026190500_set_not_null_for_apps.exs b/priv/repo/migrations/20191026190500_set_not_null_for_apps.exs
new file mode 100644 (file)
index 0000000..a6a44dd
--- /dev/null
@@ -0,0 +1,17 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForApps do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE apps
+    ALTER COLUMN client_name SET NOT NULL,
+    ALTER COLUMN redirect_uris SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE apps
+    ALTER COLUMN client_name DROP NOT NULL,
+    ALTER COLUMN redirect_uris DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026190533_set_not_null_for_bookmarks.exs b/priv/repo/migrations/20191026190533_set_not_null_for_bookmarks.exs
new file mode 100644 (file)
index 0000000..5f32240
--- /dev/null
@@ -0,0 +1,17 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForBookmarks do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE bookmarks
+    ALTER COLUMN user_id SET NOT NULL,
+    ALTER COLUMN activity_id SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE bookmarks
+    ALTER COLUMN user_id DROP NOT NULL,
+    ALTER COLUMN activity_id DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026190622_set_not_null_for_config.exs b/priv/repo/migrations/20191026190622_set_not_null_for_config.exs
new file mode 100644 (file)
index 0000000..2042724
--- /dev/null
@@ -0,0 +1,17 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForConfig do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE config
+    ALTER COLUMN key SET NOT NULL,
+    ALTER COLUMN value SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE config
+    ALTER COLUMN key DROP NOT NULL,
+    ALTER COLUMN value DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026190712_set_not_null_for_conversation_participation_recipient_ships.exs b/priv/repo/migrations/20191026190712_set_not_null_for_conversation_participation_recipient_ships.exs
new file mode 100644 (file)
index 0000000..a5ab1d3
--- /dev/null
@@ -0,0 +1,17 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForConversationParticipationRecipientShips do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE conversation_participation_recipient_ships
+    ALTER COLUMN user_id SET NOT NULL,
+    ALTER COLUMN participation_id SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE conversation_participation_recipient_ships
+    ALTER COLUMN user_id DROP NOT NULL,
+    ALTER COLUMN participation_id DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026190759_set_not_null_for_conversation_participations.exs b/priv/repo/migrations/20191026190759_set_not_null_for_conversation_participations.exs
new file mode 100644 (file)
index 0000000..cabb1f2
--- /dev/null
@@ -0,0 +1,19 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForConversationParticipations do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE conversation_participations
+    ALTER COLUMN user_id SET NOT NULL,
+    ALTER COLUMN conversation_id SET NOT NULL,
+    ALTER COLUMN read SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE conversation_participations
+    ALTER COLUMN user_id DROP NOT NULL,
+    ALTER COLUMN conversation_id DROP NOT NULL,
+    ALTER COLUMN read DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026190841_set_not_null_for_filters.exs b/priv/repo/migrations/20191026190841_set_not_null_for_filters.exs
new file mode 100644 (file)
index 0000000..52d7e68
--- /dev/null
@@ -0,0 +1,19 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForFilters do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE filters
+    ALTER COLUMN user_id SET NOT NULL,
+    ALTER COLUMN filter_id SET NOT NULL,
+    ALTER COLUMN whole_word SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE filters
+    ALTER COLUMN user_id DROP NOT NULL,
+    ALTER COLUMN filter_id DROP NOT NULL,
+    ALTER COLUMN whole_word DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026191023_set_not_null_for_instances.exs b/priv/repo/migrations/20191026191023_set_not_null_for_instances.exs
new file mode 100644 (file)
index 0000000..4c2560d
--- /dev/null
@@ -0,0 +1,15 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForInstances do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE instances
+    ALTER COLUMN host SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE instances
+    ALTER COLUMN host DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026191100_set_not_null_for_lists.exs b/priv/repo/migrations/20191026191100_set_not_null_for_lists.exs
new file mode 100644 (file)
index 0000000..40b8b13
--- /dev/null
@@ -0,0 +1,15 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForLists do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE lists
+    ALTER COLUMN user_id SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE lists
+    ALTER COLUMN user_id DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026191134_set_not_null_for_markers.exs b/priv/repo/migrations/20191026191134_set_not_null_for_markers.exs
new file mode 100644 (file)
index 0000000..7d7b73e
--- /dev/null
@@ -0,0 +1,15 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForMarkers do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE markers
+    ALTER COLUMN user_id SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE markers
+    ALTER COLUMN user_id DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026191218_set_not_null_for_moderation_log.exs b/priv/repo/migrations/20191026191218_set_not_null_for_moderation_log.exs
new file mode 100644 (file)
index 0000000..7238ca7
--- /dev/null
@@ -0,0 +1,15 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForModerationLog do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE moderation_log
+    ALTER COLUMN data SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE moderation_log
+    ALTER COLUMN data DROP NOT NULL")
+  end
+end
diff --git a/priv/repo/migrations/20191026191249_set_not_null_for_notifications.exs b/priv/repo/migrations/20191026191249_set_not_null_for_notifications.exs
new file mode 100644 (file)
index 0000000..7e2976b
--- /dev/null
@@ -0,0 +1,17 @@
+defmodule Pleroma.Repo.Migrations.SetNotNullForNotifications do
+  use Ecto.Migration
+
+  # modify/3 function will require index recreation, so using execute/1 instead
+
+  def up do
+    execute("ALTER TABLE notifications
+    ALTER COLUMN user_id SET NOT NULL,
+    ALTER COLUMN seen SET NOT NULL")
+  end
+
+  def down do
+    execute("ALTER TABLE notifications
+    ALTER COLUMN user_id DROP NOT NULL,
+    ALTER COLUMN seen DROP NOT NULL")
+  end
+end
index 9fc5b0bad8a0a64ec2ea9ace3887ff79ca95028c..87c486514008b84086e308efee4f7774cc85afad 100755 (executable)
@@ -140,11 +140,15 @@ else
        FULL_ARGS="$*"
 
        ACTION="$1"
-       shift
-        echo "$1" | grep "^-" >/dev/null
+       if [ $# -gt 0 ]; then
+               shift
+       fi
+       echo "$1" | grep "^-" >/dev/null
        if [ $? -eq 1 ]; then
                SUBACTION="$1"
-               shift
+               if [ $# -gt 0 ]; then
+                       shift
+               fi
        fi
 
        if [ "$ACTION" = "update" ]; then
index 91867bf7047341a066b7a2f810de305edc4e3021..863270022e8c0f8ac8675277114642cc46498598 100644 (file)
@@ -140,7 +140,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
     participation2 = insert(:participation, %{read: false, user: user})
     participation3 = insert(:participation, %{read: false, user: other_user})
 
-    {:ok, [%{read: true}, %{read: true}]} = Participation.mark_all_as_read(user)
+    {:ok, _, [%{read: true}, %{read: true}]} = Participation.mark_all_as_read(user)
 
     assert Participation.get(participation1.id).read == true
     assert Participation.get(participation2.id).read == true
@@ -216,4 +216,134 @@ defmodule Pleroma.Conversation.ParticipationTest do
     assert user in participation.recipients
     assert other_user in participation.recipients
   end
+
+  describe "blocking" do
+    test "when the user blocks a recipient, the existing conversations with them are marked as read" do
+      blocker = insert(:user)
+      blocked = insert(:user)
+      third_user = insert(:user)
+
+      {:ok, _direct1} =
+        CommonAPI.post(third_user, %{
+          "status" => "Hi @#{blocker.nickname}",
+          "visibility" => "direct"
+        })
+
+      {:ok, _direct2} =
+        CommonAPI.post(third_user, %{
+          "status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
+          "visibility" => "direct"
+        })
+
+      {:ok, _direct3} =
+        CommonAPI.post(blocked, %{
+          "status" => "Hi @#{blocker.nickname}",
+          "visibility" => "direct"
+        })
+
+      {:ok, _direct4} =
+        CommonAPI.post(blocked, %{
+          "status" => "Hi @#{blocker.nickname}, @#{third_user.nickname}",
+          "visibility" => "direct"
+        })
+
+      assert [%{read: false}, %{read: false}, %{read: false}, %{read: false}] =
+               Participation.for_user(blocker)
+
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 4
+
+      {:ok, blocker} = User.block(blocker, blocked)
+
+      # The conversations with the blocked user are marked as read
+      assert [%{read: true}, %{read: true}, %{read: true}, %{read: false}] =
+               Participation.for_user(blocker)
+
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 1
+
+      # The conversation is not marked as read for the blocked user
+      assert [_, _, %{read: false}] = Participation.for_user(blocked)
+      assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
+
+      # The conversation is not marked as read for the third user
+      assert [%{read: false}, _, _] = Participation.for_user(third_user)
+      assert User.get_cached_by_id(third_user.id).unread_conversation_count == 1
+    end
+
+    test "the new conversation with the blocked user is not marked as unread " do
+      blocker = insert(:user)
+      blocked = insert(:user)
+      third_user = insert(:user)
+
+      {:ok, blocker} = User.block(blocker, blocked)
+
+      # When the blocked user is the author
+      {:ok, _direct1} =
+        CommonAPI.post(blocked, %{
+          "status" => "Hi @#{blocker.nickname}",
+          "visibility" => "direct"
+        })
+
+      assert [%{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      # When the blocked user is a recipient
+      {:ok, _direct2} =
+        CommonAPI.post(third_user, %{
+          "status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
+          "visibility" => "direct"
+        })
+
+      assert [%{read: true}, %{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      assert [%{read: false}, _] = Participation.for_user(blocked)
+      assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
+    end
+
+    test "the conversation with the blocked user is not marked as unread on a reply" do
+      blocker = insert(:user)
+      blocked = insert(:user)
+      third_user = insert(:user)
+
+      {:ok, _direct1} =
+        CommonAPI.post(blocker, %{
+          "status" => "Hi @#{third_user.nickname}, @#{blocked.nickname}",
+          "visibility" => "direct"
+        })
+
+      {:ok, blocker} = User.block(blocker, blocked)
+      assert [%{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      assert [blocked_participation] = Participation.for_user(blocked)
+
+      # When it's a reply from the blocked user
+      {:ok, _direct2} =
+        CommonAPI.post(blocked, %{
+          "status" => "reply",
+          "visibility" => "direct",
+          "in_reply_to_conversation_id" => blocked_participation.id
+        })
+
+      assert [%{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      assert [third_user_participation] = Participation.for_user(third_user)
+
+      # When it's a reply from the third user
+      {:ok, _direct3} =
+        CommonAPI.post(third_user, %{
+          "status" => "reply",
+          "visibility" => "direct",
+          "in_reply_to_conversation_id" => third_user_participation.id
+        })
+
+      assert [%{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      # Marked as unread for the blocked user
+      assert [%{read: false}] = Participation.for_user(blocked)
+      assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
+    end
+  end
 end
index ae56f84940d61a0143f9c61a8dd5112e0c0bee93..6f7e1da1f65fc9eea293dd307efba4e0df3bf970 100644 (file)
@@ -720,7 +720,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert capture_log(fn ->
                :error = Transmogrifier.handle_incoming(data)
              end) =~
-               "[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, {:error, :nxdomain}}"
+               "[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, :nxdomain}"
 
       assert Activity.get_by_id(activity.id)
     end