FEATURE: Ignored user notification behaviour should be as a muted user (#7227)

FEATURE: Ignored user notification behaviour should be as a muted user (#7227)

diff --git a/app/jobs/regular/notify_mailing_list_subscribers.rb b/app/jobs/regular/notify_mailing_list_subscribers.rb
index 93330a3..6f9d01b 100644
--- a/app/jobs/regular/notify_mailing_list_subscribers.rb
+++ b/app/jobs/regular/notify_mailing_list_subscribers.rb
@@ -39,6 +39,11 @@ module Jobs
                   )', post.user_id)
             .where('NOT EXISTS (
                       SELECT 1
+                      FROM ignored_users iu
+                      WHERE iu.ignored_user_id = ? AND iu.user_id = users.id
+                  )', post.user_id)
+            .where('NOT EXISTS (
+                      SELECT 1
                       FROM topic_users tu
                       WHERE tu.topic_id = ? AND tu.user_id = users.id AND tu.notification_level = ?
                   )', post.topic_id, TopicUser.notification_levels[:muted])
diff --git a/app/services/post_alerter.rb b/app/services/post_alerter.rb
index 454f981c..a3402bb 100644
--- a/app/services/post_alerter.rb
+++ b/app/services/post_alerter.rb
@@ -297,6 +297,12 @@ class PostAlerter
       .where('NOT admin AND NOT moderator')
       .exists?
 
+    # apply ignored here
+    return if notifier_id && IgnoredUser.where(user_id: user.id, ignored_user_id: notifier_id)
+      .joins(:ignored_user)
+      .where('NOT admin AND NOT moderator')
+      .exists?
+
     # skip if muted on the topic
     return if TopicUser.where(
       topic: post.topic,
diff --git a/lib/post_creator.rb b/lib/post_creator.rb
index 01f5571..c494ba6 100644
--- a/lib/post_creator.rb
+++ b/lib/post_creator.rb
@@ -115,10 +115,12 @@ class PostCreator
       User
         .joins("LEFT JOIN user_options ON user_options.user_id = users.id")
         .joins("LEFT JOIN muted_users ON muted_users.user_id = users.id AND muted_users.muted_user_id = #{@user.id.to_i}")
+        .joins("LEFT JOIN ignored_users ON ignored_users.user_id = users.id AND ignored_users.ignored_user_id = #{@user.id.to_i}")
         .where("user_options.user_id IS NOT NULL")
         .where("
           (user_options.user_id IN (:user_ids) AND NOT user_options.allow_private_messages) OR
-          muted_users.user_id IN (:user_ids)
+          muted_users.user_id IN (:user_ids) OR
+          ignored_users.user_id IN (:user_ids)
         ", user_ids: users.keys)
         .pluck(:id).each do |m|
 
diff --git a/spec/components/post_creator_spec.rb b/spec/components/post_creator_spec.rb
index df2ace3..ffdf2cc 100644
--- a/spec/components/post_creator_spec.rb
+++ b/spec/components/post_creator_spec.rb
@@ -1233,6 +1233,48 @@ describe PostCreator do
     end
   end
 
+  context "private message to an ignored user" do
+    let(:ignorer) { Fabricate(:evil_trout) }
+    let(:another_user) { Fabricate(:user) }
+
+    context "when post author is ignored" do
+      let!(:ignored_user) { Fabricate(:ignored_user, user: ignorer, ignored_user: user) }
+
+      it 'should fail' do
+        pc = PostCreator.new(
+          user,
+          title: 'this message is to someone who ignored me!',
+          raw: "you will have to see this even if you ignored me!",
+          archetype: Archetype.private_message,
+          target_usernames: "#{ignorer.username},#{another_user.username}"
+        )
+
+        expect(pc).not_to be_valid
+        expect(pc.errors.full_messages).to contain_exactly(
+                                             I18n.t(:not_accepting_pms, username: ignorer.username)
+                                           )
+      end
+    end
+
+    context "when post author is admin who is ignored" do
+      let(:staff_user) { Fabricate(:admin) }
+      let!(:ignored_user) { Fabricate(:ignored_user, user: ignorer, ignored_user: staff_user) }
+
+      it 'succeeds if the user is staff' do
+        pc = PostCreator.new(
+          staff_user,
+          title: 'this message is to someone who ignored me!',
+          raw: "you will have to see this even if you ignored me!",
+          archetype: Archetype.private_message,
+          target_usernames: "#{ignorer.username}"
+        )
+        expect(pc).to be_valid
+        expect(pc.errors).to be_blank
+      end
+    end
+
+  end
+
   context "private message recipients limit (max_allowed_message_recipients) reached" do
     let(:target_user1) { Fabricate(:coding_horror) }
     let(:target_user2) { Fabricate(:evil_trout) }
diff --git a/spec/jobs/notify_mailing_list_subscribers_spec.rb b/spec/jobs/notify_mailing_list_subscribers_spec.rb
index 6d94894..18b67f2 100644
--- a/spec/jobs/notify_mailing_list_subscribers_spec.rb
+++ b/spec/jobs/notify_mailing_list_subscribers_spec.rb
@@ -108,6 +108,11 @@ describe Jobs::NotifyMailingListSubscribers do
         include_examples "no emails"
       end
 
+      context "from an ignored user" do
+        before { Fabricate(:ignored_user, user: mailing_list_user, ignored_user: user) }
+        include_examples "no emails"
+      end
+
       context "from a muted topic" do
         before { TopicUser.create(user: mailing_list_user, topic: post.topic, notification_level: TopicUser.notification_levels[:muted]) }
         include_examples "no emails"
diff --git a/spec/services/post_alerter_spec.rb b/spec/services/post_alerter_spec.rb
index 9143b9e..c21405d 100644
--- a/spec/services/post_alerter_spec.rb
+++ b/spec/services/post_alerter_spec.rb
@@ -171,6 +171,15 @@ describe PostAlerter do
       }.to change(evil_trout.notifications, :count).by(0)
     end
 
+    it 'does not notify for ignored users' do
+      post = Fabricate(:post, raw: '[quote="EvilTrout, post:1"]whatup[/quote]')
+      IgnoredUser.create!(user_id: evil_trout.id, ignored_user_id: post.user_id)
+
+      expect {
+        PostAlerter.post_created(post)
+      }.to change(evil_trout.notifications, :count).by(0)
+    end
+
     it 'notifies a user by username' do
       topic = Fabricate(:topic)

GitHub sha: a31a35b3