From 1048bc1bb9ec11766cff3ab3d75219f55b84f980 Mon Sep 17 00:00:00 2001
From: Ilja <ilja@ilja.space>
Date: Sun, 6 Mar 2022 17:36:30 +0100
Subject: [PATCH] Delete report notifs when demoting from superuser

When someone isn't a superuser any more, they shouldn't see the reporsts any more either.
Here we delete the report notifications from a user when that user gets updated from being a superuser to a non-superuser.
---
 lib/pleroma/notification.ex        |  8 ++++++++
 lib/pleroma/user.ex                | 19 ++++++++++++++++++-
 test/pleroma/notification_test.exs | 19 +++++++++++++++++++
 test/pleroma/user_test.exs         | 21 +++++++++++++++++++++
 4 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 9e0ce0329..2ab09495d 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -341,6 +341,14 @@ defmodule Pleroma.Notification do
     |> Repo.delete_all()
   end
 
+  def destroy_multiple_from_types(%{id: user_id}, types) do
+    from(n in Notification,
+      where: n.user_id == ^user_id,
+      where: n.type in ^types
+    )
+    |> Repo.delete_all()
+  end
+
   def dismiss(%Pleroma.Activity{} = activity) do
     Notification
     |> where([n], n.activity_id == ^activity.id)
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index efe9ec5d6..809524f56 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1089,11 +1089,28 @@ defmodule Pleroma.User do
     |> update_and_set_cache()
   end
 
-  def update_and_set_cache(changeset) do
+  def update_and_set_cache(%{data: %Pleroma.User{} = user} = changeset) do
+    was_superuser_before_update = User.superuser?(user)
+
     with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
       Pleroma.Elasticsearch.maybe_put_into_elasticsearch(user)
       set_cache(user)
     end
+    |> maybe_remove_report_notifications(was_superuser_before_update)
+  end
+
+  defp maybe_remove_report_notifications(
+         {:ok, %Pleroma.User{} = user} = result,
+         was_superuser_before_update
+       ) do
+    if was_superuser_before_update and not User.superuser?(user),
+      do: user |> Notification.destroy_multiple_from_types(["pleroma:report"])
+
+    result
+  end
+
+  defp maybe_remove_report_notifications(result, _) do
+    result
   end
 
   def get_user_friends_ap_ids(user) do
diff --git a/test/pleroma/notification_test.exs b/test/pleroma/notification_test.exs
index 716af496d..b47edd0a3 100644
--- a/test/pleroma/notification_test.exs
+++ b/test/pleroma/notification_test.exs
@@ -520,6 +520,25 @@ defmodule Pleroma.NotificationTest do
     end
   end
 
+  describe "destroy_multiple_from_types/2" do
+    test "clears all notifications of a certain type for a given user" do
+      report_activity = insert(:report_activity)
+      user1 = insert(:user, is_moderator: true, is_admin: true)
+      user2 = insert(:user, is_moderator: true, is_admin: true)
+      {:ok, _} = Notification.create_notifications(report_activity)
+
+      {:ok, _} =
+        CommonAPI.post(user2, %{
+          status: "hey @#{user1.nickname} !"
+        })
+
+      Notification.destroy_multiple_from_types(user1, ["pleroma:report"])
+
+      assert [%Pleroma.Notification{type: "mention"}] = Notification.for_user(user1)
+      assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user2)
+    end
+  end
+
   describe "set_read_up_to()" do
     test "it sets all notifications as read up to a specified notification ID" do
       user = insert(:user)
diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs
index 7c30f39ad..756281a46 100644
--- a/test/pleroma/user_test.exs
+++ b/test/pleroma/user_test.exs
@@ -5,6 +5,7 @@
 defmodule Pleroma.UserTest do
   alias Pleroma.Activity
   alias Pleroma.Builders.UserBuilder
+  alias Pleroma.Notification
   alias Pleroma.Object
   alias Pleroma.Repo
   alias Pleroma.Tests.ObanHelpers
@@ -2153,6 +2154,26 @@ defmodule Pleroma.UserTest do
       assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
       assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
     end
+
+    test "removes report notifs when user isn't superuser any more" do
+      report_activity = insert(:report_activity)
+      user = insert(:user, is_moderator: true, is_admin: true)
+      {:ok, _} = Notification.create_notifications(report_activity)
+
+      assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
+
+      {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
+      # is still superuser because still admin
+      assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
+
+      {:ok, user} = user |> User.admin_api_update(%{is_moderator: true, is_admin: false})
+      # is still superuser because still moderator
+      assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
+
+      {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
+      # is not a superuser any more
+      assert [] = Notification.for_user(user)
+    end
   end
 
   describe "following/followers synchronization" do
-- 
2.49.0