Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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/neat-trams-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Ensures the Meteor method for translateMessage validates access and types
21 changes: 20 additions & 1 deletion apps/meteor/app/autotranslate/server/methods/translateMessage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { IMessage } from '@rocket.chat/core-typings';
import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Rooms } from '@rocket.chat/models';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';

import { canAccessRoomAsync } from '../../../authorization/server';
import { translateMessage } from '../functions/translateMessage';

declare module '@rocket.chat/ddp-client' {
Expand All @@ -13,6 +16,22 @@ declare module '@rocket.chat/ddp-client' {

Meteor.methods<ServerMethods>({
async 'autoTranslate.translateMessage'(message, targetLanguage) {
return translateMessage(targetLanguage, message);
const userId = Meteor.userId();
if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'autoTranslate.translateMessage',
});
}
check(message?._id, String);
check(targetLanguage, String);
const msg = await Messages.findOneById(message._id);
if (!msg) {
throw new Meteor.Error('error-message-not-found', 'Message not found');
}
const room = await Rooms.findOneById(msg.rid);
if (!room || !(await canAccessRoomAsync(room, { _id: userId }))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed');
}
return translateMessage(targetLanguage, msg);
},
});
90 changes: 89 additions & 1 deletion apps/meteor/tests/end-to-end/api/autotranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings';
import { expect } from 'chai';
import { before, describe, after, it } from 'mocha';

import { getCredentials, api, request, credentials } from '../../data/api-data';
import { getCredentials, api, request, credentials, methodCall } from '../../data/api-data';
import { sendSimpleMessage } from '../../data/chat.helper';
import { updatePermission, updateSetting } from '../../data/permissions.helper';
import { createRoom, deleteRoom } from '../../data/rooms.helper';
Expand Down Expand Up @@ -434,6 +434,94 @@ describe('AutoTranslate', () => {
});
});

describe('[autoTranslate.translateMessage method]', () => {
let userA: TestUser<IUser>;
let userB: TestUser<IUser>;
let credA: Credentials;
let credB: Credentials;
let privateRoom: IRoom;
let privateMessage: IMessage;

before(async () => {
await updateSetting('AutoTranslate_Enabled', true);

userA = await createUser();
userB = await createUser();

credA = await login(userA.username, password);
credB = await login(userB.username, password);

privateRoom = (
await createRoom({
type: 'p',
name: `test-autotranslate-method-${Date.now()}`,
credentials: credA,
})
).body.group;

const msgRes = await sendSimpleMessage({
roomId: privateRoom._id,
text: 'Isso é um teste',
userCredentials: credA,
});
privateMessage = msgRes.body.message;
});

after(async () => {
await Promise.all([
updateSetting('AutoTranslate_Enabled', false),
deleteUser(userA),
deleteUser(userB),
deleteRoom({ type: 'p', roomId: privateRoom._id }),
]);
});

it('should fail when messageId is not a string', (done) => {
void request
.post(methodCall('autoTranslate.translateMessage'))
.set(credA)
.send({
message: JSON.stringify({
msg: 'method',
id: 'id',
method: 'autoTranslate.translateMessage',
params: [{ _id: { $gt: '' } }, 'en'],
}),
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
const parsedBody = JSON.parse(res.body.message);
expect(parsedBody).to.have.a.property('error');
})
.end(done);
});

it('should return error-not-allowed when the caller is not a member of the room', (done) => {
void request
.post(methodCall('autoTranslate.translateMessage'))
.set(credB)
.send({
message: JSON.stringify({
msg: 'method',
id: 'id',
method: 'autoTranslate.translateMessage',
params: [{ _id: privateMessage._id }, 'en'],
}),
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
const parsedBody = JSON.parse(res.body.message);
expect(parsedBody).to.have.a.property('error');
expect(parsedBody.error).to.have.a.property('error', 'error-not-allowed');
})
.end(done);
});
});

describe('Autoenable setting', () => {
let userA: TestUser<IUser>;
let userB: TestUser<IUser>;
Expand Down
Loading