From 674f95cca9a0c63463c03b6994358cb298f46061 Mon Sep 17 00:00:00 2001
From: Kevin Aleman <kaleman960@gmail.com>
Date: Thu, 29 Jun 2023 06:56:05 -0600
Subject: [PATCH] fix: Dont update a user's livechat status when its status is
 offline (#29589)

Co-authored-by: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com>
---
 .changeset/thin-hats-jog.md                            |  5 +++++
 .../server/business-hour/AbstractBusinessHour.ts       |  6 +++++-
 apps/meteor/app/livechat/server/business-hour/index.ts | 10 +++++-----
 apps/meteor/ee/server/startup/presence.ts              |  5 +++--
 apps/meteor/server/models/raw/Users.js                 |  1 +
 5 files changed, 19 insertions(+), 8 deletions(-)
 create mode 100644 .changeset/thin-hats-jog.md

diff --git a/.changeset/thin-hats-jog.md b/.changeset/thin-hats-jog.md
new file mode 100644
index 00000000000..2cea8a2312b
--- /dev/null
+++ b/.changeset/thin-hats-jog.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/meteor": patch
+---
+
+Avoid updating a user's livechat status on login when its status is set to offline
diff --git a/apps/meteor/app/livechat/server/business-hour/AbstractBusinessHour.ts b/apps/meteor/app/livechat/server/business-hour/AbstractBusinessHour.ts
index 7c0ddd007d1..2bafd2f0fa2 100644
--- a/apps/meteor/app/livechat/server/business-hour/AbstractBusinessHour.ts
+++ b/apps/meteor/app/livechat/server/business-hour/AbstractBusinessHour.ts
@@ -44,11 +44,15 @@ export abstract class AbstractBusinessHourBehavior {
 		return this.UsersRepository.isAgentWithinBusinessHours(agentId);
 	}
 
+	// After logout, users are turned not-available by default
+	// This will turn them available unless they put themselves offline (manual status change)
 	async changeAgentActiveStatus(agentId: string, status: string): Promise<any> {
 		return this.UsersRepository.setLivechatStatusIf(
 			agentId,
 			status,
-			{ livechatStatusSystemModified: true },
+			// Why this works: statusDefault is the property set when a user manually changes their status
+			// So if it's set to offline, we can be sure the user will be offline after login and we can skip the update
+			{ livechatStatusSystemModified: true, statusDefault: { $ne: 'offline' } },
 			{ livechatStatusSystemModified: true },
 		);
 	}
diff --git a/apps/meteor/app/livechat/server/business-hour/index.ts b/apps/meteor/app/livechat/server/business-hour/index.ts
index 02fd2480dce..8b80e415f7a 100644
--- a/apps/meteor/app/livechat/server/business-hour/index.ts
+++ b/apps/meteor/app/livechat/server/business-hour/index.ts
@@ -1,6 +1,7 @@
 import { Meteor } from 'meteor/meteor';
-import { Accounts } from 'meteor/accounts-base';
 import { cronJobs } from '@rocket.chat/cron';
+import type { IUser } from '@rocket.chat/core-typings';
+import { Accounts } from 'meteor/accounts-base';
 
 import { BusinessHourManager } from './BusinessHourManager';
 import { SingleBusinessHourBehavior } from './Single';
@@ -16,8 +17,7 @@ Meteor.startup(async () => {
 	businessHourManager.registerBusinessHourBehavior(new BusinessHourBehaviorClass());
 	businessHourManager.registerBusinessHourType(new DefaultBusinessHour());
 
-	Accounts.onLogin(
-		async ({ user }: { user: any }) =>
-			user?.roles?.includes('livechat-agent') && !user?.roles?.includes('bot') && businessHourManager.onLogin(user._id),
-	);
+	Accounts.onLogin((user: IUser) => {
+		void (user?.roles?.includes('livechat-agent') && !user?.roles?.includes('bot') && businessHourManager.onLogin(user._id));
+	});
 });
diff --git a/apps/meteor/ee/server/startup/presence.ts b/apps/meteor/ee/server/startup/presence.ts
index 952539ff700..51cff87cebe 100644
--- a/apps/meteor/ee/server/startup/presence.ts
+++ b/apps/meteor/ee/server/startup/presence.ts
@@ -33,9 +33,10 @@ Meteor.startup(function () {
 		if (login.type !== 'resume') {
 			return;
 		}
-		void Presence.newConnection(login.user._id, login.connection.id, nodeId).then(() => {
+		void (async function () {
+			await Presence.newConnection(login.user._id, login.connection.id, nodeId);
 			updateConns();
-		});
+		})();
 	});
 
 	Accounts.onLogout(function (login: any): void {
diff --git a/apps/meteor/server/models/raw/Users.js b/apps/meteor/server/models/raw/Users.js
index afcca73f81e..f43a1522a54 100644
--- a/apps/meteor/server/models/raw/Users.js
+++ b/apps/meteor/server/models/raw/Users.js
@@ -968,6 +968,7 @@ export class UsersRaw extends BaseRaw {
 	setLivechatStatusActiveBasedOnBusinessHours(userId) {
 		const query = {
 			_id: userId,
+			statusDefault: { $ne: 'offline' },
 			openBusinessHours: {
 				$exists: true,
 				$not: { $size: 0 },
-- 
GitLab