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/packages/rocketchat-models/server/models/Rooms.js

968 lines
16 KiB

import { Base } from './_Base';
import Messages from './Messages';
import Subscriptions from './Subscriptions';
import _ from 'underscore';
import s from 'underscore.string';
export class Rooms extends Base {
constructor(...args) {
super(...args);
this.tryEnsureIndex({ name: 1 }, { unique: 1, sparse: 1 });
this.tryEnsureIndex({ default: 1 });
this.tryEnsureIndex({ t: 1 });
this.tryEnsureIndex({ 'u._id': 1 });
}
findOneByIdOrName(_idOrName, options) {
const query = {
$or: [{
_id: _idOrName,
}, {
name: _idOrName,
}],
};
return this.findOne(query, options);
}
updateLastMessageStar(roomId, userId, starred) {
let update;
const query = { _id: roomId };
if (starred) {
update = {
$addToSet: {
'lastMessage.starred': { _id: userId },
},
};
} else {
update = {
$pull: {
'lastMessage.starred': { _id: userId },
},
};
}
return this.update(query, update);
}
setLastMessageSnippeted(roomId, message, snippetName, snippetedBy, snippeted, snippetedAt) {
const query = { _id: roomId };
const msg = `\`\`\`${ message.msg }\`\`\``;
const update = {
$set: {
'lastMessage.msg': msg,
'lastMessage.snippeted': snippeted,
'lastMessage.snippetedAt': snippetedAt || new Date,
'lastMessage.snippetedBy': snippetedBy,
'lastMessage.snippetName': snippetName,
},
};
return this.update(query, update);
}
setLastMessagePinned(roomId, pinnedBy, pinned, pinnedAt) {
const query = { _id: roomId };
const update = {
$set: {
'lastMessage.pinned': pinned,
'lastMessage.pinnedAt': pinnedAt || new Date,
'lastMessage.pinnedBy': pinnedBy,
},
};
return this.update(query, update);
}
setSentiment(roomId, sentiment) {
return this.update({ _id: roomId }, { $set: { sentiment } });
}
setDescriptionById(_id, description) {
const query = {
_id,
};
const update = {
$set: {
description,
},
};
return this.update(query, update);
}
setStreamingOptionsById(_id, streamingOptions) {
const update = {
$set: {
streamingOptions,
},
};
return this.update({ _id }, update);
}
setTokenpassById(_id, tokenpass) {
const update = {
$set: {
tokenpass,
},
};
return this.update({ _id }, update);
}
setReadOnlyById(_id, readOnly, hasPermission) {
if (!hasPermission) {
throw new Error('You must provide "hasPermission" function to be able to call this method');
}
const query = {
_id,
};
const update = {
$set: {
ro: readOnly,
muted: [],
},
};
if (readOnly) {
Subscriptions.findByRoomIdWhenUsernameExists(_id, { fields: { 'u._id': 1, 'u.username': 1 } }).forEach(function({ u: user }) {
if (hasPermission(user._id, 'post-readonly')) {
return;
}
return update.$set.muted.push(user.username);
});
} else {
update.$unset = {
muted: '',
};
}
if (update.$set.muted.length === 0) {
delete update.$set.muted;
}
return this.update(query, update);
}
setAllowReactingWhenReadOnlyById = function(_id, allowReacting) {
const query = {
_id,
};
const update = {
$set: {
reactWhenReadOnly: allowReacting,
},
};
return this.update(query, update);
}
setSystemMessagesById = function(_id, systemMessages) {
const query = {
_id,
};
const update = {
$set: {
sysMes: systemMessages,
},
};
return this.update(query, update);
}
setE2eKeyId(_id, e2eKeyId, options) {
const query = {
_id,
};
const update = {
$set: {
e2eKeyId,
},
};
return this.update(query, update, options);
}
findOneByImportId(_id, options) {
const query = { importIds: _id };
return this.findOne(query, options);
}
findOneByName(name, options) {
const query = { name };
return this.findOne(query, options);
}
findOneByNameAndNotId(name, rid) {
const query = {
_id: { $ne: rid },
name,
};
return this.findOne(query);
}
findOneByDisplayName(fname, options) {
const query = { fname };
return this.findOne(query, options);
}
findOneByNameAndType(name, type, options) {
const query = {
name,
t: type,
};
return this.findOne(query, options);
}
// FIND
findById(roomId, options) {
return this.find({ _id: roomId }, options);
}
findByIds(roomIds, options) {
return this.find({ _id: { $in: [].concat(roomIds) } }, options);
}
findByType(type, options) {
const query = { t: type };
return this.find(query, options);
}
findByTypeInIds(type, ids, options) {
const query = {
_id: {
$in: ids,
},
t: type,
};
return this.find(query, options);
}
findByTypes(types, options) {
const query = {
t: {
$in: types,
},
};
return this.find(query, options);
}
findByUserId(userId, options) {
const query = { 'u._id': userId };
return this.find(query, options);
}
findBySubscriptionUserId(userId, options) {
const data = Subscriptions.findByUserId(userId, { fields: { rid: 1 } }).fetch()
.map((item) => item.rid);
const query = {
_id: {
$in: data,
},
};
return this.find(query, options);
}
findBySubscriptionTypeAndUserId(type, userId, options) {
const data = Subscriptions.findByUserIdAndType(userId, type, { fields: { rid: 1 } }).fetch()
.map((item) => item.rid);
const query = {
t: type,
_id: {
$in: data,
},
};
return this.find(query, options);
}
findBySubscriptionUserIdUpdatedAfter(userId, _updatedAt, options) {
const ids = Subscriptions.findByUserId(userId, { fields: { rid: 1 } }).fetch()
.map((item) => item.rid);
const query = {
_id: {
$in: ids,
},
_updatedAt: {
$gt: _updatedAt,
},
};
return this.find(query, options);
}
findByNameContaining(name, options) {
const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
const query = {
$or: [
{ name: nameRegex },
{
t: 'd',
usernames: nameRegex,
},
],
};
return this.find(query, options);
}
findByNameContainingAndTypes(name, types, options) {
const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
const query = {
t: {
$in: types,
},
$or: [
{ name: nameRegex },
{
t: 'd',
usernames: nameRegex,
},
],
};
return this.find(query, options);
}
findByNameAndType(name, type, options) {
const query = {
t: type,
name,
};
// do not use cache
return this._db.find(query, options);
}
findByNameAndTypeNotDefault(name, type, options) {
const query = {
t: type,
name,
default: {
$ne: true,
},
};
// do not use cache
return this._db.find(query, options);
}
findByNameAndTypesNotInIds(name, types, ids, options) {
const query = {
_id: {
$ne: ids,
},
t: {
$in: types,
},
name,
};
// do not use cache
return this._db.find(query, options);
}
findChannelAndPrivateByNameStarting(name, options) {
const nameRegex = new RegExp(`^${ s.trim(s.escapeRegExp(name)) }`, 'i');
const query = {
t: {
$in: ['c', 'p'],
},
name: nameRegex,
};
return this.find(query, options);
}
findByDefaultAndTypes(defaultValue, types, options) {
const query = {
default: defaultValue,
t: {
$in: types,
},
};
return this.find(query, options);
}
findDirectRoomContainingUsername(username, options) {
const query = {
t: 'd',
usernames: username,
};
return this.find(query, options);
}
findDirectRoomContainingAllUsernames(usernames, options) {
const query = {
t: 'd',
usernames: { $size: usernames.length, $all: usernames },
};
return this.findOne(query, options);
}
findByTypeAndName(type, name, options) {
const query = {
name,
t: type,
};
return this.findOne(query, options);
}
findByTypeAndNameContaining(type, name, options) {
const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
const query = {
name: nameRegex,
t: type,
};
return this.find(query, options);
}
findByTypeInIdsAndNameContaining(type, ids, name, options) {
const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
const query = {
_id: {
$in: ids,
},
name: nameRegex,
t: type,
};
return this.find(query, options);
}
findByTypeAndArchivationState(type, archivationstate, options) {
const query = { t: type };
if (archivationstate) {
query.archived = true;
} else {
query.archived = { $ne: true };
}
return this.find(query, options);
}
// UPDATE
addImportIds(_id, importIds) {
importIds = [].concat(importIds);
const query = { _id };
const update = {
$addToSet: {
importIds: {
$each: importIds,
},
},
};
return this.update(query, update);
}
archiveById(_id) {
const query = { _id };
const update = {
$set: {
archived: true,
},
};
return this.update(query, update);
}
unarchiveById(_id) {
const query = { _id };
const update = {
$set: {
archived: false,
},
};
return this.update(query, update);
}
setNameById(_id, name, fname) {
const query = { _id };
const update = {
$set: {
name,
fname,
},
};
return this.update(query, update);
}
setFnameById(_id, fname) {
const query = { _id };
const update = {
$set: {
fname,
},
};
return this.update(query, update);
}
incMsgCountById(_id, inc) {
if (inc == null) { inc = 1; }
const query = { _id };
const update = {
$inc: {
msgs: inc,
},
};
return this.update(query, update);
}
incMsgCountAndSetLastMessageById(_id, inc, lastMessageTimestamp, lastMessage) {
if (inc == null) { inc = 1; }
const query = { _id };
const update = {
$set: {
lm: lastMessageTimestamp,
},
$inc: {
msgs: inc,
},
};
if (lastMessage) {
update.$set.lastMessage = lastMessage;
}
return this.update(query, update);
}
incUsersCountById(_id, inc = 1) {
const query = { _id };
const update = {
$inc: {
usersCount: inc,
},
};
return this.update(query, update);
}
incUsersCountByIds(ids, inc = 1) {
const query = {
_id: {
$in: ids,
},
};
const update = {
$inc: {
usersCount: inc,
},
};
return this.update(query, update, { multi: true });
}
setLastMessageById(_id, lastMessage) {
const query = { _id };
const update = {
$set: {
lastMessage,
},
};
return this.update(query, update);
}
resetLastMessageById(_id, messageId) {
const query = { _id };
const lastMessage = Messages.getLastVisibleMessageSentWithNoTypeByRoomId(_id, messageId);
const update = lastMessage ? {
$set: {
lastMessage,
},
} : {
$unset: {
lastMessage: 1,
},
};
return this.update(query, update);
}
replaceUsername(previousUsername, username) {
const query = { usernames: previousUsername };
const update = {
$set: {
'usernames.$': username,
},
};
return this.update(query, update, { multi: true });
}
replaceMutedUsername(previousUsername, username) {
const query = { muted: previousUsername };
const update = {
$set: {
'muted.$': username,
},
};
return this.update(query, update, { multi: true });
}
replaceUsernameOfUserByUserId(userId, username) {
const query = { 'u._id': userId };
const update = {
$set: {
'u.username': username,
},
};
return this.update(query, update, { multi: true });
}
setJoinCodeById(_id, joinCode) {
let update;
const query = { _id };
if ((joinCode != null ? joinCode.trim() : undefined) !== '') {
update = {
$set: {
joinCodeRequired: true,
joinCode,
},
};
} else {
update = {
$set: {
joinCodeRequired: false,
},
$unset: {
joinCode: 1,
},
};
}
return this.update(query, update);
}
setUserById(_id, user) {
const query = { _id };
const update = {
$set: {
u: {
_id: user._id,
username: user.username,
},
},
};
return this.update(query, update);
}
setTypeById(_id, type) {
const query = { _id };
const update = {
$set: {
t: type,
},
};
if (type === 'p') {
update.$unset = { default: '' };
}
return this.update(query, update);
}
setTopicById(_id, topic) {
const query = { _id };
const update = {
$set: {
topic,
},
};
return this.update(query, update);
}
setAnnouncementById(_id, announcement, announcementDetails) {
const query = { _id };
const update = {
$set: {
announcement,
announcementDetails,
},
};
return this.update(query, update);
}
setCustomFieldsById(_id, customFields) {
const query = { _id };
const update = {
$set: {
customFields,
},
};
return this.update(query, update);
}
muteUsernameByRoomId(_id, username) {
const query = { _id };
const update = {
$addToSet: {
muted: username,
},
};
return this.update(query, update);
}
unmuteUsernameByRoomId(_id, username) {
const query = { _id };
const update = {
$pull: {
muted: username,
},
};
return this.update(query, update);
}
saveDefaultById(_id, defaultValue) {
const query = { _id };
const update = {
$set: {
default: defaultValue === 'true',
},
};
return this.update(query, update);
}
saveRetentionEnabledById(_id, value) {
const query = { _id };
const update = {};
if (value == null) {
update.$unset = { 'retention.enabled': true };
} else {
update.$set = { 'retention.enabled': !!value };
}
return this.update(query, update);
}
saveRetentionMaxAgeById(_id, value) {
const query = { _id };
value = Number(value);
if (!value) {
value = 30;
}
const update = {
$set: {
'retention.maxAge': value,
},
};
return this.update(query, update);
}
saveRetentionExcludePinnedById(_id, value) {
const query = { _id };
const update = {
$set: {
'retention.excludePinned': value === true,
},
};
return this.update(query, update);
}
saveRetentionFilesOnlyById(_id, value) {
const query = { _id };
const update = {
$set: {
'retention.filesOnly': value === true,
},
};
return this.update(query, update);
}
saveRetentionOverrideGlobalById(_id, value) {
const query = { _id };
const update = {
$set: {
'retention.overrideGlobal': value === true,
},
};
return this.update(query, update);
}
saveEncryptedById(_id, value) {
const query = { _id };
const update = {
$set: {
encrypted: value === true,
},
};
return this.update(query, update);
}
setTopicAndTagsById(_id, topic, tags) {
const setData = {};
const unsetData = {};
if (topic != null) {
if (!_.isEmpty(s.trim(topic))) {
setData.topic = s.trim(topic);
} else {
unsetData.topic = 1;
}
}
if (tags != null) {
if (!_.isEmpty(s.trim(tags))) {
setData.tags = s.trim(tags).split(',').map((tag) => s.trim(tag));
} else {
unsetData.tags = 1;
}
}
const update = {};
if (!_.isEmpty(setData)) {
update.$set = setData;
}
if (!_.isEmpty(unsetData)) {
update.$unset = unsetData;
}
if (_.isEmpty(update)) {
return;
}
return this.update({ _id }, update);
}
// INSERT
createWithTypeNameUserAndUsernames(type, name, fname, user, usernames, extraData) {
const room = {
name,
fname,
t: type,
usernames,
msgs: 0,
usersCount: 0,
u: {
_id: user._id,
username: user.username,
},
};
_.extend(room, extraData);
room._id = this.insert(room);
return room;
}
createWithIdTypeAndName(_id, type, name, extraData) {
const room = {
_id,
ts: new Date(),
t: type,
name,
usernames: [],
msgs: 0,
usersCount: 0,
};
_.extend(room, extraData);
this.insert(room);
return room;
}
createWithFullRoomData(room) {
delete room._id;
room._id = this.insert(room);
return room;
}
// REMOVE
removeById(_id) {
const query = { _id };
return this.remove(query);
}
removeDirectRoomContainingUsername(username) {
const query = {
t: 'd',
usernames: username,
};
return this.remove(query);
}
}
export default new Rooms('room', true);