Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,6 @@ tests/end-to-end/temporary_staged_test
.screenshots
/private/livechat
/storybook-static
/tests/cypress/screenshots
/tests/cypress/screenshots
coverage
.nyc_output
1 change: 1 addition & 0 deletions .meteorignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ee/server/services
coverage
94 changes: 60 additions & 34 deletions app/oembed/server/jumpToMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import QueryString from 'querystring';
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';

import { Messages } from '../../models';
import { settings } from '../../settings';
import { callbacks } from '../../callbacks';
import { Messages, Rooms, Users } from '../../models/server';
import { settings } from '../../settings/server';
import { callbacks } from '../../callbacks/server';
import { getUserAvatarURL } from '../../utils/lib/getUserAvatarURL';
import { canAccessRoom } from '../../authorization/server/functions/canAccessRoom';

const recursiveRemove = (message, deep = 1) => {
if (message) {
Expand All @@ -21,37 +22,62 @@ const recursiveRemove = (message, deep = 1) => {
};

callbacks.add('beforeSaveMessage', (msg) => {
if (msg && msg.urls) {
msg.urls.forEach((item) => {
if (item.url.indexOf(Meteor.absoluteUrl()) === 0) {
const urlObj = URL.parse(item.url);
if (urlObj.query) {
const queryString = QueryString.parse(urlObj.query);
if (_.isString(queryString.msg)) { // Jump-to query param
const jumpToMessage = recursiveRemove(Messages.findOneById(queryString.msg));
if (jumpToMessage) {
msg.attachments = msg.attachments || [];

const index = msg.attachments.findIndex((a) => a.message_link === item.url);
if (index > -1) {
msg.attachments.splice(index, 1);
}

msg.attachments.push({
text: jumpToMessage.msg,
translations: jumpToMessage.translations,
author_name: jumpToMessage.alias || jumpToMessage.u.username,
author_icon: getUserAvatarURL(jumpToMessage.u.username),
message_link: item.url,
attachments: jumpToMessage.attachments || [],
ts: jumpToMessage.ts,
});
item.ignoreParse = true;
}
}
}
}
});
// if no message is present, or the message doesn't have any URL, skip
if (!msg || (!msg.urls || !msg.urls.length)) {
return msg;
}

const currentUser = Users.findOneById(msg.u._id);

msg.urls.forEach((item) => {
// if the URL is not internal, skip
if (!item.url.includes(Meteor.absoluteUrl())) {
return;
}

const urlObj = URL.parse(item.url);

// if the URL doesn't have query params (doesn't reference message) skip
if (!urlObj.query) {
return;
}

const { msg: msgId } = QueryString.parse(urlObj.query);

if (!_.isString(msgId)) {
return;
}

const jumpToMessage = recursiveRemove(Messages.findOneById(msgId));
if (!jumpToMessage) {
return;
}

// validates if user can see the message
// user has to belong to the room the message was first wrote in
const room = Rooms.findOneById(jumpToMessage.rid);
const canAccessRoomForUser = canAccessRoom(room, currentUser);
if (!canAccessRoomForUser) {
return;
}

msg.attachments = msg.attachments || [];
const index = msg.attachments.findIndex((a) => a.message_link === item.url);
if (index > -1) {
msg.attachments.splice(index, 1);
}

msg.attachments.push({
text: jumpToMessage.msg,
translations: jumpToMessage.translations,
author_name: jumpToMessage.alias || jumpToMessage.u.username,
author_icon: getUserAvatarURL(jumpToMessage.u.username),
message_link: item.url,
attachments: jumpToMessage.attachments || [],
ts: jumpToMessage.ts,
});
item.ignoreParse = true;
});

return msg;
}, callbacks.priority.LOW, 'jumpToMessage');