Skip to content

Commit

Permalink
Merge branch 'develop' into feat/new-user-panel-backend
Browse files Browse the repository at this point in the history
  • Loading branch information
rique223 authored Apr 8, 2024
2 parents fe43f5b + a316c2b commit ccae8e3
Show file tree
Hide file tree
Showing 155 changed files with 1,283 additions and 843 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-ghosts-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': minor
---

Introduces a resizable Contextualbar allowing users to change the width just by dragging it
6 changes: 6 additions & 0 deletions .changeset/pink-ants-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": patch
---

Fixed a UI issue that allowed a user to "mark" a room as favorite even when a room was not default. The Back-End was correctly ignoring the `favorite` property from being updated when the room was not default, but the UI still allowed users to try.
As UI allowed but changes were not saved, this gave the impression that the function was not working.
5 changes: 5 additions & 0 deletions .changeset/smart-squids-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes the missing space between name and user name on system messages
8 changes: 8 additions & 0 deletions .changeset/strange-rivers-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@rocket.chat/core-typings': minor
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---

Added support for allowing agents to forward inquiries to departments that may not have any online agents given that `Allow department to receive forwarded inquiries even when there's no available agents` is set to `true` in the department configuration.
This configuration empowers agents to seamlessly direct incoming requests to the designated department, ensuring efficient handling of queries even when departmental resources are not actively online. When an agent becomes available, any pending inquiries will be automatically routed to them if the routing algorithm supports it.
5 changes: 5 additions & 0 deletions .changeset/sweet-books-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

fixed search room not showing the new name room name changes
5 changes: 5 additions & 0 deletions .changeset/wild-keys-obey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/livechat": patch
---

Fixes issue causing a desync in different browser windows when a chat is closed and started again
16 changes: 6 additions & 10 deletions .github/actions/build-docker/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ inputs:
required: false
description: 'Platform'
type: string
build-containers:
required: false
description: 'Containers to build along with Rocket.Chat'
type: string

runs:
using: composite
Expand Down Expand Up @@ -54,22 +58,14 @@ runs:
- name: Build Docker images
shell: bash
run: |
args=(rocketchat)
if [[ '${{ inputs.platform }}' = 'alpine' ]]; then
args+=($SERVICES_PUBLISH)
fi;
args=(rocketchat ${{ inputs.build-containers }})
docker compose -f docker-compose-ci.yml build "${args[@]}"
- name: Publish Docker images to GitHub Container Registry
if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
shell: bash
run: |
args=(rocketchat)
if [[ '${{ inputs.platform }}' = 'alpine' ]]; then
args+=($SERVICES_PUBLISH)
fi;
args=(rocketchat ${{ inputs.build-containers }})
docker compose -f docker-compose-ci.yml push "${args[@]}"
8 changes: 8 additions & 0 deletions .github/workflows/ci-test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ jobs:
name: MongoDB ${{ matrix.mongodb-version }} (${{ matrix.shard }}/${{ inputs.total-shard }})

steps:
- name: Login to GitHub Container Registry
if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ secrets.CR_USER }}
password: ${{ secrets.CR_PAT }}

- name: Launch MongoDB
uses: supercharge/[email protected]
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ jobs:
RC_DOCKER_TAG: ${{ matrix.platform == 'alpine' && needs.release-versions.outputs.rc-docker-tag-alpine || needs.release-versions.outputs.rc-docker-tag }}
DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}
LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }}
SERVICES_PUBLISH: 'authorization-service account-service ddp-streamer-service presence-service stream-hub-service'

strategy:
fail-fast: false
Expand All @@ -237,6 +236,7 @@ jobs:
CR_PAT: ${{ secrets.CR_PAT }}
node-version: ${{ needs.release-versions.outputs.node-version }}
platform: ${{ matrix.platform }}
build-containers: ${{ matrix.platform == 'alpine' && 'authorization-service account-service ddp-streamer-service presence-service stream-hub-service queue-worker-service omnichannel-transcript-service' || '' }}

build-gh-docker:
name: 🚢 Build Docker Images for Production
Expand All @@ -248,7 +248,6 @@ jobs:
RC_DOCKER_TAG: ${{ matrix.platform == 'alpine' && needs.release-versions.outputs.rc-docker-tag-alpine || needs.release-versions.outputs.rc-docker-tag }}
DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}
LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }}
SERVICES_PUBLISH: 'authorization-service account-service ddp-streamer-service presence-service stream-hub-service'

strategy:
fail-fast: false
Expand All @@ -264,6 +263,7 @@ jobs:
CR_PAT: ${{ secrets.CR_PAT }}
node-version: ${{ needs.release-versions.outputs.node-version }}
platform: ${{ matrix.platform }}
build-containers: ${{ matrix.platform == 'alpine' && 'authorization-service account-service ddp-streamer-service presence-service stream-hub-service queue-worker-service omnichannel-transcript-service' || '' }}

- name: Rename official Docker tag to GitHub Container Registry
if: matrix.platform == 'official'
Expand Down
6 changes: 3 additions & 3 deletions apps/meteor/app/authentication/server/startup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,8 @@ const insertUserDocAsync = async function (options, user) {

if (!options.skipAppsEngineEvent) {
// `post` triggered events don't need to wait for the promise to resolve
Apps?.triggerEvent(AppEvents.IPostUserCreated, { user, performedBy: await safeGetMeteorUser() }).catch((e) => {
Apps?.getRocketChatLogger().error('Error while executing post user created event:', e);
Apps.self?.triggerEvent(AppEvents.IPostUserCreated, { user, performedBy: await safeGetMeteorUser() }).catch((e) => {
Apps.self?.getRocketChatLogger().error('Error while executing post user created event:', e);
});
}

Expand Down Expand Up @@ -424,7 +424,7 @@ const validateLoginAttemptAsync = async function (login) {
*/
if (login.type !== 'resume') {
// App IPostUserLoggedIn event hook
await Apps?.triggerEvent(AppEvents.IPostUserLoggedIn, login.user);
await Apps.self?.triggerEvent(AppEvents.IPostUserLoggedIn, login.user);
}

return true;
Expand Down
12 changes: 2 additions & 10 deletions apps/meteor/app/file-upload/server/lib/FileUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export const FileUpload = {

// App IPreFileUpload event hook
try {
await Apps?.triggerEvent(AppEvents.IPreFileUpload, { file, content: content || Buffer.from([]) });
await Apps.self?.triggerEvent(AppEvents.IPreFileUpload, { file, content: content || Buffer.from([]) });
} catch (error: any) {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
Expand Down Expand Up @@ -587,15 +587,7 @@ export const FileUpload = {
}

// eslint-disable-next-line prettier/prettier
const headersToProxy = [
'age',
'cache-control',
'content-length',
'content-type',
'date',
'expired',
'last-modified',
];
const headersToProxy = ['age', 'cache-control', 'content-length', 'content-type', 'date', 'expired', 'last-modified'];

headersToProxy.forEach((header) => {
fileRes.headers[header] && res.setHeader(header, String(fileRes.headers[header]));
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/lib/server/functions/addUserToRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const addUserToRoom = async function (
}

try {
await Apps?.triggerEvent(AppEvents.IPreRoomUserJoined, room, userToBeAdded, inviter);
await Apps.self?.triggerEvent(AppEvents.IPreRoomUserJoined, room, userToBeAdded, inviter);
} catch (error: any) {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
Expand Down Expand Up @@ -118,7 +118,7 @@ export const addUserToRoom = async function (
// Keep the current event
await callbacks.run('afterJoinRoom', userToBeAdded, room);

void Apps?.triggerEvent(AppEvents.IPostRoomUserJoined, room, userToBeAdded, inviter);
void Apps.self?.triggerEvent(AppEvents.IPostRoomUserJoined, room, userToBeAdded, inviter);
});
}

Expand Down
8 changes: 4 additions & 4 deletions apps/meteor/app/lib/server/functions/createDirectRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export async function createDirectRoom(
_USERNAMES: usernames,
};

const prevent = await Apps?.triggerEvent(AppEvents.IPreRoomCreatePrevent, tmpRoom).catch((error) => {
const prevent = await Apps.self?.triggerEvent(AppEvents.IPreRoomCreatePrevent, tmpRoom).catch((error) => {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
}
Expand All @@ -115,9 +115,9 @@ export async function createDirectRoom(
throw new Meteor.Error('error-app-prevented', 'A Rocket.Chat App prevented the room creation.');
}

const result = await Apps?.triggerEvent(
const result = await Apps.self?.triggerEvent(
AppEvents.IPreRoomCreateModify,
await Apps?.triggerEvent(AppEvents.IPreRoomCreateExtend, tmpRoom),
await Apps.self?.triggerEvent(AppEvents.IPreRoomCreateExtend, tmpRoom),
);

if (typeof result === 'object') {
Expand Down Expand Up @@ -172,7 +172,7 @@ export async function createDirectRoom(

await callbacks.run('afterCreateDirectRoom', insertedRoom, { members: roomMembers, creatorId: options?.creator });

void Apps?.triggerEvent(AppEvents.IPostRoomCreate, insertedRoom);
void Apps.self?.triggerEvent(AppEvents.IPostRoomCreate, insertedRoom);
}

return {
Expand Down
6 changes: 3 additions & 3 deletions apps/meteor/app/lib/server/functions/createRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export const createRoom = async <T extends RoomType>(
_USERNAMES: members,
};

const prevent = await Apps?.triggerEvent(AppEvents.IPreRoomCreatePrevent, tmp).catch((error) => {
const prevent = await Apps.self?.triggerEvent(AppEvents.IPreRoomCreatePrevent, tmp).catch((error) => {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
}
Expand All @@ -210,7 +210,7 @@ export const createRoom = async <T extends RoomType>(
throw new Meteor.Error('error-app-prevented', 'A Rocket.Chat App prevented the room creation.');
}

const eventResult = await Apps?.triggerEvent(
const eventResult = await Apps.self?.triggerEvent(
AppEvents.IPreRoomCreateModify,
await Apps.triggerEvent(AppEvents.IPreRoomCreateExtend, tmp),
);
Expand Down Expand Up @@ -245,7 +245,7 @@ export const createRoom = async <T extends RoomType>(
callbacks.runAsync('federation.afterCreateFederatedRoom', room, { owner, originalMemberList: members });
}

void Apps?.triggerEvent(AppEvents.IPostRoomCreate, room);
void Apps.self?.triggerEvent(AppEvents.IPostRoomCreate, room);
return {
rid: room._id, // backwards compatible
inserted: true,
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/lib/server/functions/deleteMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export async function deleteMessage(message: IMessage, user: IUser): Promise<voi
const isThread = (deletedMsg?.tcount || 0) > 0;
const keepHistory = settings.get('Message_KeepHistory') || isThread;
const showDeletedStatus = settings.get('Message_ShowDeletedStatus') || isThread;
const bridges = Apps?.isLoaded() && Apps.getBridges();
const bridges = Apps.self?.isLoaded() && Apps.getBridges();

if (deletedMsg && bridges) {
const prevent = await bridges.getListenerBridge().messageEvent(AppEvents.IPreMessageDeletePrevent, deletedMsg);
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/lib/server/functions/removeUserFromRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const removeUserFromRoom = async function (
}

try {
await Apps?.triggerEvent(AppEvents.IPreRoomUserLeave, room, user);
await Apps.self?.triggerEvent(AppEvents.IPreRoomUserLeave, room, user);
} catch (error: any) {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
Expand Down Expand Up @@ -67,5 +67,5 @@ export const removeUserFromRoom = async function (
// TODO: CACHE: maybe a queue?
await afterLeaveRoomCallback.run(user, room);

await Apps?.triggerEvent(AppEvents.IPostRoomUserLeave, room, user);
await Apps.self?.triggerEvent(AppEvents.IPostRoomUserLeave, room, user);
};
2 changes: 1 addition & 1 deletion apps/meteor/app/lib/server/functions/saveUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ export const saveUser = async function (userId, userData) {
oldUser: oldUserData,
});

await Apps?.triggerEvent(AppEvents.IPostUserUpdated, {
await Apps.self?.triggerEvent(AppEvents.IPostUserUpdated, {
user: userUpdated,
previousUser: oldUserData,
performedBy: await safeGetMeteorUser(),
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/lib/server/functions/sendMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export const sendMessage = async function (user: any, message: any, room: any, u
}

// For the Rocket.Chat Apps :)
if (Apps?.isLoaded()) {
if (Apps.self?.isLoaded()) {
const listenerBridge = Apps.getBridges()?.getListenerBridge();

const prevent = await listenerBridge?.messageEvent('IPreMessageSentPrevent', message);
Expand Down Expand Up @@ -275,7 +275,7 @@ export const sendMessage = async function (user: any, message: any, room: any, u
message._id = insertedId;
}

if (Apps?.isLoaded()) {
if (Apps.self?.isLoaded()) {
// This returns a promise, but it won't mutate anything about the message
// so, we don't really care if it is successful or fails
void Apps.getBridges()?.getListenerBridge().messageEvent('IPostMessageSent', message);
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/lib/server/functions/updateMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const updateMessage = async function (
let messageData: IMessage = Object.assign({}, originalMessage, message);

// For the Rocket.Chat Apps :)
if (message && Apps && Apps.isLoaded()) {
if (message && Apps.self && Apps.isLoaded()) {
const prevent = await Apps.getBridges().getListenerBridge().messageEvent(AppEvents.IPreMessageUpdatedPrevent, messageData);
if (prevent) {
throw new Meteor.Error('error-app-prevented-updating', 'A Rocket.Chat App prevented the message updating.');
Expand Down Expand Up @@ -76,7 +76,7 @@ export const updateMessage = async function (
},
);

if (Apps?.isLoaded()) {
if (Apps.self?.isLoaded()) {
// This returns a promise, but it won't mutate anything about the message
// so, we don't really care if it is successful or fails
void Apps.getBridges()?.getListenerBridge().messageEvent(AppEvents.IPostMessageUpdated, messageData);
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Meteor.methods<ServerMethods>({
await deleteUser(uid, confirmRelinquish);

// App IPostUserDeleted event hook
await Apps?.triggerEvent(AppEvents.IPostUserDeleted, { user });
await Apps.self?.triggerEvent(AppEvents.IPostUserDeleted, { user });

return true;
},
Expand Down
29 changes: 19 additions & 10 deletions apps/meteor/app/livechat/server/lib/Helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ export const removeAgentFromSubscription = async (rid: string, { _id, username }
await Message.saveSystemMessage('ul', rid, username || '', { _id: user._id, username: user.username, name: user.name });

setImmediate(() => {
void Apps?.triggerEvent(AppEvents.IPostLivechatAgentUnassigned, { room, user });
void Apps.self?.triggerEvent(AppEvents.IPostLivechatAgentUnassigned, { room, user });
});
};

Expand Down Expand Up @@ -452,7 +452,7 @@ export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: T
}

setImmediate(() => {
void Apps?.triggerEvent(AppEvents.IPostLivechatRoomTransferred, {
void Apps.self?.triggerEvent(AppEvents.IPostLivechatRoomTransferred, {
type: LivechatTransferEventType.AGENT,
room: rid,
from: oldServedBy?._id,
Expand Down Expand Up @@ -482,7 +482,7 @@ export const updateChatDepartment = async ({
]);

setImmediate(() => {
void Apps?.triggerEvent(AppEvents.IPostLivechatRoomTransferred, {
void Apps.self?.triggerEvent(AppEvents.IPostLivechatRoomTransferred, {
type: LivechatTransferEventType.DEPARTMENT,
room: rid,
from: oldDepartmentId,
Expand Down Expand Up @@ -539,10 +539,24 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi
agent = { agentId, username };
}

if (!RoutingManager.getConfig()?.autoAssignAgent || !(await Omnichannel.isWithinMACLimit(room))) {
const department = await LivechatDepartment.findOneById<
Pick<ILivechatDepartment, 'allowReceiveForwardOffline' | 'fallbackForwardDepartment' | 'name'>
>(departmentId, {
projection: {
allowReceiveForwardOffline: 1,
fallbackForwardDepartment: 1,
name: 1,
},
});

if (
!RoutingManager.getConfig()?.autoAssignAgent ||
!(await Omnichannel.isWithinMACLimit(room)) ||
(department?.allowReceiveForwardOffline && !(await LivechatTyped.checkOnlineAgents(departmentId)))
) {
logger.debug(`Room ${room._id} will be on department queue`);
await LivechatTyped.saveTransferHistory(room, transferData);
return RoutingManager.unassignAgent(inquiry, departmentId);
return RoutingManager.unassignAgent(inquiry, departmentId, true);
}

// Fake the department to forward the inquiry - Case the forward process does not success
Expand All @@ -559,11 +573,6 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi

const { servedBy, chatQueued } = roomTaken;
if (!chatQueued && oldServedBy && servedBy && oldServedBy._id === servedBy._id) {
const department = departmentId
? await LivechatDepartment.findOneById<Pick<ILivechatDepartment, '_id' | 'fallbackForwardDepartment' | 'name'>>(departmentId, {
projection: { fallbackForwardDepartment: 1, name: 1 },
})
: null;
if (!department?.fallbackForwardDepartment?.length) {
logger.debug(`Cannot forward room ${room._id}. Chat assigned to agent ${servedBy._id} (Previous was ${oldServedBy._id})`);
throw new Error('error-no-agents-online-in-department');
Expand Down
Loading

0 comments on commit ccae8e3

Please sign in to comment.