The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/app/message-pin/server/pinMessage.js

178 lines
5.9 KiB

import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { settings } from '../../settings/server';
import { callbacks } from '../../../lib/callbacks';
import { isTheLastMessage } from '../../lib/server';
import { getUserAvatarURL } from '../../utils/lib/getUserAvatarURL';
import { canAccessRoom, hasPermission, roomAccessAttributes } from '../../authorization/server';
import { Subscriptions, Messages, Users, Rooms } from '../../models';
const recursiveRemove = (msg, deep = 1) => {
if (!msg) {
return;
}
if (deep > settings.get('Message_QuoteChainLimit')) {
delete msg.attachments;
return msg;
}
msg.attachments = Array.isArray(msg.attachments) ? msg.attachments.map((nestedMsg) => recursiveRemove(nestedMsg, deep + 1)) : null;
return msg;
};
const shouldAdd = (attachments, attachment) =>
!attachments.some(({ message_link }) => message_link && message_link === attachment.message_link);
Meteor.methods({
pinMessage(message, pinnedAt) {
check(message._id, String);
const userId = Meteor.userId();
if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'pinMessage',
});
}
if (!settings.get('Message_AllowPinning')) {
throw new Meteor.Error('error-action-not-allowed', 'Message pinning not allowed', {
method: 'pinMessage',
action: 'Message_pinning',
});
}
let originalMessage = Messages.findOneById(message._id);
if (originalMessage == null || originalMessage._id == null) {
throw new Meteor.Error('error-invalid-message', 'Message you are pinning was not found', {
method: 'pinMessage',
action: 'Message_pinning',
});
}
const subscription = Subscriptions.findOneByRoomIdAndUserId(originalMessage.rid, Meteor.userId(), { fields: { _id: 1 } });
if (!subscription) {
// If it's a valid message but on a room that the user is not subscribed to, report that the message was not found.
throw new Meteor.Error('error-invalid-message', 'Message you are pinning was not found', {
method: 'pinMessage',
action: 'Message_pinning',
});
}
if (!hasPermission(Meteor.userId(), 'pin-message', originalMessage.rid)) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'pinMessage' });
}
const me = Users.findOneById(userId);
// If we keep history of edits, insert a new message to store history information
if (settings.get('Message_KeepHistory')) {
Messages.cloneAndSaveAsHistoryById(message._id, me);
}
const room = Rooms.findOneById(originalMessage.rid);
if (!canAccessRoom(room, { _id: Meteor.userId() })) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'pinMessage' });
}
originalMessage.pinned = true;
originalMessage.pinnedAt = pinnedAt || Date.now;
originalMessage.pinnedBy = {
_id: userId,
username: me.username,
};
originalMessage = callbacks.run('beforeSaveMessage', originalMessage);
Messages.setPinnedByIdAndUserId(originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned);
if (isTheLastMessage(room, message)) {
Rooms.setLastMessagePinned(room._id, originalMessage.pinnedBy, originalMessage.pinned);
}
const attachments = [];
if (Array.isArray(originalMessage.attachments)) {
originalMessage.attachments.forEach((attachment) => {
if (!attachment.message_link || shouldAdd(attachments, attachment)) {
attachments.push(attachment);
}
});
}
return Messages.createWithTypeRoomIdMessageAndUser('message_pinned', originalMessage.rid, '', me, {
attachments: [
{
text: originalMessage.msg,
author_name: originalMessage.u.username,
author_icon: getUserAvatarURL(originalMessage.u.username),
ts: originalMessage.ts,
attachments: recursiveRemove(attachments),
},
],
});
},
unpinMessage(message) {
check(message._id, String);
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'unpinMessage',
});
}
if (!settings.get('Message_AllowPinning')) {
throw new Meteor.Error('error-action-not-allowed', 'Message pinning not allowed', {
method: 'unpinMessage',
action: 'Message_pinning',
});
}
let originalMessage = Messages.findOneById(message._id);
if (originalMessage == null || originalMessage._id == null) {
throw new Meteor.Error('error-invalid-message', 'Message you are unpinning was not found', {
method: 'unpinMessage',
action: 'Message_pinning',
});
}
const subscription = Subscriptions.findOneByRoomIdAndUserId(originalMessage.rid, Meteor.userId(), { fields: { _id: 1 } });
if (!subscription) {
// If it's a valid message but on a room that the user is not subscribed to, report that the message was not found.
throw new Meteor.Error('error-invalid-message', 'Message you are unpinning was not found', {
method: 'unpinMessage',
action: 'Message_pinning',
});
}
if (!hasPermission(Meteor.userId(), 'pin-message', originalMessage.rid)) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'unpinMessage' });
}
const me = Users.findOneById(Meteor.userId());
// If we keep history of edits, insert a new message to store history information
if (settings.get('Message_KeepHistory')) {
Messages.cloneAndSaveAsHistoryById(originalMessage._id, me);
}
originalMessage.pinned = false;
originalMessage.pinnedBy = {
_id: Meteor.userId(),
username: me.username,
};
originalMessage = callbacks.run('beforeSaveMessage', originalMessage);
const room = Rooms.findOneById(originalMessage.rid, { fields: { ...roomAccessAttributes, lastMessage: 1 } });
if (!canAccessRoom(room, { _id: Meteor.userId() })) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'unpinMessage' });
}
if (isTheLastMessage(room, message)) {
Rooms.setLastMessagePinned(room._id, originalMessage.pinnedBy, originalMessage.pinned);
}
return Messages.setPinnedByIdAndUserId(originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned);
},
});