Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 6.4.2 #30651

Merged
merged 6 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/bump-patch-1697486167182.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Bump @rocket.chat/meteor version.
5 changes: 5 additions & 0 deletions .changeset/cool-zoos-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

fixed threads breaking when sending messages too fast
5 changes: 5 additions & 0 deletions .changeset/old-zoos-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

fix: mobile ringing notification missing call id
5 changes: 5 additions & 0 deletions .changeset/tough-apples-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Forward headers when using proxy for file uploads
5 changes: 5 additions & 0 deletions .changeset/wicked-jars-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Handle the username update in the background
2 changes: 1 addition & 1 deletion apps/meteor/app/cas/server/cas_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ Accounts.registerLoginHandler('cas', async (options) => {
if (roomName) {
let room = await Rooms.findOneByNameAndType(roomName, 'c');
if (!room) {
room = await createRoom('c', roomName, user.username);
room = await createRoom('c', roomName, user);
}
}
}
Expand Down
27 changes: 26 additions & 1 deletion apps/meteor/app/file-upload/server/lib/FileUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,32 @@ export const FileUpload = {
) {
res.setHeader('Content-Disposition', `${forceDownload ? 'attachment' : 'inline'}; filename="${encodeURI(fileName)}"`);

request.get(fileUrl, (fileRes) => fileRes.pipe(res));
request.get(fileUrl, (fileRes) => {
if (fileRes.statusCode !== 200) {
res.setHeader('x-rc-proxyfile-status', String(fileRes.statusCode));
res.setHeader('content-length', 0);
res.writeHead(500);
res.end();
return;
}

// eslint-disable-next-line prettier/prettier
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]));
});

fileRes.pipe(res);
});
},

generateJWTToFileUrls({ rid, userId, fileId }: { rid: string; userId: string; fileId: string }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default async function handleJoinedChannel(args) {
let room = await Rooms.findOneByName(args.roomName);

if (!room) {
const createdRoom = await createRoom('c', args.roomName, user.username, []);
const createdRoom = await createRoom('c', args.roomName, user, []);
room = await Rooms.findOne({ _id: createdRoom.rid });

this.log(`${user.username} created room ${args.roomName}`);
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/app/lib/server/functions/saveUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ export const saveUser = async function (userId, userData) {
_id: userData._id,
username: userData.username,
name: userData.name,
updateUsernameInBackground: true,
}))
) {
throw new Meteor.Error('error-could-not-save-identity', 'Could not save user identity', {
Expand Down
129 changes: 93 additions & 36 deletions apps/meteor/app/lib/server/functions/saveUserIdentity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { IUser } from '@rocket.chat/core-typings';
import { Messages, VideoConference, LivechatDepartmentAgents, Rooms, Subscriptions, Users } from '@rocket.chat/models';

import { SystemLogger } from '../../../../server/lib/logger/system';
import { FileUpload } from '../../../file-upload/server';
import { _setRealName } from './setRealName';
import { _setUsername } from './setUsername';
Expand All @@ -11,7 +13,17 @@ import { validateName } from './validateName';
* @param {object} changes changes to the user
*/

export async function saveUserIdentity({ _id, name: rawName, username: rawUsername }: { _id: string; name?: string; username?: string }) {
export async function saveUserIdentity({
_id,
name: rawName,
username: rawUsername,
updateUsernameInBackground = false,
}: {
_id: string;
name?: string;
username?: string;
updateUsernameInBackground?: boolean; // TODO: remove this
}) {
if (!_id) {
return false;
}
Expand Down Expand Up @@ -48,46 +60,91 @@ export async function saveUserIdentity({ _id, name: rawName, username: rawUserna

// if coming from old username, update all references
if (previousUsername) {
if (usernameChanged && typeof rawUsername !== 'undefined') {
const fileStore = FileUpload.getStore('Avatars');
const previousFile = await fileStore.model.findOneByName(previousUsername);
const file = await fileStore.model.findOneByName(username);
if (file) {
await fileStore.model.deleteFile(file._id);
}
if (previousFile) {
await fileStore.model.updateFileNameById(previousFile._id, username);
}

await Messages.updateAllUsernamesByUserId(user._id, username);
await Messages.updateUsernameOfEditByUserId(user._id, username);

const cursor = Messages.findByMention(previousUsername);
for await (const msg of cursor) {
const updatedMsg = msg.msg.replace(new RegExp(`@${previousUsername}`, 'ig'), `@${username}`);
await Messages.updateUsernameAndMessageOfMentionByIdAndOldUsername(msg._id, previousUsername, username, updatedMsg);
}

await Rooms.replaceUsername(previousUsername, username);
await Rooms.replaceMutedUsername(previousUsername, username);
await Rooms.replaceUsernameOfUserByUserId(user._id, username);
await Subscriptions.setUserUsernameByUserId(user._id, username);

await LivechatDepartmentAgents.replaceUsernameOfAgentByUserId(user._id, username);
const handleUpdateParams = {
username,
previousUsername,
rawUsername,
usernameChanged,
user,
name,
previousName,
rawName,
nameChanged,
};
if (updateUsernameInBackground) {
setImmediate(async () => {
try {
await updateUsernameReferences(handleUpdateParams);
} catch (err) {
SystemLogger.error(err);
}
});
} else {
await updateUsernameReferences(handleUpdateParams);
}
}

return true;
}

// update other references if either the name or username has changed
if (usernameChanged || nameChanged) {
// update name and fname of 1-on-1 direct messages
await Subscriptions.updateDirectNameAndFnameByName(previousUsername, rawUsername && username, rawName && name);
async function updateUsernameReferences({
username,
previousUsername,
rawUsername,
usernameChanged,
user,
name,
previousName,
rawName,
nameChanged,
}: {
username: string;
previousUsername: string;
rawUsername?: string;
usernameChanged: boolean;
user: IUser;
name: string;
previousName: string | undefined;
rawName?: string;
nameChanged: boolean;
}): Promise<void> {
if (usernameChanged && typeof rawUsername !== 'undefined') {
const fileStore = FileUpload.getStore('Avatars');
const previousFile = await fileStore.model.findOneByName(previousUsername);
const file = await fileStore.model.findOneByName(username);
if (file) {
await fileStore.model.deleteFile(file._id);
}
if (previousFile) {
await fileStore.model.updateFileNameById(previousFile._id, username);
}

// update name and fname of group direct messages
await updateGroupDMsName(user);
await Messages.updateAllUsernamesByUserId(user._id, username);
await Messages.updateUsernameOfEditByUserId(user._id, username);

// update name and username of users on video conferences
await VideoConference.updateUserReferences(user._id, username || previousUsername, name || previousName);
const cursor = Messages.findByMention(previousUsername);
for await (const msg of cursor) {
const updatedMsg = msg.msg.replace(new RegExp(`@${previousUsername}`, 'ig'), `@${username}`);
await Messages.updateUsernameAndMessageOfMentionByIdAndOldUsername(msg._id, previousUsername, username, updatedMsg);
}

await Rooms.replaceUsername(previousUsername, username);
await Rooms.replaceMutedUsername(previousUsername, username);
await Rooms.replaceUsernameOfUserByUserId(user._id, username);
await Subscriptions.setUserUsernameByUserId(user._id, username);

await LivechatDepartmentAgents.replaceUsernameOfAgentByUserId(user._id, username);
}

return true;
// update other references if either the name or username has changed
if (usernameChanged || nameChanged) {
// update name and fname of 1-on-1 direct messages
await Subscriptions.updateDirectNameAndFnameByName(previousUsername, rawUsername && username, rawName && name);

// update name and fname of group direct messages
await updateGroupDMsName(user);

// update name and username of users on video conferences
await VideoConference.updateUserReferences(user._id, username || previousUsername, name || previousName);
}
}
2 changes: 1 addition & 1 deletion apps/meteor/app/slackbridge/server/RocketAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ export default class RocketAdapter {

try {
const isPrivate = slackChannel.is_private;
const rocketChannel = await createRoom(isPrivate ? 'p' : 'c', slackChannel.name, rocketUserCreator.username, rocketUsers);
const rocketChannel = await createRoom(isPrivate ? 'p' : 'c', slackChannel.name, rocketUserCreator, rocketUsers);
slackChannel.rocketId = rocketChannel.rid;
} catch (e) {
if (!hasRetried) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { isThreadMainMessage } from '@rocket.chat/core-typings';
import type { IMessage, IThreadMainMessage } from '@rocket.chat/core-typings';
import { useStream } from '@rocket.chat/ui-contexts';
import type { UseQueryResult } from '@tanstack/react-query';
import { useQueryClient, useQuery } from '@tanstack/react-query';
import { useCallback, useEffect, useRef } from 'react';

import { withDebouncing } from '../../../../../../lib/utils/highOrderFunctions';
import type { FieldExpression, Query } from '../../../../../lib/minimongo';
import { createFilterFromQuery } from '../../../../../lib/minimongo';
import { onClientMessageReceived } from '../../../../../lib/onClientMessageReceived';
import { useRoom } from '../../../contexts/RoomContext';
import { useGetMessageByID } from './useGetMessageByID';

Expand Down Expand Up @@ -87,19 +86,22 @@ export const useThreadMainMessageQuery = (
}, [tmid]);

return useQuery(['rooms', room._id, 'threads', tmid, 'main-message'] as const, async ({ queryKey }) => {
const message = await getMessage(tmid);
const mainMessage = await getMessage(tmid);

const mainMessage = (await onClientMessageReceived(message)) || message;

if (!mainMessage && !isThreadMainMessage(mainMessage)) {
if (!mainMessage) {
throw new Error('Invalid main message');
}

const debouncedInvalidate = withDebouncing({ wait: 10000 })(() => {
queryClient.invalidateQueries(queryKey, { exact: true });
});

unsubscribeRef.current =
unsubscribeRef.current ||
subscribeToMessage(mainMessage, {
onMutate: () => {
queryClient.invalidateQueries(queryKey, { exact: true });
onMutate: (message) => {
queryClient.setQueryData(queryKey, () => message);
debouncedInvalidate();
},
onDelete: () => {
onDelete?.();
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/server/services/video-conference/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
caller: call.createdBy,
avatar: getUserAvatarURL(call.createdBy.username),
status: call.status,
callId: call._id,
},
userId: calleeId,
notId: PushNotification.getNotificationId(`${call.rid}|${call._id}`),
Expand Down
48 changes: 25 additions & 23 deletions apps/meteor/tests/end-to-end/api/09-rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path';
import { expect } from 'chai';
import { after, afterEach, before, beforeEach, describe, it } from 'mocha';

import { sleep } from '../../../lib/utils/sleep';
import { getCredentials, api, request, credentials } from '../../data/api-data.js';
import { sendSimpleMessage, deleteMessage } from '../../data/chat.helper';
import { imgURL } from '../../data/interactions.js';
Expand Down Expand Up @@ -1543,29 +1544,30 @@ describe('[Rooms]', function () {
roomId = result.body.room.rid;
});

it('should update group name if user changes username', (done) => {
updateSetting('UI_Use_Real_Name', false).then(() => {
request
.post(api('users.update'))
.set(credentials)
.send({
userId: testUser._id,
data: {
username: `changed.username.${testUser.username}`,
},
})
.end(() => {
request
.get(api('subscriptions.getOne'))
.set(credentials)
.query({ roomId })
.end((err, res) => {
const { subscription } = res.body;
expect(subscription.name).to.equal(`rocket.cat,changed.username.${testUser.username}`);
done();
});
});
});
it('should update group name if user changes username', async () => {
await updateSetting('UI_Use_Real_Name', false);
await request
.post(api('users.update'))
.set(credentials)
.send({
userId: testUser._id,
data: {
username: `changed.username.${testUser.username}`,
},
});

// need to wait for the username update finish
await sleep(300);

await request
.get(api('subscriptions.getOne'))
.set(credentials)
.query({ roomId })
.send()
.expect((res) => {
const { subscription } = res.body;
expect(subscription.name).to.equal(`rocket.cat,changed.username.${testUser.username}`);
});
});

it('should update group name if user changes name', (done) => {
Expand Down
Loading
Loading