snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import { expect } from 'chai';
|
||||
|
||||
import { BeforeSaveBadWords } from '../../../../../../server/services/messages/hooks/BeforeSaveBadWords';
|
||||
|
||||
const createMessage = (msg?: string) => ({
|
||||
_id: 'random',
|
||||
rid: 'GENERAL',
|
||||
ts: new Date(),
|
||||
u: {
|
||||
_id: 'userId',
|
||||
username: 'username',
|
||||
},
|
||||
_updatedAt: new Date(),
|
||||
msg: msg as string,
|
||||
});
|
||||
|
||||
describe('Filter bad words before saving message', () => {
|
||||
it('should return same message if bad words not configured', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
|
||||
const message = createMessage('hell');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal('hell');
|
||||
});
|
||||
|
||||
it("should return same message if no 'msg' property provided", async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
|
||||
const message = createMessage();
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal(undefined);
|
||||
});
|
||||
|
||||
it('should return filter bad words from message when configured', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
await badWords.configure();
|
||||
|
||||
const message = createMessage('hell');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.equal('****');
|
||||
});
|
||||
|
||||
it('should return same message if bad words disabled after configured', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
await badWords.configure();
|
||||
|
||||
badWords.disable();
|
||||
|
||||
const message = createMessage('hell');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal('hell');
|
||||
});
|
||||
|
||||
it('should filter custom bad words', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
await badWords.configure('good');
|
||||
|
||||
const message = createMessage('good');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal('****');
|
||||
});
|
||||
|
||||
it('should allow custom good words', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
await badWords.configure(undefined, 'hell');
|
||||
|
||||
const message = createMessage('hell');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal('hell');
|
||||
});
|
||||
|
||||
it('should filter non ascii bad words', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
await badWords.configure('バカ');
|
||||
|
||||
const message = createMessage('hell is バカ');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal('**** is **');
|
||||
});
|
||||
|
||||
it('should filter just the non ascii bad words', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
await badWords.configure('バカ');
|
||||
|
||||
const message = createMessage('バカ');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal('**');
|
||||
});
|
||||
|
||||
it('should filter non ascii bad words with punctuation', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
await badWords.configure('バカ');
|
||||
|
||||
const message = createMessage('バカ.');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal('**.');
|
||||
});
|
||||
|
||||
it('should not filter non ascii bad words, if part of another word ', async () => {
|
||||
const badWords = new BeforeSaveBadWords();
|
||||
await badWords.configure('バカ');
|
||||
|
||||
const message = createMessage('TESTバカTEST');
|
||||
|
||||
const result = await badWords.filterBadWords({ message });
|
||||
|
||||
return expect(result.msg).to.be.equal('TESTバカTEST');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,104 @@
|
||||
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 as any);
|
||||
});
|
||||
|
||||
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,0 +1,734 @@
|
||||
import type { IMessage } from '@rocket.chat/core-typings';
|
||||
import { expect } from 'chai';
|
||||
|
||||
import { BeforeSaveJumpToMessage } from '../../../../../../server/services/messages/hooks/BeforeSaveJumpToMessage';
|
||||
|
||||
const createMessage = (msg?: string, extra: Partial<IMessage> = {}) => ({
|
||||
_id: 'random',
|
||||
rid: 'GENERAL',
|
||||
ts: new Date(),
|
||||
u: {
|
||||
_id: 'userId',
|
||||
username: 'username',
|
||||
},
|
||||
_updatedAt: new Date(),
|
||||
msg: msg as string,
|
||||
...extra,
|
||||
});
|
||||
|
||||
const createUser = (username?: string) => ({
|
||||
_id: 'userId',
|
||||
username,
|
||||
name: 'name',
|
||||
language: 'en',
|
||||
});
|
||||
|
||||
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 countDeep = (msg: any, deep = 1): number => {
|
||||
if (!msg) {
|
||||
return deep - 1;
|
||||
}
|
||||
|
||||
if (Array.isArray(msg?.attachments) && msg.attachments.length > 0) {
|
||||
return msg.attachments.reduce((count: number, att: any) => Math.max(countDeep(att, deep + 1), count), 0);
|
||||
}
|
||||
|
||||
return deep - 1;
|
||||
};
|
||||
|
||||
describe('Create attachments for message URLs', () => {
|
||||
it('should return message without attatchment and URLs if no URL provided', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey'),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
return expect(message).to.not.have.property('urls');
|
||||
});
|
||||
|
||||
it('should do nothing if URL is not from SiteUrl', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://google.com',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').of.length(1);
|
||||
expect(message).to.not.have.property('attachments');
|
||||
});
|
||||
|
||||
it('should do nothing if URL is from SiteUrl but not have a query string', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').of.length(1);
|
||||
expect(message).to.not.have.property('attachments');
|
||||
});
|
||||
|
||||
it('should do nothing if URL is from SiteUrl but not have a msgId query string', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/?token=value',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').of.length(1);
|
||||
expect(message).to.not.have.property('attachments');
|
||||
});
|
||||
|
||||
it('should do nothing if it do not find a msg from the URL', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/?msg=value',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').of.length(1);
|
||||
expect(message).to.not.have.property('attachments');
|
||||
});
|
||||
|
||||
it('should do nothing if it cannot find the room of the message from the URL', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/?msg=value',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').of.length(1);
|
||||
expect(message).to.not.have.property('attachments');
|
||||
});
|
||||
|
||||
it('should do nothing if user dont have access to the room of the message from the URL', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => false,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/?msg=value',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').of.length(1);
|
||||
expect(message).to.not.have.property('attachments');
|
||||
});
|
||||
|
||||
it('should not duplicate quote attachment from the message if message_link is the same as the URL', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
attachments: [
|
||||
{
|
||||
text: 'old attachment',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linked',
|
||||
ts: new Date(),
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(1);
|
||||
|
||||
const [url] = message.urls ?? [];
|
||||
|
||||
expect(url).to.include({
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
ignoreParse: true,
|
||||
});
|
||||
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(1);
|
||||
|
||||
const [attachment] = message.attachments ?? [];
|
||||
|
||||
expect(attachment).to.have.property('text', 'linked message');
|
||||
});
|
||||
|
||||
it('should remove existing quote attachments provided in the message if they are not in the urls field', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [],
|
||||
attachments: [
|
||||
{
|
||||
text: 'old attachment',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linked',
|
||||
ts: new Date(),
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(0);
|
||||
});
|
||||
|
||||
it('should not consider attachments with undefined message_link as quotes', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [],
|
||||
attachments: [
|
||||
{
|
||||
text: 'old attachment',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
message_link: undefined,
|
||||
ts: new Date(),
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(1);
|
||||
const [attachment] = message.attachments ?? [];
|
||||
expect(attachment).to.have.property('text', 'old attachment');
|
||||
});
|
||||
|
||||
it('should return an attachment with the message content if a message URL is provided', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(1);
|
||||
|
||||
const [url] = message.urls ?? [];
|
||||
|
||||
expect(url).to.include({
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
ignoreParse: true,
|
||||
});
|
||||
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(1);
|
||||
|
||||
const [attachment] = message.attachments ?? [];
|
||||
|
||||
expect(attachment).to.have.property('text', 'linked message');
|
||||
});
|
||||
|
||||
it('should respect chain limit config', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [
|
||||
createMessage('linked message', {
|
||||
_id: 'linked',
|
||||
attachments: [
|
||||
{
|
||||
text: 'chained 1',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
ts: new Date(),
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linkedMsgId',
|
||||
attachments: [
|
||||
{
|
||||
text: 'chained 2',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linkedMsgId',
|
||||
ts: new Date(),
|
||||
attachments: [
|
||||
{
|
||||
text: 'chained 3',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linkedMsgId',
|
||||
ts: new Date(),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 3,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(1);
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(1);
|
||||
|
||||
const deep = countDeep(message);
|
||||
expect(deep).to.be.eq(3);
|
||||
});
|
||||
|
||||
it('should respect chain limit config but keep the file attachments of last chained message', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [
|
||||
createMessage('linked message', {
|
||||
_id: 'linked',
|
||||
attachments: [
|
||||
{
|
||||
text: 'chained 1',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
ts: new Date(),
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linkedMsgId',
|
||||
attachments: [
|
||||
{
|
||||
text: 'chained 2',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linkedMsgId',
|
||||
ts: new Date(),
|
||||
attachments: [
|
||||
{
|
||||
ts: new Date(),
|
||||
title: 'file.png',
|
||||
title_link: 'title-link',
|
||||
title_link_download: true,
|
||||
image_dimensions: {
|
||||
width: 480,
|
||||
height: 269,
|
||||
},
|
||||
image_preview: 'image-preview',
|
||||
image_url: 'image-url',
|
||||
image_type: 'image/png',
|
||||
image_size: 68016,
|
||||
type: 'file',
|
||||
description: 'chained 3 - file',
|
||||
descriptionMd: [
|
||||
{
|
||||
type: 'PARAGRAPH',
|
||||
value: [
|
||||
{
|
||||
type: 'PLAIN_TEXT',
|
||||
value: 'chained 3 - file',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 3,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(1);
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(1);
|
||||
|
||||
const deep = countDeep(message);
|
||||
expect(deep).to.be.eq(4, 'The chain limit should be respected, but the file attachments of the last chained message should be kept.');
|
||||
});
|
||||
|
||||
it('should create the attachment if cannot access room but message has a livechat token', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom({ t: 'l', v: { token: 'livechatToken' } })],
|
||||
canAccessRoom: async () => false,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
token: 'livechatToken',
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(1);
|
||||
|
||||
const [url] = message.urls ?? [];
|
||||
|
||||
expect(url).to.include({
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
ignoreParse: true,
|
||||
});
|
||||
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(1);
|
||||
|
||||
const [attachment] = message.attachments ?? [];
|
||||
|
||||
expect(attachment).to.have.property('text', 'linked message');
|
||||
});
|
||||
|
||||
it('should do nothing if cannot access room but message has a livechat token but is not from the room does not have a token', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [createMessage('linked message', { _id: 'linked' })],
|
||||
getRooms: async () => [createRoom({ t: 'l' })],
|
||||
canAccessRoom: async () => false,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=linked',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
token: 'another-token',
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 10,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(1);
|
||||
expect(message).to.not.have.property('attachments');
|
||||
});
|
||||
|
||||
it('should remove the clean up the attachments of the quoted message property if chain limit < 2', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => [
|
||||
createMessage('linked message', {
|
||||
_id: 'linkedMsgId',
|
||||
attachments: [
|
||||
{
|
||||
text: 'chained 1',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linkedMsgId1',
|
||||
ts: new Date(),
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=linkedMsgId',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 1,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(1);
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(1);
|
||||
|
||||
const deep = countDeep(message);
|
||||
expect(deep).to.be.eq(1);
|
||||
|
||||
const [attachment] = message.attachments ?? [];
|
||||
|
||||
expect(attachment).to.have.property('attachments').and.to.have.lengthOf(0);
|
||||
expect(attachment).to.include({
|
||||
text: 'linked message',
|
||||
author_name: 'username',
|
||||
author_icon: 'url',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=linkedMsgId',
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for multiple URLs', async () => {
|
||||
const jumpToMessage = new BeforeSaveJumpToMessage({
|
||||
getMessages: async () => {
|
||||
return [
|
||||
createMessage('first message', {
|
||||
_id: 'msg1',
|
||||
}),
|
||||
createMessage('second message', {
|
||||
_id: 'msg2',
|
||||
}),
|
||||
];
|
||||
},
|
||||
getRooms: async () => [createRoom()],
|
||||
canAccessRoom: async () => true,
|
||||
getUserAvatarURL: () => 'url',
|
||||
});
|
||||
|
||||
const message = await jumpToMessage.createAttachmentForMessageURLs({
|
||||
message: createMessage('hey', {
|
||||
urls: [
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=msg1',
|
||||
meta: {},
|
||||
},
|
||||
{
|
||||
url: 'https://open.rocket.chat/linked?msg=msg2',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
user: createUser(),
|
||||
config: {
|
||||
chainLimit: 1,
|
||||
siteUrl: 'https://open.rocket.chat',
|
||||
useRealName: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(2);
|
||||
expect(message).to.have.property('attachments').and.to.have.lengthOf(2);
|
||||
|
||||
const deep = countDeep(message);
|
||||
expect(deep).to.be.eq(1);
|
||||
|
||||
const [att1, att2] = message.attachments ?? [];
|
||||
|
||||
expect(att1).to.include({
|
||||
text: 'first message',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=msg1',
|
||||
});
|
||||
|
||||
expect(att2).to.include({
|
||||
text: 'second message',
|
||||
message_link: 'https://open.rocket.chat/linked?msg=msg2',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,110 @@
|
||||
import { expect } from 'chai';
|
||||
import { beforeEach } from 'mocha';
|
||||
|
||||
import { BeforeSaveMarkdownParser } from '../../../../../../server/services/messages/hooks/BeforeSaveMarkdownParser';
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
describe('Markdown parser', () => {
|
||||
beforeEach(() => {
|
||||
delete process.env.MESSAGE_MAX_PARSE_LENGTH;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete process.env.MESSAGE_MAX_PARSE_LENGTH;
|
||||
});
|
||||
|
||||
it('should do nothing if markdown parser is disabled', async () => {
|
||||
const markdownParser = new BeforeSaveMarkdownParser(false);
|
||||
|
||||
const message = await markdownParser.parseMarkdown({
|
||||
message: createMessage('hey'),
|
||||
config: {},
|
||||
});
|
||||
|
||||
expect(message).to.not.have.property('md');
|
||||
});
|
||||
|
||||
it('should do nothing for E2E messages', async () => {
|
||||
const markdownParser = new BeforeSaveMarkdownParser(true);
|
||||
|
||||
const message = await markdownParser.parseMarkdown({
|
||||
message: createMessage('hey', { t: 'e2e' }),
|
||||
config: {},
|
||||
});
|
||||
|
||||
expect(message).to.not.have.property('md');
|
||||
});
|
||||
|
||||
it('should skip parsing when msg exceeds MESSAGE_MAX_PARSE_LENGTH', async () => {
|
||||
process.env.MESSAGE_MAX_PARSE_LENGTH = '10';
|
||||
const markdownParser = new BeforeSaveMarkdownParser(true);
|
||||
|
||||
const message = await markdownParser.parseMarkdown({
|
||||
message: createMessage('a'.repeat(11)),
|
||||
config: {},
|
||||
});
|
||||
|
||||
expect(message).to.not.have.property('md');
|
||||
});
|
||||
|
||||
it('should parse normally when msg is within MESSAGE_MAX_PARSE_LENGTH', async () => {
|
||||
process.env.MESSAGE_MAX_PARSE_LENGTH = '100';
|
||||
const markdownParser = new BeforeSaveMarkdownParser(true);
|
||||
|
||||
const message = await markdownParser.parseMarkdown({
|
||||
message: createMessage('short msg'),
|
||||
config: {},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('md');
|
||||
});
|
||||
|
||||
it('should parse normally when MESSAGE_MAX_PARSE_LENGTH is 0', async () => {
|
||||
process.env.MESSAGE_MAX_PARSE_LENGTH = '0';
|
||||
const markdownParser = new BeforeSaveMarkdownParser(true);
|
||||
|
||||
const message = await markdownParser.parseMarkdown({
|
||||
message: createMessage('short msg'),
|
||||
config: {},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('md');
|
||||
});
|
||||
|
||||
it('should parse markdown on the first attachment only', async () => {
|
||||
const markdownParser = new BeforeSaveMarkdownParser(true);
|
||||
|
||||
const message = await markdownParser.parseMarkdown({
|
||||
message: createMessage('hey', {
|
||||
attachments: [
|
||||
{
|
||||
description: 'hey ho',
|
||||
},
|
||||
{
|
||||
description: 'lets go',
|
||||
},
|
||||
],
|
||||
}),
|
||||
config: {},
|
||||
});
|
||||
|
||||
expect(message).to.have.property('md');
|
||||
|
||||
const [attachment1, attachment2] = message.attachments || [];
|
||||
|
||||
expect(attachment1).to.have.property('descriptionMd');
|
||||
expect(attachment2).to.not.have.property('descriptionMd');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,114 @@
|
||||
import { expect } from 'chai';
|
||||
import proxyquire from 'proxyquire';
|
||||
|
||||
const Authorization = {
|
||||
hasPermission: async (_uid: string, _permission: string, _room?: string): Promise<boolean> => true,
|
||||
};
|
||||
|
||||
class MeteorError extends Error {}
|
||||
|
||||
const { BeforeSavePreventMention } = proxyquire
|
||||
.noCallThru()
|
||||
.load('../../../../../../server/services/messages/hooks/BeforeSavePreventMention', {
|
||||
'@rocket.chat/core-services': {
|
||||
Authorization,
|
||||
MeteorError,
|
||||
},
|
||||
'../../../lib/i18n': {
|
||||
i18n: {
|
||||
t: (s: any) => s,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('Prevent mention on messages', () => {
|
||||
it('should return void if message has no mentions', async () => {
|
||||
const preventMention = new BeforeSavePreventMention();
|
||||
|
||||
return expect(
|
||||
preventMention.preventMention({
|
||||
message: { rid: 'GENERAL', msg: 'hey', u: { _id: 'random' } },
|
||||
user: { _id: 'userId', language: 'en' },
|
||||
mention: 'all',
|
||||
permission: 'mention-all',
|
||||
}),
|
||||
).to.eventually.be.true;
|
||||
});
|
||||
|
||||
it("should return void if message doesnt't have @all mention", () => {
|
||||
const preventMention = new BeforeSavePreventMention();
|
||||
|
||||
return expect(
|
||||
preventMention.preventMention({
|
||||
message: { rid: 'GENERAL', msg: 'hey', mentions: [{ _id: 'here' }], u: { _id: 'random' } },
|
||||
user: { _id: 'userId', language: 'en' },
|
||||
mention: 'all',
|
||||
permission: 'mention-all',
|
||||
}),
|
||||
).to.eventually.be.true;
|
||||
});
|
||||
|
||||
it("should return void if message doesnt't have @here mention", () => {
|
||||
const preventMention = new BeforeSavePreventMention();
|
||||
|
||||
return expect(
|
||||
preventMention.preventMention({
|
||||
message: { rid: 'GENERAL', msg: 'hey', mentions: [{ _id: 'all' }], u: { _id: 'random' } },
|
||||
user: { _id: 'userId', language: 'en' },
|
||||
mention: 'all',
|
||||
permission: 'mention-here',
|
||||
}),
|
||||
).to.eventually.be.true;
|
||||
});
|
||||
|
||||
it('should return true if user has required permission', () => {
|
||||
const preventMention = new BeforeSavePreventMention();
|
||||
|
||||
Authorization.hasPermission = async () => true;
|
||||
|
||||
return expect(
|
||||
preventMention.preventMention({
|
||||
message: { rid: 'GENERAL', msg: 'hey', mentions: [{ _id: 'all' }], u: { _id: 'random' } },
|
||||
user: { _id: 'userId', language: 'en' },
|
||||
mention: 'all',
|
||||
permission: 'mention-all',
|
||||
}),
|
||||
).to.eventually.be.true;
|
||||
});
|
||||
|
||||
it('should return void if user has required permission on room scope', () => {
|
||||
const preventMention = new BeforeSavePreventMention();
|
||||
|
||||
Authorization.hasPermission = async (_uid, _permission, room) => {
|
||||
if (room) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
return expect(
|
||||
preventMention.preventMention({
|
||||
message: { rid: 'GENERAL', msg: 'hey', mentions: [{ _id: 'all' }], u: { _id: 'random' } },
|
||||
user: { _id: 'userId', language: 'en' },
|
||||
mention: 'all',
|
||||
permission: 'mention-all',
|
||||
}),
|
||||
).to.eventually.be.true;
|
||||
});
|
||||
|
||||
it("should throw if user doesn't have required permissions", () => {
|
||||
Authorization.hasPermission = async (_uid, _permission, _room) => false;
|
||||
|
||||
const preventMention = new BeforeSavePreventMention();
|
||||
|
||||
return expect(
|
||||
preventMention.preventMention({
|
||||
message: { rid: 'GENERAL', msg: 'hey', mentions: [{ _id: 'all' }], u: { _id: 'random' } },
|
||||
user: { _id: 'userId', language: 'en' },
|
||||
mention: 'all',
|
||||
permission: 'mention-all',
|
||||
}),
|
||||
).to.be.rejectedWith(MeteorError);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
import { expect } from 'chai';
|
||||
|
||||
import { BeforeSaveSpotify } from '../../../../../../server/services/messages/hooks/BeforeSaveSpotify';
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
describe('Convert Spotify syntax to URLs', () => {
|
||||
it('should return no URLs if no Spotify syntax provided', async () => {
|
||||
const spotify = new BeforeSaveSpotify();
|
||||
|
||||
const message = await spotify.convertSpotifyLinks({
|
||||
message: createMessage('hey'),
|
||||
});
|
||||
|
||||
return expect(message).to.not.have.property('urls');
|
||||
});
|
||||
|
||||
it('should return no URLs if an undefined message is provided', async () => {
|
||||
const spotify = new BeforeSaveSpotify();
|
||||
|
||||
const message = await spotify.convertSpotifyLinks({
|
||||
message: createMessage(),
|
||||
});
|
||||
|
||||
return expect(message).to.not.have.property('urls');
|
||||
});
|
||||
|
||||
it('should not return a Spotify URL if some Spotify syntax is provided within a code block', async () => {
|
||||
const spotify = new BeforeSaveSpotify();
|
||||
|
||||
const message = await spotify.convertSpotifyLinks({
|
||||
message: createMessage('test\n```\nspotify:track:1q6IK1l4qpYykOaWaLJkWG\n```'),
|
||||
});
|
||||
|
||||
return expect(message).to.not.have.property('urls');
|
||||
});
|
||||
|
||||
it('should not return a Spotify URL if some Spotify syntax is provided within a inline code', async () => {
|
||||
const spotify = new BeforeSaveSpotify();
|
||||
|
||||
const message = await spotify.convertSpotifyLinks({
|
||||
message: createMessage('test `spotify:track:1q6IK1l4qpYykOaWaLJkWG` ok'),
|
||||
});
|
||||
|
||||
return expect(message).to.not.have.property('urls');
|
||||
});
|
||||
|
||||
it('should return a Spotify URL if some Spotify syntax is provided', async () => {
|
||||
const spotify = new BeforeSaveSpotify();
|
||||
|
||||
const message = await spotify.convertSpotifyLinks({
|
||||
message: createMessage('spotify:track:1q6IK1l4qpYykOaWaLJkWG'),
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(1);
|
||||
|
||||
const [url] = message.urls ?? [];
|
||||
|
||||
expect(url).to.have.property('url', 'https://open.spotify.com/track/1q6IK1l4qpYykOaWaLJkWG');
|
||||
expect(url).to.have.property('source', 'spotify:track:1q6IK1l4qpYykOaWaLJkWG');
|
||||
});
|
||||
|
||||
it('should append a Spotify URL when Spotify syntax is provided with already existing URLs', async () => {
|
||||
const spotify = new BeforeSaveSpotify();
|
||||
|
||||
const message = await spotify.convertSpotifyLinks({
|
||||
message: createMessage('spotify:track:1q6IK1l4qpYykOaWaLJkWG', {
|
||||
urls: [{ url: 'https://rocket.chat' }],
|
||||
}),
|
||||
});
|
||||
|
||||
expect(message).to.have.property('urls').and.to.have.lengthOf(2);
|
||||
|
||||
const [url1, url2] = message.urls ?? [];
|
||||
|
||||
expect(url1).to.have.property('url', 'https://rocket.chat');
|
||||
|
||||
expect(url2).to.have.property('url', 'https://open.spotify.com/track/1q6IK1l4qpYykOaWaLJkWG');
|
||||
expect(url2).to.have.property('source', 'spotify:track:1q6IK1l4qpYykOaWaLJkWG');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user