From e4342b397c32ad00f028789523d4e8a26c6dbfa5 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Fri, 13 Aug 2021 22:17:33 -0600 Subject: [PATCH] [FIX] Close omnichannel conversations when agent is deactivated (#22917) * close omnichannel conversations when agent is deactivated * Remove console.log * remove unnecesary props from type * Update app/lib/server/functions/setUserActiveStatus.js Co-authored-by: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Co-authored-by: Renato Becker Co-authored-by: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> --- .../closeOmnichannelConversations.ts | 19 +++++++++++++++++++ .../server/functions/setUserActiveStatus.js | 11 ++++++++--- app/models/server/models/LivechatRooms.js | 15 +++++++++++++++ packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-i18n/i18n/es.i18n.json | 1 + 5 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 app/lib/server/functions/closeOmnichannelConversations.ts diff --git a/app/lib/server/functions/closeOmnichannelConversations.ts b/app/lib/server/functions/closeOmnichannelConversations.ts new file mode 100644 index 00000000000..46be29d8a98 --- /dev/null +++ b/app/lib/server/functions/closeOmnichannelConversations.ts @@ -0,0 +1,19 @@ +import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; + +import { LivechatRooms } from '../../../models/server'; +import { IUser } from '../../../../definition/IUser'; +import { settings } from '../../../settings/server'; +import { Livechat } from '../../../livechat/server/lib/Livechat'; + +type SubscribedRooms = { + rid: string; + t: string; +} + +export const closeOmnichannelConversations = (user: IUser, subscribedRooms: SubscribedRooms[]): void => { + const roomsInfo = LivechatRooms.findByIds(subscribedRooms.map(({ rid }) => rid)); + const language = settings.get('Language') || 'en'; + roomsInfo.map((room: any) => + Livechat.closeRoom({ user, visitor: {}, room, comment: TAPi18n.__('Agent_deactivated', { lng: language }) }), + ); +}; diff --git a/app/lib/server/functions/setUserActiveStatus.js b/app/lib/server/functions/setUserActiveStatus.js index fe9a889e0cf..28d3111d0d2 100644 --- a/app/lib/server/functions/setUserActiveStatus.js +++ b/app/lib/server/functions/setUserActiveStatus.js @@ -6,6 +6,7 @@ import * as Mailer from '../../../mailer'; import { Users, Subscriptions, Rooms } from '../../../models'; import { settings } from '../../../settings'; import { relinquishRoomOwnerships } from './relinquishRoomOwnerships'; +import { closeOmnichannelConversations } from './closeOmnichannelConversations'; import { shouldRemoveOrChangeOwner, getSubscribedRoomsForUserWithDetails } from './getRoomsWithSingleOwner'; import { getUserSingleOwnedRooms } from './getUserSingleOwnedRooms'; @@ -41,13 +42,17 @@ export function setUserActiveStatus(userId, active, confirmRelinquish = false) { // Users without username can't do anything, so there is no need to check for owned rooms if (user.username != null && !active) { const subscribedRooms = getSubscribedRoomsForUserWithDetails(userId); + // give omnichannel rooms a special treatment :) + const chatSubscribedRooms = subscribedRooms.filter(({ t }) => t !== 'l'); + const livechatSubscribedRooms = subscribedRooms.filter(({ t }) => t === 'l'); - if (shouldRemoveOrChangeOwner(subscribedRooms) && !confirmRelinquish) { - const rooms = getUserSingleOwnedRooms(subscribedRooms); + if (shouldRemoveOrChangeOwner(chatSubscribedRooms) && !confirmRelinquish) { + const rooms = getUserSingleOwnedRooms(chatSubscribedRooms); throw new Meteor.Error('user-last-owner', '', rooms); } - relinquishRoomOwnerships(user._id, subscribedRooms, false); + closeOmnichannelConversations(user, livechatSubscribedRooms); + relinquishRoomOwnerships(user, chatSubscribedRooms, false); } Users.setUserActive(userId, active); diff --git a/app/models/server/models/LivechatRooms.js b/app/models/server/models/LivechatRooms.js index a57b5e9f358..0b3d2b24e76 100644 --- a/app/models/server/models/LivechatRooms.js +++ b/app/models/server/models/LivechatRooms.js @@ -138,6 +138,21 @@ export class LivechatRooms extends Base { return this.find(query, options); } + findByIds(ids, fields) { + const options = {}; + + if (fields) { + options.fields = fields; + } + + const query = { + t: 'l', + _id: { $in: ids }, + }; + + return this.find(query, options); + } + findOneById(_id, fields = {}) { const options = {}; diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index c532ba25a94..b065ff649ec 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -301,6 +301,7 @@ "Agent_messages": "Agent Messages", "Agent_Name_Placeholder": "Please enter an agent name...", "Agent_removed": "Agent removed", + "Agent_deactivated": "Agent was deactivated", "Agents": "Agents", "Alerts": "Alerts", "Alias": "Alias", diff --git a/packages/rocketchat-i18n/i18n/es.i18n.json b/packages/rocketchat-i18n/i18n/es.i18n.json index b4aedc633e8..5e3bb4e0741 100644 --- a/packages/rocketchat-i18n/i18n/es.i18n.json +++ b/packages/rocketchat-i18n/i18n/es.i18n.json @@ -301,6 +301,7 @@ "Agent_messages": "Mensajes del agente", "Agent_Name_Placeholder": "Por favor, introduzca el nombre de un agente...", "Agent_removed": "Agente eliminado", + "Agent_deactivated": "Agente desactivado", "Agents": "Agentes", "Alerts": "Alertas", "Alias": "Alias",