Skip to content

Commit e48e4a9

Browse files
committed
fix: imported fixes (#32690)
1 parent 1a2ca07 commit e48e4a9

File tree

14 files changed

+539
-20
lines changed

14 files changed

+539
-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
@@ -61,6 +61,7 @@ interface IAPIDefaultFieldsToExclude {
6161
statusDefault: number;
6262
_updatedAt: number;
6363
settings: number;
64+
inviteToken: number;
6465
}
6566

6667
type RateLimiterOptions = {
@@ -147,6 +148,7 @@ export class APIClass<TBasePath extends string = ''> extends Restivus {
147148

148149
public limitedUserFieldsToExcludeIfIsPrivilegedUser: {
149150
services: number;
151+
inviteToken: number;
150152
};
151153

152154
constructor(properties: IAPIProperties) {
@@ -174,10 +176,12 @@ export class APIClass<TBasePath extends string = ''> extends Restivus {
174176
statusDefault: 0,
175177
_updatedAt: 0,
176178
settings: 0,
179+
inviteToken: 0,
177180
};
178181
this.limitedUserFieldsToExclude = this.defaultLimitedUserFieldsToExclude;
179182
this.limitedUserFieldsToExcludeIfIsPrivilegedUser = {
180183
services: 0,
184+
inviteToken: 0,
181185
};
182186
}
183187

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
@@ -777,6 +777,10 @@ describe('[Users]', function () {
777777
let deactivatedUser;
778778
let user2;
779779
let user2Credentials;
780+
let user3;
781+
let user3Credentials;
782+
let group;
783+
let inviteToken;
780784

781785
before(async () => {
782786
const username = `deactivated_${Date.now()}${apiUsername}`;
@@ -833,14 +837,44 @@ describe('[Users]', function () {
833837
before(async () => {
834838
user2 = await createUser({ joinDefaultChannels: false });
835839
user2Credentials = await login(user2.username, password);
840+
user3 = await createUser({ joinDefaultChannels: false });
841+
user3Credentials = await login(user3.username, password);
836842
});
837843

844+
before('Create a group', async () => {
845+
group = (
846+
await createRoom({
847+
type: 'p',
848+
name: `group.test.${Date.now()}-${Math.random()}`,
849+
})
850+
).body.group;
851+
});
852+
853+
before('Create invite link', async () => {
854+
inviteToken = (
855+
await request.post(api('findOrCreateInvite')).set(credentials).send({
856+
rid: group._id,
857+
days: 0,
858+
maxUses: 0,
859+
})
860+
).body._id;
861+
});
862+
863+
after('Remove invite link', async () =>
864+
request
865+
.delete(api(`removeInvite/${inviteToken}`))
866+
.set(credentials)
867+
.send(),
868+
);
869+
838870
after(() =>
839871
Promise.all([
840872
clearCustomFields(),
841873
deleteUser(deactivatedUser),
842874
deleteUser(user),
843875
deleteUser(user2),
876+
deleteUser(user3),
877+
deleteRoom({ type: 'p', roomId: group._id }),
844878
updatePermission('view-outside-room', ['admin', 'owner', 'moderator', 'user']),
845879
updateSetting('API_Apply_permission_view-outside-room_on_users-list', false),
846880
]),
@@ -963,6 +997,70 @@ describe('[Users]', function () {
963997

964998
await request.get(api('users.list')).set(user2Credentials).expect('Content-Type', 'application/json').expect(403);
965999
});
1000+
1001+
it('should exclude inviteToken in the user item for privileged users even when fields={inviteToken:1} is specified', async () => {
1002+
await request
1003+
.post(api('useInviteToken'))
1004+
.set(user2Credentials)
1005+
.send({ token: inviteToken })
1006+
.expect(200)
1007+
.expect('Content-Type', 'application/json')
1008+
.expect((res) => {
1009+
expect(res.body).to.have.property('success', true);
1010+
expect(res.body).to.have.property('room');
1011+
expect(res.body.room).to.have.property('rid', group._id);
1012+
});
1013+
1014+
await request
1015+
.get(api('users.list'))
1016+
.set(credentials)
1017+
.expect('Content-Type', 'application/json')
1018+
.query({
1019+
fields: JSON.stringify({ inviteToken: 1 }),
1020+
sort: JSON.stringify({ inviteToken: -1 }),
1021+
count: 100,
1022+
})
1023+
.expect(200)
1024+
.expect((res) => {
1025+
expect(res.body).to.have.property('success', true);
1026+
expect(res.body).to.have.property('users');
1027+
res.body.users.forEach((user) => {
1028+
expect(user).to.not.have.property('inviteToken');
1029+
});
1030+
});
1031+
});
1032+
1033+
it('should exclude inviteToken in the user item for normal users even when fields={inviteToken:1} is specified', async () => {
1034+
await updateSetting('API_Apply_permission_view-outside-room_on_users-list', false);
1035+
await request
1036+
.post(api('useInviteToken'))
1037+
.set(user3Credentials)
1038+
.send({ token: inviteToken })
1039+
.expect(200)
1040+
.expect((res) => {
1041+
expect(res.body).to.have.property('success', true);
1042+
expect(res.body).to.have.property('room');
1043+
expect(res.body.room).to.have.property('rid', group._id);
1044+
});
1045+
1046+
await request
1047+
.get(api('users.list'))
1048+
.set(user3Credentials)
1049+
.expect('Content-Type', 'application/json')
1050+
.query({
1051+
fields: JSON.stringify({ inviteToken: 1 }),
1052+
sort: JSON.stringify({ inviteToken: -1 }),
1053+
count: 100,
1054+
})
1055+
.expect(200)
1056+
.expect((res) => {
1057+
expect(res.body).to.have.property('success', true);
1058+
expect(res.body).to.have.property('users');
1059+
res.body.users.forEach((user) => {
1060+
expect(user).to.not.have.property('inviteToken');
1061+
});
1062+
});
1063+
});
9661064
});
9671065

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

0 commit comments

Comments
 (0)