From 49b2bb294ead8cfaf3d78a9215e52bc56170eb81 Mon Sep 17 00:00:00 2001
From: Vinoth Kannan <svkn.87@gmail.com>
Date: Tue, 31 Aug 2021 16:11:26 +0530
Subject: [PATCH] FEATURE: option to update default notification level of
 existing users. (#14084)

Previously, a group's `default_notification_level` change will only affect the users added after it.

Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
---
 app/controllers/groups_controller.rb    | 32 ++++++++++---
 spec/requests/groups_controller_spec.rb | 61 +++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 7930a90ac85..828bb11a5f5 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -157,10 +157,10 @@ class GroupsController < ApplicationController
 
     categories, tags = []
     if !group.automatic || current_user.admin
-      categories, tags = user_default_notifications(group, params_with_permitted)
+      notification_level, categories, tags = user_default_notifications(group, params_with_permitted)
 
       if params[:update_existing_users].blank?
-        user_count = count_existing_users(group.group_users, categories, tags)
+        user_count = count_existing_users(group.group_users, notification_level, categories, tags)
 
         if user_count > 0
           render json: { user_count: user_count }
@@ -173,7 +173,7 @@ class GroupsController < ApplicationController
       GroupActionLogger.new(current_user, group).log_change_group_settings
       group.record_email_setting_changes!(current_user)
       group.expire_imap_mailbox_cache
-      update_existing_users(group.group_users, categories, tags) if categories.present? || tags.present?
+      update_existing_users(group.group_users, notification_level, categories, tags) if params[:update_existing_users] == "true"
 
       if guardian.can_see?(group)
         render json: success_json
@@ -847,18 +847,38 @@ class GroupsController < ApplicationController
       tags[tag_id] = { action: :delete, old_value: tag_notifications[tag_id] }
     end
 
-    [categories, tags]
+    notification_level = nil
+    default_notification_level = params[:default_notification_level]&.to_i
+
+    if default_notification_level.present? && group.default_notification_level != default_notification_level
+      notification_level = {
+        old_value: group.default_notification_level,
+        new_value: default_notification_level
+      }
+    end
+
+    [notification_level, categories, tags]
   end
 
   %i{
     count
     update
   }.each do |action|
-    define_method("#{action}_existing_users") do |group_users, categories, tags|
-      return 0 if categories.blank? && tags.blank?
+    define_method("#{action}_existing_users") do |group_users, notification_level, categories, tags|
+      return 0 if notification_level.blank? && categories.blank? && tags.blank?
 
       ids = []
 
+      if notification_level.present?
+        users = group_users.where(notification_level: notification_level[:old_value])
+
+        if action == :update
+          users.update_all(notification_level: notification_level[:new_value])
+        else
+          ids += users.pluck(:user_id)
+        end
+      end
+
       categories.each do |category_id, data|
         if data[:action] == :update || data[:action] == :delete
           category_users = CategoryUser.where(category_id: category_id, notification_level: data[:old_value], user_id: group_users.select(:user_id))
diff --git a/spec/requests/groups_controller_spec.rb b/spec/requests/groups_controller_spec.rb
index e57f59361ef..d918db850af 100644
--- a/spec/requests/groups_controller_spec.rb
+++ b/spec/requests/groups_controller_spec.rb
@@ -883,6 +883,67 @@ describe GroupsController do
 
       context "user default notifications" do
         it "should update default notification preference for existing users" do
+          group.update!(default_notification_level: NotificationLevels.all[:watching])
+          user1 = Fabricate(:user)
+          user2 = Fabricate(:user)
+          group.add(user1)
+          group.add(user2)
+          group_user1 = user1.group_users.first
+          group_user2 = user2.group_users.first
+
+          put "/groups/#{group.id}.json", params: {
+            group: {
+              default_notification_level: NotificationLevels.all[:tracking]
+            }
+          }
+
+          expect(response.status).to eq(200)
+
+          expect(group_user1.reload.notification_level).to eq(NotificationLevels.all[:watching])
+          expect(group_user2.reload.notification_level).to eq(NotificationLevels.all[:watching])
+
+          group_users = group.group_users
+          expect(response.parsed_body["user_count"]).to eq(group_users.count)
+
+          group_user1.update!(notification_level: NotificationLevels.all[:regular])
+
+          put "/groups/#{group.id}.json", params: {
+            group: {
+              default_notification_level: NotificationLevels.all[:tracking]
+            }
+          }
+
+          expect(response.status).to eq(200)
+          expect(response.parsed_body["user_count"]).to eq(group.group_users.count - 1)
+          expect(group_user1.reload.notification_level).to eq(NotificationLevels.all[:regular])
+          expect(group_user2.reload.notification_level).to eq(NotificationLevels.all[:watching])
+
+          put "/groups/#{group.id}.json", params: {
+            group: {
+              default_notification_level: NotificationLevels.all[:tracking]
+            },
+            update_existing_users: true
+          }
+
+          expect(response.status).to eq(200)
+          expect(response.parsed_body["success"]).to eq("OK")
+          expect(group_user1.reload.notification_level).to eq(NotificationLevels.all[:regular])
+          expect(group_user2.reload.notification_level).to eq(NotificationLevels.all[:tracking])
+
+          put "/groups/#{group.id}.json", params: {
+            group: {
+              default_notification_level: NotificationLevels.all[:regular]
+            },
+            update_existing_users: false
+          }
+
+          expect(response.status).to eq(200)
+          expect(response.parsed_body["success"]).to eq("OK")
+          expect(group_user1.reload.notification_level).to eq(NotificationLevels.all[:regular])
+          expect(group_user2.reload.notification_level).to eq(NotificationLevels.all[:tracking])
+        end
+
+        it "should update category & tag notification preferences for existing users" do
           user1 = Fabricate(:user)
           user2 = Fabricate(:user)
           CategoryUser.create!(user: user1, category: category, notification_level: 4)