Skip to content

Commit 2bd8c98

Browse files
authored
fix: imported fixes (#32690)
1 parent 86bf75c commit 2bd8c98

File tree

14 files changed

+536
-20
lines changed

14 files changed

+536
-20
lines changed

.changeset/witty-penguins-rush.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rocket.chat/meteor': patch
3+
---
4+
5+
Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)

apps/meteor/app/api/server/api.ts

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ interface IAPIDefaultFieldsToExclude {
6363
statusDefault: number;
6464
_updatedAt: number;
6565
settings: number;
66+
inviteToken: number;
6667
}
6768

6869
type RateLimiterOptions = {
@@ -149,6 +150,7 @@ export class APIClass<TBasePath extends string = ''> extends Restivus {
149150

150151
public limitedUserFieldsToExcludeIfIsPrivilegedUser: {
151152
services: number;
153+
inviteToken: number;
152154
};
153155

154156
constructor(properties: IAPIProperties) {
@@ -176,10 +178,12 @@ export class APIClass<TBasePath extends string = ''> extends Restivus {
176178
statusDefault: 0,
177179
_updatedAt: 0,
178180
settings: 0,
181+
inviteToken: 0,
179182
};
180183
this.limitedUserFieldsToExclude = this.defaultLimitedUserFieldsToExclude;
181184
this.limitedUserFieldsToExcludeIfIsPrivilegedUser = {
182185
services: 0,
186+
inviteToken: 0,
183187
};
184188
}
185189

apps/meteor/app/livechat/server/api/v1/message.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ API.v1.addRoute(
9898
throw new Error('invalid-room');
9999
}
100100

101-
let message = await Messages.findOneById(_id);
101+
let message = await Messages.findOneByRoomIdAndMessageId(rid, _id);
102102
if (!message) {
103103
throw new Error('invalid-message');
104104
}

apps/meteor/app/livechat/server/methods/loadHistory.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { IMessage } from '@rocket.chat/core-typings';
22
import { LivechatVisitors, LivechatRooms } from '@rocket.chat/models';
33
import type { ServerMethods } from '@rocket.chat/ui-contexts';
4+
import { check, Match } from 'meteor/check';
45
import { Meteor } from 'meteor/meteor';
56

67
import { loadMessageHistory } from '../../../lib/server/functions/loadMessageHistory';
@@ -23,9 +24,11 @@ Meteor.methods<ServerMethods>({
2324
async 'livechat:loadHistory'({ token, rid, end, limit = 20, ls }) {
2425
methodDeprecationLogger.method('livechat:loadHistory', '7.0.0');
2526

26-
if (!token || typeof token !== 'string') {
27-
return;
28-
}
27+
check(token, String);
28+
check(rid, String);
29+
check(end, Date);
30+
check(ls, Match.OneOf(String, Date));
31+
check(limit, Number);
2932

3033
const visitor = await LivechatVisitors.getVisitorByToken(token, { projection: { _id: 1 } });
3134

apps/meteor/app/livechat/server/methods/loginByToken.ts

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ declare module '@rocket.chat/ui-contexts' {
1414
Meteor.methods<ServerMethods>({
1515
async 'livechat:loginByToken'(token) {
1616
methodDeprecationLogger.method('livechat:loginByToken', '7.0.0');
17+
check(token, String);
1718
const visitor = await LivechatVisitors.getVisitorByToken(token, { projection: { _id: 1 } });
1819

1920
if (!visitor) {

apps/meteor/app/slashcommands-inviteall/server/server.ts

+9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Meteor } from 'meteor/meteor';
1010

1111
import { isTruthy } from '../../../lib/isTruthy';
1212
import { i18n } from '../../../server/lib/i18n';
13+
import { canAccessRoomAsync } from '../../authorization/server';
1314
import { addUsersToRoomMethod } from '../../lib/server/methods/addUsersToRoom';
1415
import { createChannelMethod } from '../../lib/server/methods/createChannel';
1516
import { createPrivateGroupMethod } from '../../lib/server/methods/createPrivateGroup';
@@ -55,6 +56,14 @@ function inviteAll<T extends string>(type: T): SlashCommand<T>['callback'] {
5556
});
5657
return;
5758
}
59+
60+
if (!(await canAccessRoomAsync(baseChannel, user))) {
61+
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
62+
msg: i18n.t('Room_not_exist_or_not_permission', { lng }),
63+
});
64+
return;
65+
}
66+
5867
const cursor = Subscriptions.findByRoomIdWhenUsernameExists(baseChannel._id, {
5968
projection: { 'u.username': 1 },
6069
});

apps/meteor/server/models/raw/Team.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ export class TeamRaw extends BaseRaw<ITeam> implements ITeamModel {
4545
query?: Filter<ITeam>,
4646
): FindCursor<P> | FindCursor<ITeam> {
4747
if (options === undefined) {
48-
return this.find({ _id: { $in: ids }, ...query });
48+
return this.find({ ...query, _id: { $in: ids } });
4949
}
5050

51-
return this.find({ _id: { $in: ids }, ...query }, options);
51+
return this.find({ ...query, _id: { $in: ids } }, options);
5252
}
5353

5454
findByIdsPaginated(
@@ -57,10 +57,10 @@ export class TeamRaw extends BaseRaw<ITeam> implements ITeamModel {
5757
query?: Filter<ITeam>,
5858
): FindPaginated<FindCursor<ITeam>> {
5959
if (options === undefined) {
60-
return this.findPaginated({ _id: { $in: ids }, ...query });
60+
return this.findPaginated({ ...query, _id: { $in: ids } });
6161
}
6262

63-
return this.findPaginated({ _id: { $in: ids }, ...query }, options);
63+
return this.findPaginated({ ...query, _id: { $in: ids } }, options);
6464
}
6565

6666
findByIdsAndType(ids: Array<string>, type: TEAM_TYPE): FindCursor<ITeam>;

apps/meteor/tests/data/api-data.js

+4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export function methodCall(methodName) {
4646
return api(`method.call/${methodName}`);
4747
}
4848

49+
export function methodCallAnon(methodName) {
50+
return api(`method.callAnon/${methodName}`);
51+
}
52+
4953
export function log(res) {
5054
console.log(res.req.path);
5155
console.log({

apps/meteor/tests/end-to-end/api/01-users.js

+98
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,10 @@ describe('[Users]', function () {
793793
let deactivatedUser;
794794
let user2;
795795
let user2Credentials;
796+
let user3;
797+
let user3Credentials;
798+
let group;
799+
let inviteToken;
796800

797801
before(async () => {
798802
const username = `deactivated_${Date.now()}${apiUsername}`;
@@ -849,14 +853,44 @@ describe('[Users]', function () {
849853
before(async () => {
850854
user2 = await createUser({ joinDefaultChannels: false });
851855
user2Credentials = await login(user2.username, password);
856+
user3 = await createUser({ joinDefaultChannels: false });
857+
user3Credentials = await login(user3.username, password);
852858
});
853859

860+
before('Create a group', async () => {
861+
group = (
862+
await createRoom({
863+
type: 'p',
864+
name: `group.test.${Date.now()}-${Math.random()}`,
865+
})
866+
).body.group;
867+
});
868+
869+
before('Create invite link', async () => {
870+
inviteToken = (
871+
await request.post(api('findOrCreateInvite')).set(credentials).send({
872+
rid: group._id,
873+
days: 0,
874+
maxUses: 0,
875+
})
876+
).body._id;
877+
});
878+
879+
after('Remove invite link', async () =>
880+
request
881+
.delete(api(`removeInvite/${inviteToken}`))
882+
.set(credentials)
883+
.send(),
884+
);
885+
854886
after(() =>
855887
Promise.all([
856888
clearCustomFields(),
857889
deleteUser(deactivatedUser),
858890
deleteUser(user),
859891
deleteUser(user2),
892+
deleteUser(user3),
893+
deleteRoom({ type: 'p', roomId: group._id }),
860894
updatePermission('view-outside-room', ['admin', 'owner', 'moderator', 'user']),
861895
updateSetting('API_Apply_permission_view-outside-room_on_users-list', false),
862896
]),
@@ -979,6 +1013,70 @@ describe('[Users]', function () {
9791013

9801014
await request.get(api('users.list')).set(user2Credentials).expect('Content-Type', 'application/json').expect(403);
9811015
});
1016+
1017+
it('should exclude inviteToken in the user item for privileged users even when fields={inviteToken:1} is specified', async () => {
1018+
await request
1019+
.post(api('useInviteToken'))
1020+
.set(user2Credentials)
1021+
.send({ token: inviteToken })
1022+
.expect(200)
1023+
.expect('Content-Type', 'application/json')
1024+
.expect((res) => {
1025+
expect(res.body).to.have.property('success', true);
1026+
expect(res.body).to.have.property('room');
1027+
expect(res.body.room).to.have.property('rid', group._id);
1028+
});
1029+
1030+
await request
1031+
.get(api('users.list'))
1032+
.set(credentials)
1033+
.expect('Content-Type', 'application/json')
1034+
.query({
1035+
fields: JSON.stringify({ inviteToken: 1 }),
1036+
sort: JSON.stringify({ inviteToken: -1 }),
1037+
count: 100,
1038+
})
1039+
.expect(200)
1040+
.expect((res) => {
1041+
expect(res.body).to.have.property('success', true);
1042+
expect(res.body).to.have.property('users');
1043+
res.body.users.forEach((user) => {
1044+
expect(user).to.not.have.property('inviteToken');
1045+
});
1046+
});
1047+
});
1048+
1049+
it('should exclude inviteToken in the user item for normal users even when fields={inviteToken:1} is specified', async () => {
1050+
await updateSetting('API_Apply_permission_view-outside-room_on_users-list', false);
1051+
await request
1052+
.post(api('useInviteToken'))
1053+
.set(user3Credentials)
1054+
.send({ token: inviteToken })
1055+
.expect(200)
1056+
.expect((res) => {
1057+
expect(res.body).to.have.property('success', true);
1058+
expect(res.body).to.have.property('room');
1059+
expect(res.body.room).to.have.property('rid', group._id);
1060+
});
1061+
1062+
await request
1063+
.get(api('users.list'))
1064+
.set(user3Credentials)
1065+
.expect('Content-Type', 'application/json')
1066+
.query({
1067+
fields: JSON.stringify({ inviteToken: 1 }),
1068+
sort: JSON.stringify({ inviteToken: -1 }),
1069+
count: 100,
1070+
})
1071+
.expect(200)
1072+
.expect((res) => {
1073+
expect(res.body).to.have.property('success', true);
1074+
expect(res.body).to.have.property('users');
1075+
res.body.users.forEach((user) => {
1076+
expect(user).to.not.have.property('inviteToken');
1077+
});
1078+
});
1079+
});
9821080
});
9831081

9841082
describe('Avatars', () => {

0 commit comments

Comments
 (0)