Skip to content
Snippets Groups Projects
Unverified Commit 8b3ee664 authored by Diego Sampaio's avatar Diego Sampaio Committed by GitHub
Browse files

refactor: convert MAC check callback to class (#31231)

parent bfbfb8bc
No related branches found
No related tags found
No related merge requests found
import { Omnichannel } from '@rocket.chat/core-services';
import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
import { isEditedMessage } from '@rocket.chat/core-typings';
import { callbacks } from '../../../../lib/callbacks';
callbacks.add('beforeSaveMessage', async (message, room) => {
if (!room || room.t !== 'l') {
return message;
}
if (isEditedMessage(message)) {
return message;
}
if (message.token) {
return message;
}
if (message.t) {
return message;
}
const canSendMessage = await Omnichannel.isWithinMACLimit(room as IOmnichannelRoom);
if (!canSendMessage) {
throw new Error('error-mac-limit-reached');
}
return message;
});
......@@ -16,7 +16,6 @@ import './hooks/saveContactLastChat';
import './hooks/saveLastMessageToInquiry';
import './hooks/afterUserActions';
import './hooks/afterAgentRemoved';
import './hooks/checkMAC';
import './methods/addAgent';
import './methods/addManager';
import './methods/changeLivechatStatus';
......
import { MeteorError, Omnichannel } from '@rocket.chat/core-services';
import type { IRoom } from '@rocket.chat/core-typings';
import { isOmnichannelRoom, type IMessage } from '@rocket.chat/core-typings';
export class BeforeSaveCheckMAC {
async isWithinLimits({ message, room }: { message: IMessage; room: IRoom }): Promise<void> {
if (!isOmnichannelRoom(room)) {
return;
}
if (message.token) {
return;
}
if (message.t) {
return;
}
const canSendMessage = await Omnichannel.isWithinMACLimit(room);
if (!canSendMessage) {
throw new MeteorError('error-mac-limit-reached');
}
}
}
......@@ -12,6 +12,7 @@ import { settings } from '../../../app/settings/server';
import { getUserAvatarURL } from '../../../app/utils/server/getUserAvatarURL';
import { broadcastMessageSentEvent } from '../../modules/watchers/lib/messages';
import { BeforeSaveBadWords } from './hooks/BeforeSaveBadWords';
import { BeforeSaveCheckMAC } from './hooks/BeforeSaveCheckMAC';
import { BeforeSaveJumpToMessage } from './hooks/BeforeSaveJumpToMessage';
import { BeforeSavePreventMention } from './hooks/BeforeSavePreventMention';
import { BeforeSaveSpotify } from './hooks/BeforeSaveSpotify';
......@@ -27,6 +28,8 @@ export class MessageService extends ServiceClassInternal implements IMessageServ
private jumpToMessage: BeforeSaveJumpToMessage;
private checkMAC: BeforeSaveCheckMAC;
async created() {
this.preventMention = new BeforeSavePreventMention(this.api);
this.badWords = new BeforeSaveBadWords();
......@@ -45,6 +48,7 @@ export class MessageService extends ServiceClassInternal implements IMessageServ
return (user && getUserAvatarURL(user)) || '';
},
});
this.checkMAC = new BeforeSaveCheckMAC();
await this.configureBadWords();
}
......@@ -134,6 +138,7 @@ export class MessageService extends ServiceClassInternal implements IMessageServ
if (!this.isEditedOrOld(message)) {
await Promise.all([
this.checkMAC.isWithinLimits({ message, room: _room }),
this.preventMention.preventMention({ message, user, mention: 'all', permission: 'mention-all' }),
this.preventMention.preventMention({ message, user, mention: 'here', permission: 'mention-here' }),
]);
......
export class BrokerMocked {
actions: Record<string, (...params: unknown[]) => Promise<unknown>> = {};
destroyService(): void {
// no op
}
createService(): void {
// no op
}
async call(method: string, data: any): Promise<any> {
return this.actions[method](data);
}
async waitAndCall(method: string, data: any): Promise<any> {
return this.actions[method](data);
}
async broadcastToServices(): Promise<void> {
// no op
}
async broadcast(): Promise<void> {
// no op
}
async broadcastLocal(): Promise<void> {
// no op
}
async nodeList(): Promise<any> {
// no op
}
async start(): Promise<void> {
// no op
}
mockServices(actions: Record<string, () => Promise<unknown>>) {
this.actions = actions;
}
}
import { api, MeteorError } from '@rocket.chat/core-services';
import { expect } from 'chai';
import { before, describe } from 'mocha';
import { BeforeSaveCheckMAC } from '../../../../../../server/services/messages/hooks/BeforeSaveCheckMAC';
import { BrokerMocked } from '../../../../../mocks/server/BrokerMocked';
const createMessage = (msg?: string, extra: any = {}) => ({
_id: 'random',
rid: 'GENERAL',
ts: new Date(),
u: {
_id: 'userId',
username: 'username',
},
_updatedAt: new Date(),
msg: msg as string,
...extra,
});
const createRoom = (extra: any = {}): any => ({
_id: 'GENERAL',
t: 'c',
u: {
_id: 'userId',
username: 'username',
name: 'name',
},
msgs: 1,
usersCount: 1,
_updatedAt: new Date(),
...extra,
});
const broker = new BrokerMocked();
describe('Check MAC', () => {
before(() => {
api.setBroker(broker);
});
it('should do nothing if not omnichannel room', async () => {
const checkMAC = new BeforeSaveCheckMAC();
const empty = await checkMAC.isWithinLimits({
message: createMessage('hey'),
room: createRoom(),
});
expect(empty).to.not.have.value;
});
it('should do nothing if message from visitor', async () => {
const checkMAC = new BeforeSaveCheckMAC();
const empty = await checkMAC.isWithinLimits({
message: createMessage('hey', { token: 'hash' }),
room: createRoom({ t: 'l' }),
});
expect(empty).to.not.have.value;
});
it('should do nothing if it is a system message', async () => {
const checkMAC = new BeforeSaveCheckMAC();
const empty = await checkMAC.isWithinLimits({
message: createMessage('hey', { t: 'uj' }),
room: createRoom({ t: 'l' }),
});
expect(empty).to.not.have.value;
});
it('should throw an error if not within limits', () => {
const checkMAC = new BeforeSaveCheckMAC();
broker.mockServices({
'omnichannel.isWithinMACLimit': async () => false,
});
void expect(
checkMAC.isWithinLimits({
message: createMessage('hey'),
room: createRoom({ t: 'l' }),
}),
).to.be.rejectedWith(MeteorError, 'error-mac-limit-reached');
});
it('should work if MAC within limits', async () => {
const checkMAC = new BeforeSaveCheckMAC();
broker.mockServices({
'omnichannel.isWithinMACLimit': async () => true,
});
const empty = await checkMAC.isWithinLimits({
message: createMessage('hey'),
room: createRoom({ t: 'l' }),
});
expect(empty).to.not.have.value;
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment