parent
e6ba3d84bc
commit
1c2e35bd93
@ -1,119 +0,0 @@ |
|||||||
RocketChat.Notifications = new class |
|
||||||
constructor: -> |
|
||||||
self = @ |
|
||||||
|
|
||||||
@debug = false |
|
||||||
|
|
||||||
@streamAll = new Meteor.Streamer 'notify-all' |
|
||||||
@streamLogged = new Meteor.Streamer 'notify-logged' |
|
||||||
@streamRoom = new Meteor.Streamer 'notify-room' |
|
||||||
@streamRoomUsers = new Meteor.Streamer 'notify-room-users' |
|
||||||
@streamUser = new Meteor.Streamer 'notify-user' |
|
||||||
|
|
||||||
|
|
||||||
@streamAll.allowWrite('none') |
|
||||||
@streamLogged.allowWrite('none') |
|
||||||
@streamRoom.allowWrite('none') |
|
||||||
@streamRoomUsers.allowWrite (eventName, args...) -> |
|
||||||
[roomId, e] = eventName.split('/') |
|
||||||
|
|
||||||
user = Meteor.users.findOne @userId, {fields: {username: 1}} |
|
||||||
if RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, @userId)? |
|
||||||
subscriptions = RocketChat.models.Subscriptions.findByRoomIdAndNotUserId(roomId, @userId).fetch() |
|
||||||
for subscription in subscriptions |
|
||||||
RocketChat.Notifications.notifyUser(subscription.u._id, e, args...) |
|
||||||
|
|
||||||
return false |
|
||||||
|
|
||||||
@streamUser.allowWrite('logged') |
|
||||||
|
|
||||||
@streamAll.allowRead('all') |
|
||||||
|
|
||||||
@streamLogged.allowRead('logged') |
|
||||||
|
|
||||||
@streamRoom.allowRead (eventName) -> |
|
||||||
if not @userId? then return false |
|
||||||
|
|
||||||
roomId = eventName.split('/')[0] |
|
||||||
|
|
||||||
user = Meteor.users.findOne @userId, {fields: {username: 1}} |
|
||||||
room = RocketChat.models.Rooms.findOneById(roomId) |
|
||||||
if room.t is 'l' and room.v._id is user._id |
|
||||||
return true |
|
||||||
|
|
||||||
return room.usernames.indexOf(user.username) > -1 |
|
||||||
|
|
||||||
@streamRoomUsers.allowRead('none'); |
|
||||||
|
|
||||||
@streamUser.allowRead (eventName) -> |
|
||||||
userId = eventName.split('/')[0] |
|
||||||
return @userId? and @userId is userId |
|
||||||
|
|
||||||
|
|
||||||
notifyAll: (eventName, args...) -> |
|
||||||
console.log 'notifyAll', arguments if @debug is true |
|
||||||
|
|
||||||
args.unshift eventName |
|
||||||
@streamAll.emit.apply @streamAll, args |
|
||||||
|
|
||||||
notifyLogged: (eventName, args...) -> |
|
||||||
console.log 'notifyLogged', arguments if @debug is true |
|
||||||
|
|
||||||
args.unshift eventName |
|
||||||
@streamLogged.emit.apply @streamLogged, args |
|
||||||
|
|
||||||
notifyRoom: (room, eventName, args...) -> |
|
||||||
console.log 'notifyRoom', arguments if @debug is true |
|
||||||
|
|
||||||
args.unshift "#{room}/#{eventName}" |
|
||||||
@streamRoom.emit.apply @streamRoom, args |
|
||||||
|
|
||||||
notifyUser: (userId, eventName, args...) -> |
|
||||||
console.log 'notifyUser', arguments if @debug is true |
|
||||||
|
|
||||||
args.unshift "#{userId}/#{eventName}" |
|
||||||
@streamUser.emit.apply @streamUser, args |
|
||||||
|
|
||||||
|
|
||||||
notifyAllInThisInstance: (eventName, args...) -> |
|
||||||
console.log 'notifyAll', arguments if @debug is true |
|
||||||
|
|
||||||
args.unshift eventName |
|
||||||
@streamAll.emitWithoutBroadcast.apply @streamAll, args |
|
||||||
|
|
||||||
notifyLoggedInThisInstance: (eventName, args...) -> |
|
||||||
console.log 'notifyLogged', arguments if @debug is true |
|
||||||
|
|
||||||
args.unshift eventName |
|
||||||
@streamLogged.emitWithoutBroadcast.apply @streamLogged, args |
|
||||||
|
|
||||||
notifyRoomInThisInstance: (room, eventName, args...) -> |
|
||||||
console.log 'notifyRoomAndBroadcast', arguments if @debug is true |
|
||||||
|
|
||||||
args.unshift "#{room}/#{eventName}" |
|
||||||
@streamRoom.emitWithoutBroadcast.apply @streamRoom, args |
|
||||||
|
|
||||||
notifyUserInThisInstance: (userId, eventName, args...) -> |
|
||||||
console.log 'notifyUserAndBroadcast', arguments if @debug is true |
|
||||||
|
|
||||||
args.unshift "#{userId}/#{eventName}" |
|
||||||
@streamUser.emitWithoutBroadcast.apply @streamUser, args |
|
||||||
|
|
||||||
|
|
||||||
## Permissions for client |
|
||||||
|
|
||||||
# Enable emit for event typing for rooms and add username to event data |
|
||||||
func = (eventName, username) -> |
|
||||||
[room, e] = eventName.split('/') |
|
||||||
|
|
||||||
if e is 'webrtc' |
|
||||||
return true |
|
||||||
|
|
||||||
if e is 'typing' |
|
||||||
user = Meteor.users.findOne(@userId, {fields: {username: 1}}) |
|
||||||
if user?.username is username |
|
||||||
return true |
|
||||||
|
|
||||||
return false |
|
||||||
|
|
||||||
RocketChat.Notifications.streamRoom.allowWrite func |
|
@ -0,0 +1,132 @@ |
|||||||
|
RocketChat.Notifications = new class { |
||||||
|
constructor() { |
||||||
|
this.debug = false; |
||||||
|
this.streamAll = new Meteor.Streamer('notify-all'); |
||||||
|
this.streamLogged = new Meteor.Streamer('notify-logged'); |
||||||
|
this.streamRoom = new Meteor.Streamer('notify-room'); |
||||||
|
this.streamRoomUsers = new Meteor.Streamer('notify-room-users'); |
||||||
|
this.streamUser = new Meteor.Streamer('notify-user'); |
||||||
|
this.streamAll.allowWrite('none'); |
||||||
|
this.streamLogged.allowWrite('none'); |
||||||
|
this.streamRoom.allowWrite('none'); |
||||||
|
this.streamRoomUsers.allowWrite(function(eventName, ...args) { |
||||||
|
const [roomId, e] = eventName.split('/'); |
||||||
|
// const user = Meteor.users.findOne(this.userId, {
|
||||||
|
// fields: {
|
||||||
|
// username: 1
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
if (RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, this.userId) != null) { |
||||||
|
const subscriptions = RocketChat.models.Subscriptions.findByRoomIdAndNotUserId(roomId, this.userId).fetch(); |
||||||
|
subscriptions.forEach(subscription => RocketChat.Notifications.notifyUser(subscription.u._id, e, ...args)); |
||||||
|
} |
||||||
|
return false; |
||||||
|
}); |
||||||
|
this.streamUser.allowWrite('logged'); |
||||||
|
this.streamAll.allowRead('all'); |
||||||
|
this.streamLogged.allowRead('logged'); |
||||||
|
this.streamRoom.allowRead(function(eventName) { |
||||||
|
if (this.userId == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
const [roomId] = eventName.split('/'); |
||||||
|
const user = Meteor.users.findOne(this.userId, { |
||||||
|
fields: { |
||||||
|
username: 1 |
||||||
|
} |
||||||
|
}); |
||||||
|
const room = RocketChat.models.Rooms.findOneById(roomId); |
||||||
|
if (room.t === 'l' && room.v._id === user._id) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return room.usernames.indexOf(user.username) > -1; |
||||||
|
}); |
||||||
|
this.streamRoomUsers.allowRead('none'); |
||||||
|
this.streamUser.allowRead(function(eventName) { |
||||||
|
const [userId] = eventName.split('/'); |
||||||
|
return (this.userId != null) && this.userId === userId; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
notifyAll(eventName, ...args) { |
||||||
|
if (this.debug === true) { |
||||||
|
console.log('notifyAll', arguments); |
||||||
|
} |
||||||
|
args.unshift(eventName); |
||||||
|
return this.streamAll.emit.apply(this.streamAll, args); |
||||||
|
} |
||||||
|
|
||||||
|
notifyLogged(eventName, ...args) { |
||||||
|
if (this.debug === true) { |
||||||
|
console.log('notifyLogged', arguments); |
||||||
|
} |
||||||
|
args.unshift(eventName); |
||||||
|
return this.streamLogged.emit.apply(this.streamLogged, args); |
||||||
|
} |
||||||
|
|
||||||
|
notifyRoom(room, eventName, ...args) { |
||||||
|
if (this.debug === true) { |
||||||
|
console.log('notifyRoom', arguments); |
||||||
|
} |
||||||
|
args.unshift(`${ room }/${ eventName }`); |
||||||
|
return this.streamRoom.emit.apply(this.streamRoom, args); |
||||||
|
} |
||||||
|
|
||||||
|
notifyUser(userId, eventName, ...args) { |
||||||
|
if (this.debug === true) { |
||||||
|
console.log('notifyUser', arguments); |
||||||
|
} |
||||||
|
args.unshift(`${ userId }/${ eventName }`); |
||||||
|
return this.streamUser.emit.apply(this.streamUser, args); |
||||||
|
} |
||||||
|
|
||||||
|
notifyAllInThisInstance(eventName, ...args) { |
||||||
|
if (this.debug === true) { |
||||||
|
console.log('notifyAll', arguments); |
||||||
|
} |
||||||
|
args.unshift(eventName); |
||||||
|
return this.streamAll.emitWithoutBroadcast.apply(this.streamAll, args); |
||||||
|
} |
||||||
|
|
||||||
|
notifyLoggedInThisInstance(eventName, ...args) { |
||||||
|
if (this.debug === true) { |
||||||
|
console.log('notifyLogged', arguments); |
||||||
|
} |
||||||
|
args.unshift(eventName); |
||||||
|
return this.streamLogged.emitWithoutBroadcast.apply(this.streamLogged, args); |
||||||
|
} |
||||||
|
|
||||||
|
notifyRoomInThisInstance(room, eventName, ...args) { |
||||||
|
if (this.debug === true) { |
||||||
|
console.log('notifyRoomAndBroadcast', arguments); |
||||||
|
} |
||||||
|
args.unshift(`${ room }/${ eventName }`); |
||||||
|
return this.streamRoom.emitWithoutBroadcast.apply(this.streamRoom, args); |
||||||
|
} |
||||||
|
|
||||||
|
notifyUserInThisInstance(userId, eventName, ...args) { |
||||||
|
if (this.debug === true) { |
||||||
|
console.log('notifyUserAndBroadcast', arguments); |
||||||
|
} |
||||||
|
args.unshift(`${ userId }/${ eventName }`); |
||||||
|
return this.streamUser.emitWithoutBroadcast.apply(this.streamUser, args); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
RocketChat.Notifications.streamRoom.allowWrite(function(eventName, username) { |
||||||
|
const [, e] = eventName.split('/'); |
||||||
|
if (e === 'webrtc') { |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (e === 'typing') { |
||||||
|
const user = Meteor.users.findOne(this.userId, { |
||||||
|
fields: { |
||||||
|
username: 1 |
||||||
|
} |
||||||
|
}); |
||||||
|
if (user != null && user.username === username) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
}); |
@ -0,0 +1,20 @@ |
|||||||
|
RocketChat.checkUsernameAvailability = function(username) { |
||||||
|
return RocketChat.settings.get('Accounts_BlockedUsernameList', function(key, value) { |
||||||
|
const usernameBlackList = _.map(value.split(','), function(username) { |
||||||
|
return username.trim(); |
||||||
|
}); |
||||||
|
if (usernameBlackList.length !== 0) { |
||||||
|
if (usernameBlackList.every(restrictedUsername => { |
||||||
|
const regex = new RegExp(`^${ s.escapeRegExp(restrictedUsername) }$`, 'i'); |
||||||
|
return !regex.test(s.trim(s.escapeRegExp(username))); |
||||||
|
})) { |
||||||
|
return !Meteor.users.findOne({ |
||||||
|
username: { |
||||||
|
$regex: new RegExp(`^${ s.trim(s.escapeRegExp(username)) }$`, 'i') |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
}); |
||||||
|
}; |
@ -1,50 +0,0 @@ |
|||||||
RocketChat.sendMessage = (user, message, room, upsert = false) -> |
|
||||||
if not user or not message or not room._id |
|
||||||
return false |
|
||||||
|
|
||||||
unless message.ts? |
|
||||||
message.ts = new Date() |
|
||||||
|
|
||||||
message.u = _.pick user, ['_id','username'] |
|
||||||
|
|
||||||
if not Match.test(message.msg, String) |
|
||||||
message.msg = '' |
|
||||||
|
|
||||||
message.rid = room._id |
|
||||||
|
|
||||||
if not room.usernames? || room.usernames.length is 0 |
|
||||||
updated_room = RocketChat.models.Rooms.findOneById(room._id) |
|
||||||
if updated_room? |
|
||||||
room = updated_room |
|
||||||
else |
|
||||||
room.usernames = [] |
|
||||||
|
|
||||||
if message.parseUrls isnt false |
|
||||||
if urls = message.msg.match /([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g |
|
||||||
message.urls = urls.map (url) -> url: url |
|
||||||
|
|
||||||
message = RocketChat.callbacks.run 'beforeSaveMessage', message |
|
||||||
|
|
||||||
# Avoid saving sandstormSessionId to the database |
|
||||||
sandstormSessionId = null |
|
||||||
if message.sandstormSessionId |
|
||||||
sandstormSessionId = message.sandstormSessionId |
|
||||||
delete message.sandstormSessionId |
|
||||||
|
|
||||||
if message._id? and upsert |
|
||||||
_id = message._id |
|
||||||
delete message._id |
|
||||||
RocketChat.models.Messages.upsert {_id: _id, 'u._id': message.u._id}, message |
|
||||||
message._id = _id |
|
||||||
else |
|
||||||
message._id = RocketChat.models.Messages.insert message |
|
||||||
|
|
||||||
### |
|
||||||
Defer other updates as their return is not interesting to the user |
|
||||||
### |
|
||||||
Meteor.defer -> |
|
||||||
# Execute all callbacks |
|
||||||
message.sandstormSessionId = sandstormSessionId |
|
||||||
RocketChat.callbacks.run 'afterSaveMessage', message, room |
|
||||||
|
|
||||||
return message |
|
@ -0,0 +1,59 @@ |
|||||||
|
RocketChat.sendMessage = function(user, message, room, upsert = false) { |
||||||
|
if (!user || !message || !room._id) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (message.ts == null) { |
||||||
|
message.ts = new Date(); |
||||||
|
} |
||||||
|
message.u = _.pick(user, ['_id', 'username', 'name']); |
||||||
|
if (!Match.test(message.msg, String)) { |
||||||
|
message.msg = ''; |
||||||
|
} |
||||||
|
message.rid = room._id; |
||||||
|
if (room.usernames || room.usernames.length === 0) { |
||||||
|
const updated_room = RocketChat.models.Rooms.findOneById(room._id); |
||||||
|
if (updated_room != null) { |
||||||
|
room = updated_room; |
||||||
|
} else { |
||||||
|
room.usernames = []; |
||||||
|
} |
||||||
|
} |
||||||
|
if (message.parseUrls !== false) { |
||||||
|
const urls = message.msg.match(/([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g); |
||||||
|
if (urls) { |
||||||
|
message.urls = urls.map(function(url) { |
||||||
|
return { |
||||||
|
url |
||||||
|
}; |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
message = RocketChat.callbacks.run('beforeSaveMessage', message); |
||||||
|
// Avoid saving sandstormSessionId to the database
|
||||||
|
let sandstormSessionId = null; |
||||||
|
if (message.sandstormSessionId) { |
||||||
|
sandstormSessionId = message.sandstormSessionId; |
||||||
|
delete message.sandstormSessionId; |
||||||
|
} |
||||||
|
if (message._id && upsert) { |
||||||
|
const _id = message._id; |
||||||
|
delete message._id; |
||||||
|
RocketChat.models.Messages.upsert({ |
||||||
|
_id, |
||||||
|
'u._id': message.u._id |
||||||
|
}, message); |
||||||
|
message._id = _id; |
||||||
|
} else { |
||||||
|
message._id = RocketChat.models.Messages.insert(message); |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
Defer other updates as their return is not interesting to the user |
||||||
|
*/ |
||||||
|
Meteor.defer(() => { |
||||||
|
// Execute all callbacks
|
||||||
|
message.sandstormSessionId = sandstormSessionId; |
||||||
|
return RocketChat.callbacks.run('afterSaveMessage', message, room); |
||||||
|
}); |
||||||
|
return message; |
||||||
|
}; |
@ -1,77 +0,0 @@ |
|||||||
RocketChat._setUsername = (userId, username) -> |
|
||||||
username = s.trim username |
|
||||||
if not userId or not username |
|
||||||
return false |
|
||||||
|
|
||||||
try |
|
||||||
nameValidation = new RegExp '^' + RocketChat.settings.get('UTF8_Names_Validation') + '$' |
|
||||||
catch |
|
||||||
nameValidation = new RegExp '^[0-9a-zA-Z-_.]+$' |
|
||||||
|
|
||||||
if not nameValidation.test username |
|
||||||
return false |
|
||||||
|
|
||||||
user = RocketChat.models.Users.findOneById userId |
|
||||||
|
|
||||||
# User already has desired username, return |
|
||||||
if user.username is username |
|
||||||
return user |
|
||||||
|
|
||||||
previousUsername = user.username |
|
||||||
|
|
||||||
# Check username availability or if the user already owns a different casing of the name |
|
||||||
if ( !previousUsername or !(username.toLowerCase() == previousUsername.toLowerCase())) |
|
||||||
unless RocketChat.checkUsernameAvailability username |
|
||||||
return false |
|
||||||
|
|
||||||
# If first time setting username, send Enrollment Email |
|
||||||
try |
|
||||||
if not previousUsername and user.emails?.length > 0 and RocketChat.settings.get 'Accounts_Enrollment_Email' |
|
||||||
Accounts.sendEnrollmentEmail(user._id) |
|
||||||
catch error |
|
||||||
|
|
||||||
user.username = username |
|
||||||
|
|
||||||
# If first time setting username, check if should set default avatar |
|
||||||
if not previousUsername and RocketChat.settings.get('Accounts_SetDefaultAvatar') is true |
|
||||||
avatarSuggestions = getAvatarSuggestionForUser user |
|
||||||
for service, avatarData of avatarSuggestions |
|
||||||
if service isnt 'gravatar' |
|
||||||
RocketChat.setUserAvatar(user, avatarData.blob, avatarData.contentType, service) |
|
||||||
gravatar = null |
|
||||||
break |
|
||||||
else |
|
||||||
gravatar = avatarData |
|
||||||
if gravatar? |
|
||||||
RocketChat.setUserAvatar(user, gravatar.blob, gravatar.contentType, 'gravatar') |
|
||||||
|
|
||||||
# Username is available; if coming from old username, update all references |
|
||||||
if previousUsername |
|
||||||
RocketChat.models.Messages.updateAllUsernamesByUserId user._id, username |
|
||||||
RocketChat.models.Messages.updateUsernameOfEditByUserId user._id, username |
|
||||||
|
|
||||||
RocketChat.models.Messages.findByMention(previousUsername).forEach (msg) -> |
|
||||||
updatedMsg = msg.msg.replace(new RegExp("@#{previousUsername}", "ig"), "@#{username}") |
|
||||||
RocketChat.models.Messages.updateUsernameAndMessageOfMentionByIdAndOldUsername msg._id, previousUsername, username, updatedMsg |
|
||||||
|
|
||||||
RocketChat.models.Rooms.replaceUsername previousUsername, username |
|
||||||
RocketChat.models.Rooms.replaceMutedUsername previousUsername, username |
|
||||||
RocketChat.models.Rooms.replaceUsernameOfUserByUserId user._id, username |
|
||||||
|
|
||||||
RocketChat.models.Subscriptions.setUserUsernameByUserId user._id, username |
|
||||||
RocketChat.models.Subscriptions.setNameForDirectRoomsWithOldName previousUsername, username |
|
||||||
|
|
||||||
rs = RocketChatFileAvatarInstance.getFileWithReadStream(encodeURIComponent("#{previousUsername}.jpg")) |
|
||||||
if rs? |
|
||||||
RocketChatFileAvatarInstance.deleteFile encodeURIComponent("#{username}.jpg") |
|
||||||
ws = RocketChatFileAvatarInstance.createWriteStream encodeURIComponent("#{username}.jpg"), rs.contentType |
|
||||||
ws.on 'end', Meteor.bindEnvironment -> |
|
||||||
RocketChatFileAvatarInstance.deleteFile encodeURIComponent("#{previousUsername}.jpg") |
|
||||||
rs.readStream.pipe(ws) |
|
||||||
|
|
||||||
# Set new username |
|
||||||
RocketChat.models.Users.setUsername user._id, username |
|
||||||
return user |
|
||||||
|
|
||||||
RocketChat.setUsername = RocketChat.RateLimiter.limitFunction RocketChat._setUsername, 1, 60000, |
|
||||||
0: () -> return not Meteor.userId() or not RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-info') # Administrators have permission to change others usernames, so don't limit those |
|
@ -0,0 +1,85 @@ |
|||||||
|
|
||||||
|
RocketChat._setUsername = function(userId, u) { |
||||||
|
const username = s.trim(u); |
||||||
|
if (!userId || !username) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
let nameValidation; |
||||||
|
try { |
||||||
|
nameValidation = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`); |
||||||
|
} catch (error) { |
||||||
|
nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$'); |
||||||
|
} |
||||||
|
if (!nameValidation.test(username)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
const user = RocketChat.models.Users.findOneById(userId); |
||||||
|
// User already has desired username, return
|
||||||
|
if (user.username === username) { |
||||||
|
return user; |
||||||
|
} |
||||||
|
const previousUsername = user.username; |
||||||
|
// Check username availability or if the user already owns a different casing of the name
|
||||||
|
if (!previousUsername || !(username.toLowerCase() === previousUsername.toLowerCase())) { |
||||||
|
if (!RocketChat.checkUsernameAvailability(username)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
//If first time setting username, send Enrollment Email
|
||||||
|
try { |
||||||
|
if (!previousUsername && user.emails && user.emails.length > 0 && RocketChat.settings.get('Accounts_Enrollment_Email')) { |
||||||
|
Accounts.sendEnrollmentEmail(user._id); |
||||||
|
} |
||||||
|
} catch (e) { |
||||||
|
console.error(e); |
||||||
|
} |
||||||
|
/* globals getAvatarSuggestionForUser */ |
||||||
|
user.username = username; |
||||||
|
if (!previousUsername && RocketChat.settings.get('Accounts_SetDefaultAvatar') === true) { |
||||||
|
const avatarSuggestions = getAvatarSuggestionForUser(user); |
||||||
|
let gravatar; |
||||||
|
Object.keys(avatarSuggestions).some(service => { |
||||||
|
const avatarData = avatarSuggestions[service]; |
||||||
|
if (service !== 'gravatar') { |
||||||
|
RocketChat.setUserAvatar(user, avatarData.blob, avatarData.contentType, service); |
||||||
|
gravatar = null; |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
gravatar = avatarData; |
||||||
|
} |
||||||
|
}); |
||||||
|
if (gravatar != null) { |
||||||
|
RocketChat.setUserAvatar(user, gravatar.blob, gravatar.contentType, 'gravatar'); |
||||||
|
} |
||||||
|
} |
||||||
|
// Username is available; if coming from old username, update all references
|
||||||
|
if (previousUsername) { |
||||||
|
RocketChat.models.Messages.updateAllUsernamesByUserId(user._id, username); |
||||||
|
RocketChat.models.Messages.updateUsernameOfEditByUserId(user._id, username); |
||||||
|
RocketChat.models.Messages.findByMention(previousUsername).forEach(function(msg) { |
||||||
|
const updatedMsg = msg.msg.replace(new RegExp(`@${ previousUsername }`, 'ig'), `@${ username }`); |
||||||
|
return RocketChat.models.Messages.updateUsernameAndMessageOfMentionByIdAndOldUsername(msg._id, previousUsername, username, updatedMsg); |
||||||
|
}); |
||||||
|
RocketChat.models.Rooms.replaceUsername(previousUsername, username); |
||||||
|
RocketChat.models.Rooms.replaceMutedUsername(previousUsername, username); |
||||||
|
RocketChat.models.Rooms.replaceUsernameOfUserByUserId(user._id, username); |
||||||
|
RocketChat.models.Subscriptions.setUserUsernameByUserId(user._id, username); |
||||||
|
RocketChat.models.Subscriptions.setNameForDirectRoomsWithOldName(previousUsername, username); |
||||||
|
const rs = RocketChatFileAvatarInstance.getFileWithReadStream(encodeURIComponent(`${ previousUsername }.jpg`)); |
||||||
|
if (rs != null) { |
||||||
|
RocketChatFileAvatarInstance.deleteFile(encodeURIComponent(`${ username }.jpg`)); |
||||||
|
const ws = RocketChatFileAvatarInstance.createWriteStream(encodeURIComponent(`${ username }.jpg`), rs.contentType); |
||||||
|
ws.on('end', Meteor.bindEnvironment(() => RocketChatFileAvatarInstance.deleteFile(encodeURIComponent(`${ previousUsername }.jpg`)))); |
||||||
|
rs.readStream.pipe(ws); |
||||||
|
} |
||||||
|
} |
||||||
|
// Set new username*
|
||||||
|
RocketChat.models.Users.setUsername(user._id, username); |
||||||
|
return user; |
||||||
|
}; |
||||||
|
|
||||||
|
RocketChat.setUsername = RocketChat.RateLimiter.limitFunction(RocketChat._setUsername, 1, 60000, { |
||||||
|
[0](userId) { |
||||||
|
return !userId || !RocketChat.authz.hasPermission(userId, 'edit-other-user-info'); |
||||||
|
} |
||||||
|
}); |
@ -1,248 +0,0 @@ |
|||||||
blockedSettings = {} |
|
||||||
process.env.SETTINGS_BLOCKED?.split(',').forEach (settingId) -> |
|
||||||
blockedSettings[settingId] = 1 |
|
||||||
|
|
||||||
hiddenSettings = {} |
|
||||||
process.env.SETTINGS_HIDDEN?.split(',').forEach (settingId) -> |
|
||||||
hiddenSettings[settingId] = 1 |
|
||||||
|
|
||||||
RocketChat.settings._sorter = {} |
|
||||||
|
|
||||||
### |
|
||||||
# Add a setting |
|
||||||
# @param {String} _id |
|
||||||
# @param {Mixed} value |
|
||||||
# @param {Object} setting |
|
||||||
### |
|
||||||
RocketChat.settings.add = (_id, value, options = {}) -> |
|
||||||
# console.log '[functions] RocketChat.settings.add -> '.green, 'arguments:', arguments |
|
||||||
|
|
||||||
if not _id or |
|
||||||
not value? and not process?.env?['OVERWRITE_SETTING_' + _id]? |
|
||||||
return false |
|
||||||
|
|
||||||
RocketChat.settings._sorter[options.group] ?= 0 |
|
||||||
|
|
||||||
options.packageValue = value |
|
||||||
options.valueSource = 'packageValue' |
|
||||||
options.hidden = false |
|
||||||
options.blocked = options.blocked || false |
|
||||||
options.sorter ?= RocketChat.settings._sorter[options.group]++ |
|
||||||
|
|
||||||
if options.enableQuery? |
|
||||||
options.enableQuery = JSON.stringify options.enableQuery |
|
||||||
|
|
||||||
if options.i18nDefaultQuery? |
|
||||||
options.i18nDefaultQuery = JSON.stringify options.i18nDefaultQuery |
|
||||||
|
|
||||||
if process?.env?[_id]? |
|
||||||
value = process.env[_id] |
|
||||||
if value.toLowerCase() is "true" |
|
||||||
value = true |
|
||||||
else if value.toLowerCase() is "false" |
|
||||||
value = false |
|
||||||
options.processEnvValue = value |
|
||||||
options.valueSource = 'processEnvValue' |
|
||||||
|
|
||||||
else if Meteor.settings?[_id]? |
|
||||||
value = Meteor.settings[_id] |
|
||||||
options.meteorSettingsValue = value |
|
||||||
options.valueSource = 'meteorSettingsValue' |
|
||||||
|
|
||||||
if not options.i18nLabel? |
|
||||||
options.i18nLabel = _id |
|
||||||
|
|
||||||
# Default description i18n key will be the setting name + "_Description" (eg: LDAP_Enable -> LDAP_Enable_Description) |
|
||||||
if not options.i18nDescription? |
|
||||||
options.i18nDescription = "#{_id}_Description" |
|
||||||
|
|
||||||
if blockedSettings[_id]? |
|
||||||
options.blocked = true |
|
||||||
|
|
||||||
if hiddenSettings[_id]? |
|
||||||
options.hidden = true |
|
||||||
|
|
||||||
if process?.env?['OVERWRITE_SETTING_' + _id]? |
|
||||||
value = process.env['OVERWRITE_SETTING_' + _id] |
|
||||||
if value.toLowerCase() is "true" |
|
||||||
value = true |
|
||||||
else if value.toLowerCase() is "false" |
|
||||||
value = false |
|
||||||
options.value = value |
|
||||||
options.processEnvValue = value |
|
||||||
options.valueSource = 'processEnvValue' |
|
||||||
|
|
||||||
updateOperations = |
|
||||||
$set: options |
|
||||||
$setOnInsert: |
|
||||||
createdAt: new Date |
|
||||||
|
|
||||||
if options.editor? |
|
||||||
updateOperations.$setOnInsert.editor = options.editor |
|
||||||
delete options.editor |
|
||||||
|
|
||||||
if not options.value? |
|
||||||
if options.force is true |
|
||||||
updateOperations.$set.value = options.packageValue |
|
||||||
else |
|
||||||
updateOperations.$setOnInsert.value = value |
|
||||||
|
|
||||||
query = _.extend { _id: _id }, updateOperations.$set |
|
||||||
|
|
||||||
if not options.section? |
|
||||||
updateOperations.$unset = { section: 1 } |
|
||||||
query.section = { $exists: false } |
|
||||||
|
|
||||||
existantSetting = RocketChat.models.Settings.db.findOne(query) |
|
||||||
|
|
||||||
if existantSetting? |
|
||||||
if not existantSetting.editor? and updateOperations.$setOnInsert.editor? |
|
||||||
updateOperations.$set.editor = updateOperations.$setOnInsert.editor |
|
||||||
delete updateOperations.$setOnInsert.editor |
|
||||||
else |
|
||||||
updateOperations.$set.ts = new Date |
|
||||||
|
|
||||||
return RocketChat.models.Settings.upsert { _id: _id }, updateOperations |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### |
|
||||||
# Add a setting group |
|
||||||
# @param {String} _id |
|
||||||
### |
|
||||||
RocketChat.settings.addGroup = (_id, options = {}, cb) -> |
|
||||||
# console.log '[functions] RocketChat.settings.addGroup -> '.green, 'arguments:', arguments |
|
||||||
|
|
||||||
if not _id |
|
||||||
return false |
|
||||||
|
|
||||||
if _.isFunction(options) |
|
||||||
cb = options |
|
||||||
options = {} |
|
||||||
|
|
||||||
if not options.i18nLabel? |
|
||||||
options.i18nLabel = _id |
|
||||||
|
|
||||||
if not options.i18nDescription? |
|
||||||
options.i18nDescription = "#{_id}_Description" |
|
||||||
|
|
||||||
options.ts = new Date |
|
||||||
options.blocked = false |
|
||||||
options.hidden = false |
|
||||||
|
|
||||||
if blockedSettings[_id]? |
|
||||||
options.blocked = true |
|
||||||
|
|
||||||
if hiddenSettings[_id]? |
|
||||||
options.hidden = true |
|
||||||
|
|
||||||
RocketChat.models.Settings.upsert { _id: _id }, |
|
||||||
$set: options |
|
||||||
$setOnInsert: |
|
||||||
type: 'group' |
|
||||||
createdAt: new Date |
|
||||||
|
|
||||||
if cb? |
|
||||||
cb.call |
|
||||||
add: (id, value, options = {}) -> |
|
||||||
options.group = _id |
|
||||||
RocketChat.settings.add id, value, options |
|
||||||
|
|
||||||
section: (section, cb) -> |
|
||||||
cb.call |
|
||||||
add: (id, value, options = {}) -> |
|
||||||
options.group = _id |
|
||||||
options.section = section |
|
||||||
RocketChat.settings.add id, value, options |
|
||||||
|
|
||||||
return |
|
||||||
|
|
||||||
|
|
||||||
### |
|
||||||
# Remove a setting by id |
|
||||||
# @param {String} _id |
|
||||||
### |
|
||||||
RocketChat.settings.removeById = (_id) -> |
|
||||||
# console.log '[functions] RocketChat.settings.add -> '.green, 'arguments:', arguments |
|
||||||
|
|
||||||
if not _id |
|
||||||
return false |
|
||||||
|
|
||||||
return RocketChat.models.Settings.removeById _id |
|
||||||
|
|
||||||
|
|
||||||
### |
|
||||||
# Update a setting by id |
|
||||||
# @param {String} _id |
|
||||||
### |
|
||||||
RocketChat.settings.updateById = (_id, value, editor) -> |
|
||||||
# console.log '[functions] RocketChat.settings.updateById -> '.green, 'arguments:', arguments |
|
||||||
|
|
||||||
if not _id or not value? |
|
||||||
return false |
|
||||||
|
|
||||||
if editor? |
|
||||||
return RocketChat.models.Settings.updateValueAndEditorById _id, value, editor |
|
||||||
|
|
||||||
return RocketChat.models.Settings.updateValueById _id, value |
|
||||||
|
|
||||||
|
|
||||||
### |
|
||||||
# Update options of a setting by id |
|
||||||
# @param {String} _id |
|
||||||
### |
|
||||||
RocketChat.settings.updateOptionsById = (_id, options) -> |
|
||||||
# console.log '[functions] RocketChat.settings.updateOptionsById -> '.green, 'arguments:', arguments |
|
||||||
|
|
||||||
if not _id or not options? |
|
||||||
return false |
|
||||||
|
|
||||||
return RocketChat.models.Settings.updateOptionsById _id, options |
|
||||||
|
|
||||||
|
|
||||||
### |
|
||||||
# Update a setting by id |
|
||||||
# @param {String} _id |
|
||||||
### |
|
||||||
RocketChat.settings.clearById = (_id) -> |
|
||||||
# console.log '[functions] RocketChat.settings.clearById -> '.green, 'arguments:', arguments |
|
||||||
|
|
||||||
if not _id? |
|
||||||
return false |
|
||||||
|
|
||||||
return RocketChat.models.Settings.updateValueById _id, undefined |
|
||||||
|
|
||||||
|
|
||||||
### |
|
||||||
# Update a setting by id |
|
||||||
### |
|
||||||
RocketChat.settings.init = -> |
|
||||||
RocketChat.settings.initialLoad = true |
|
||||||
RocketChat.models.Settings.find().observe |
|
||||||
added: (record) -> |
|
||||||
Meteor.settings[record._id] = record.value |
|
||||||
if record.env is true |
|
||||||
process.env[record._id] = record.value |
|
||||||
RocketChat.settings.load record._id, record.value, RocketChat.settings.initialLoad |
|
||||||
changed: (record) -> |
|
||||||
Meteor.settings[record._id] = record.value |
|
||||||
if record.env is true |
|
||||||
process.env[record._id] = record.value |
|
||||||
RocketChat.settings.load record._id, record.value, RocketChat.settings.initialLoad |
|
||||||
removed: (record) -> |
|
||||||
delete Meteor.settings[record._id] |
|
||||||
if record.env is true |
|
||||||
delete process.env[record._id] |
|
||||||
RocketChat.settings.load record._id, undefined, RocketChat.settings.initialLoad |
|
||||||
RocketChat.settings.initialLoad = false |
|
||||||
|
|
||||||
for fn in RocketChat.settings.afterInitialLoad |
|
||||||
fn(Meteor.settings) |
|
||||||
|
|
||||||
|
|
||||||
RocketChat.settings.afterInitialLoad = [] |
|
||||||
|
|
||||||
RocketChat.settings.onAfterInitialLoad = (fn) -> |
|
||||||
RocketChat.settings.afterInitialLoad.push(fn) |
|
||||||
if RocketChat.settings.initialLoad is false |
|
||||||
fn(Meteor.settings) |
|
@ -0,0 +1,283 @@ |
|||||||
|
const blockedSettings = {}; |
||||||
|
|
||||||
|
if (process.env.SETTINGS_BLOCKED) { |
||||||
|
process.env.SETTINGS_BLOCKED.split(',').forEach((settingId) => blockedSettings[settingId] = 1); |
||||||
|
} |
||||||
|
|
||||||
|
const hiddenSettings = {}; |
||||||
|
if (process.env.SETTINGS_HIDDEN) { |
||||||
|
process.env.SETTINGS_HIDDEN.split(',').forEach((settingId) => hiddenSettings[settingId] = 1); |
||||||
|
} |
||||||
|
|
||||||
|
RocketChat.settings._sorter = {}; |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* Add a setting |
||||||
|
* @param {String} _id |
||||||
|
* @param {Mixed} value |
||||||
|
* @param {Object} setting |
||||||
|
*/ |
||||||
|
|
||||||
|
RocketChat.settings.add = function(_id, value, options = {}) { |
||||||
|
if (options == null) { |
||||||
|
options = {}; |
||||||
|
} |
||||||
|
if (!_id || value == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (RocketChat.settings._sorter[options.group] == null) { |
||||||
|
RocketChat.settings._sorter[options.group] = 0; |
||||||
|
} |
||||||
|
options.packageValue = value; |
||||||
|
options.valueSource = 'packageValue'; |
||||||
|
options.hidden = false; |
||||||
|
options.blocked = options.blocked || false; |
||||||
|
if (options.sorter == null) { |
||||||
|
options.sorter = RocketChat.settings._sorter[options.group]++; |
||||||
|
} |
||||||
|
if (options.enableQuery != null) { |
||||||
|
options.enableQuery = JSON.stringify(options.enableQuery); |
||||||
|
} |
||||||
|
if (options.i18nDefaultQuery != null) { |
||||||
|
options.i18nDefaultQuery = JSON.stringify(options.i18nDefaultQuery); |
||||||
|
} |
||||||
|
if (typeof process !== 'undefined' && process.env && process.env._id) { |
||||||
|
let value = process.env[_id]; |
||||||
|
if (value.toLowerCase() === 'true') { |
||||||
|
value = true; |
||||||
|
} else if (value.toLowerCase() === 'false') { |
||||||
|
value = false; |
||||||
|
} |
||||||
|
options.processEnvValue = value; |
||||||
|
options.valueSource = 'processEnvValue'; |
||||||
|
} else if (Meteor.settings && Meteor.settings) { |
||||||
|
const value = Meteor.settings[_id]; |
||||||
|
options.meteorSettingsValue = value; |
||||||
|
options.valueSource = 'meteorSettingsValue'; |
||||||
|
} |
||||||
|
if (options.i18nLabel == null) { |
||||||
|
options.i18nLabel = _id; |
||||||
|
} |
||||||
|
if (options.i18nDescription == null) { |
||||||
|
options.i18nDescription = `${ _id }_Description`; |
||||||
|
} |
||||||
|
if (blockedSettings[_id] != null) { |
||||||
|
options.blocked = true; |
||||||
|
} |
||||||
|
if (hiddenSettings[_id] != null) { |
||||||
|
options.hidden = true; |
||||||
|
} |
||||||
|
if (typeof process !== 'undefined' && process.env && process.env[`OVERWRITE_SETTING_${ _id }`]) { |
||||||
|
let value = process.env[`OVERWRITE_SETTING_${ _id }`]; |
||||||
|
if (value.toLowerCase() === 'true') { |
||||||
|
value = true; |
||||||
|
} else if (value.toLowerCase() === 'false') { |
||||||
|
value = false; |
||||||
|
} |
||||||
|
options.value = value; |
||||||
|
options.processEnvValue = value; |
||||||
|
options.valueSource = 'processEnvValue'; |
||||||
|
} |
||||||
|
const updateOperations = { |
||||||
|
$set: options, |
||||||
|
$setOnInsert: { |
||||||
|
createdAt: new Date |
||||||
|
} |
||||||
|
}; |
||||||
|
if (options.editor != null) { |
||||||
|
updateOperations.$setOnInsert.editor = options.editor; |
||||||
|
delete options.editor; |
||||||
|
} |
||||||
|
if (options.value == null) { |
||||||
|
if (options.force === true) { |
||||||
|
updateOperations.$set.value = options.packageValue; |
||||||
|
} else { |
||||||
|
updateOperations.$setOnInsert.value = value; |
||||||
|
} |
||||||
|
} |
||||||
|
const query = _.extend({ |
||||||
|
_id |
||||||
|
}, updateOperations.$set); |
||||||
|
if (options.section == null) { |
||||||
|
updateOperations.$unset = { |
||||||
|
section: 1 |
||||||
|
}; |
||||||
|
query.section = { |
||||||
|
$exists: false |
||||||
|
}; |
||||||
|
} |
||||||
|
const existantSetting = RocketChat.models.Settings.db.findOne(query); |
||||||
|
if (existantSetting != null) { |
||||||
|
if (existantSetting.editor == null && updateOperations.$setOnInsert.editor != null) { |
||||||
|
updateOperations.$set.editor = updateOperations.$setOnInsert.editor; |
||||||
|
delete updateOperations.$setOnInsert.editor; |
||||||
|
} |
||||||
|
} else { |
||||||
|
updateOperations.$set.ts = new Date; |
||||||
|
} |
||||||
|
return RocketChat.models.Settings.upsert({ |
||||||
|
_id |
||||||
|
}, updateOperations); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* Add a setting group |
||||||
|
* @param {String} _id |
||||||
|
*/ |
||||||
|
|
||||||
|
RocketChat.settings.addGroup = function(_id, options = {}, cb) { |
||||||
|
if (!_id) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (_.isFunction(options)) { |
||||||
|
cb = options; |
||||||
|
options = {}; |
||||||
|
} |
||||||
|
if (options.i18nLabel == null) { |
||||||
|
options.i18nLabel = _id; |
||||||
|
} |
||||||
|
if (options.i18nDescription == null) { |
||||||
|
options.i18nDescription = `${ _id }_Description`; |
||||||
|
} |
||||||
|
options.ts = new Date; |
||||||
|
options.blocked = false; |
||||||
|
options.hidden = false; |
||||||
|
if (blockedSettings[_id] != null) { |
||||||
|
options.blocked = true; |
||||||
|
} |
||||||
|
if (hiddenSettings[_id] != null) { |
||||||
|
options.hidden = true; |
||||||
|
} |
||||||
|
RocketChat.models.Settings.upsert({ |
||||||
|
_id |
||||||
|
}, { |
||||||
|
$set: options, |
||||||
|
$setOnInsert: { |
||||||
|
type: 'group', |
||||||
|
createdAt: new Date |
||||||
|
} |
||||||
|
}); |
||||||
|
if (cb != null) { |
||||||
|
cb.call({ |
||||||
|
add(id, value, options) { |
||||||
|
if (options == null) { |
||||||
|
options = {}; |
||||||
|
} |
||||||
|
options.group = _id; |
||||||
|
return RocketChat.settings.add(id, value, options); |
||||||
|
}, |
||||||
|
section(section, cb) { |
||||||
|
return cb.call({ |
||||||
|
add(id, value, options) { |
||||||
|
if (options == null) { |
||||||
|
options = {}; |
||||||
|
} |
||||||
|
options.group = _id; |
||||||
|
options.section = section; |
||||||
|
return RocketChat.settings.add(id, value, options); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* Remove a setting by id |
||||||
|
* @param {String} _id |
||||||
|
*/ |
||||||
|
|
||||||
|
RocketChat.settings.removeById = function(_id) { |
||||||
|
if (!_id) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return RocketChat.models.Settings.removeById(_id); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* Update a setting by id |
||||||
|
* @param {String} _id |
||||||
|
*/ |
||||||
|
|
||||||
|
RocketChat.settings.updateById = function(_id, value, editor) { |
||||||
|
if (!_id || value == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (editor != null) { |
||||||
|
return RocketChat.models.Settings.updateValueAndEditorById(_id, value, editor); |
||||||
|
} |
||||||
|
return RocketChat.models.Settings.updateValueById(_id, value); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* Update options of a setting by id |
||||||
|
* @param {String} _id |
||||||
|
*/ |
||||||
|
|
||||||
|
RocketChat.settings.updateOptionsById = function(_id, options) { |
||||||
|
if (!_id || options == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return RocketChat.models.Settings.updateOptionsById(_id, options); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* Update a setting by id |
||||||
|
* @param {String} _id |
||||||
|
*/ |
||||||
|
|
||||||
|
RocketChat.settings.clearById = function(_id) { |
||||||
|
if (_id == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return RocketChat.models.Settings.updateValueById(_id, undefined); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* Update a setting by id |
||||||
|
*/ |
||||||
|
|
||||||
|
RocketChat.settings.init = function() { |
||||||
|
RocketChat.settings.initialLoad = true; |
||||||
|
RocketChat.models.Settings.find().observe({ |
||||||
|
added(record) { |
||||||
|
Meteor.settings[record._id] = record.value; |
||||||
|
if (record.env === true) { |
||||||
|
process.env[record._id] = record.value; |
||||||
|
} |
||||||
|
return RocketChat.settings.load(record._id, record.value, RocketChat.settings.initialLoad); |
||||||
|
}, |
||||||
|
changed(record) { |
||||||
|
Meteor.settings[record._id] = record.value; |
||||||
|
if (record.env === true) { |
||||||
|
process.env[record._id] = record.value; |
||||||
|
} |
||||||
|
return RocketChat.settings.load(record._id, record.value, RocketChat.settings.initialLoad); |
||||||
|
}, |
||||||
|
removed(record) { |
||||||
|
delete Meteor.settings[record._id]; |
||||||
|
if (record.env === true) { |
||||||
|
delete process.env[record._id]; |
||||||
|
} |
||||||
|
return RocketChat.settings.load(record._id, undefined, RocketChat.settings.initialLoad); |
||||||
|
} |
||||||
|
}); |
||||||
|
RocketChat.settings.initialLoad = false; |
||||||
|
RocketChat.settings.afterInitialLoad.forEach(fn => fn(Meteor.settings)); |
||||||
|
}; |
||||||
|
|
||||||
|
RocketChat.settings.afterInitialLoad = []; |
||||||
|
|
||||||
|
RocketChat.settings.onAfterInitialLoad = function(fn) { |
||||||
|
RocketChat.settings.afterInitialLoad.push(fn); |
||||||
|
if (RocketChat.settings.initialLoad === false) { |
||||||
|
return fn(Meteor.settings); |
||||||
|
} |
||||||
|
}; |
@ -1,64 +0,0 @@ |
|||||||
import moment from 'moment' |
|
||||||
|
|
||||||
Meteor.methods |
|
||||||
sendMessage: (message) -> |
|
||||||
|
|
||||||
check message, Object |
|
||||||
|
|
||||||
if not Meteor.userId() |
|
||||||
throw new Meteor.Error('error-invalid-user', "Invalid user", { method: 'sendMessage' }) |
|
||||||
|
|
||||||
if message.ts |
|
||||||
tsDiff = Math.abs(moment(message.ts).diff()) |
|
||||||
if tsDiff > 60000 |
|
||||||
throw new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', { method: 'sendMessage', message_ts: message.ts, server_ts: new Date().getTime() }) |
|
||||||
else if tsDiff > 10000 |
|
||||||
message.ts = new Date() |
|
||||||
else |
|
||||||
message.ts = new Date() |
|
||||||
|
|
||||||
if message.msg?.length > RocketChat.settings.get('Message_MaxAllowedSize') |
|
||||||
throw new Meteor.Error('error-message-size-exceeded', 'Message size exceeds Message_MaxAllowedSize', { method: 'sendMessage' }) |
|
||||||
|
|
||||||
user = RocketChat.models.Users.findOneById Meteor.userId(), fields: username: 1, name: 1 |
|
||||||
|
|
||||||
room = Meteor.call 'canAccessRoom', message.rid, user._id |
|
||||||
|
|
||||||
if not room |
|
||||||
return false |
|
||||||
|
|
||||||
subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId()); |
|
||||||
if subscription and (subscription.blocked or subscription.blocker) |
|
||||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
|
||||||
_id: Random.id() |
|
||||||
rid: room._id |
|
||||||
ts: new Date |
|
||||||
msg: TAPi18n.__('room_is_blocked', {}, user.language) |
|
||||||
} |
|
||||||
return false |
|
||||||
|
|
||||||
if user.username in (room.muted or []) |
|
||||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
|
||||||
_id: Random.id() |
|
||||||
rid: room._id |
|
||||||
ts: new Date |
|
||||||
msg: TAPi18n.__('You_have_been_muted', {}, user.language) |
|
||||||
} |
|
||||||
return false |
|
||||||
|
|
||||||
message.alias = user.name if not message.alias? and RocketChat.settings.get 'Message_SetNameToAliasEnabled' |
|
||||||
if Meteor.settings.public.sandstorm |
|
||||||
message.sandstormSessionId = this.connection.sandstormSessionId() |
|
||||||
|
|
||||||
RocketChat.metrics.messagesSent.inc() # This line needs to be moved to it's proper place. See the comments on: https://github.com/RocketChat/Rocket.Chat/pull/5736 |
|
||||||
RocketChat.sendMessage user, message, room |
|
||||||
|
|
||||||
# Limit a user, who does not have the "bot" role, to sending 5 msgs/second |
|
||||||
DDPRateLimiter.addRule |
|
||||||
type: 'method' |
|
||||||
name: 'sendMessage' |
|
||||||
userId: (userId) -> |
|
||||||
user = RocketChat.models.Users.findOneById(userId) |
|
||||||
return true if not user?.roles |
|
||||||
return 'bot' not in user.roles |
|
||||||
, 5, 1000 |
|
@ -0,0 +1,81 @@ |
|||||||
|
import moment from 'moment'; |
||||||
|
|
||||||
|
Meteor.methods({ |
||||||
|
sendMessage(message) { |
||||||
|
check(message, Object); |
||||||
|
if (!Meteor.userId()) { |
||||||
|
throw new Meteor.Error('error-invalid-user', 'Invalid user', { |
||||||
|
method: 'sendMessage' |
||||||
|
}); |
||||||
|
} |
||||||
|
if (message.ts) { |
||||||
|
const tsDiff = Math.abs(moment(message.ts).diff()); |
||||||
|
if (tsDiff > 60000) { |
||||||
|
throw new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', { |
||||||
|
method: 'sendMessage', |
||||||
|
message_ts: message.ts, |
||||||
|
server_ts: new Date().getTime() |
||||||
|
}); |
||||||
|
} else if (tsDiff > 10000) { |
||||||
|
message.ts = new Date(); |
||||||
|
} |
||||||
|
} else { |
||||||
|
message.ts = new Date(); |
||||||
|
} |
||||||
|
if (message.msg && message.msg.length > RocketChat.settings.get('Message_MaxAllowedSize')) { |
||||||
|
throw new Meteor.Error('error-message-size-exceeded', 'Message size exceeds Message_MaxAllowedSize', { |
||||||
|
method: 'sendMessage' |
||||||
|
}); |
||||||
|
} |
||||||
|
const user = RocketChat.models.Users.findOneById(Meteor.userId(), { |
||||||
|
fields: { |
||||||
|
username: 1, |
||||||
|
name: 1 |
||||||
|
} |
||||||
|
}); |
||||||
|
const room = Meteor.call('canAccessRoom', message.rid, user._id); |
||||||
|
if (!room) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId()); |
||||||
|
if (subscription && subscription.blocked || subscription.blocker) { |
||||||
|
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||||
|
_id: Random.id(), |
||||||
|
rid: room._id, |
||||||
|
ts: new Date, |
||||||
|
msg: TAPi18n.__('room_is_blocked', {}, user.language) |
||||||
|
}); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if ((room.muted||[]).includes(user.username)) { |
||||||
|
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||||
|
_id: Random.id(), |
||||||
|
rid: room._id, |
||||||
|
ts: new Date, |
||||||
|
msg: TAPi18n.__('You_have_been_muted', {}, user.language) |
||||||
|
}); |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (message.alias == null && RocketChat.settings.get('Message_SetNameToAliasEnabled')) { |
||||||
|
message.alias = user.name; |
||||||
|
} |
||||||
|
if (Meteor.settings['public'].sandstorm) { |
||||||
|
message.sandstormSessionId = this.connection.sandstormSessionId(); |
||||||
|
} |
||||||
|
RocketChat.metrics.messagesSent.inc(); // TODO This line needs to be moved to it's proper place. See the comments on: https://github.com/RocketChat/Rocket.Chat/pull/5736
|
||||||
|
return RocketChat.sendMessage(user, message, room); |
||||||
|
} |
||||||
|
}); |
||||||
|
// Limit a user, who does not have the "bot" role, to sending 5 msgs/second
|
||||||
|
DDPRateLimiter.addRule({ |
||||||
|
type: 'method', |
||||||
|
name: 'sendMessage', |
||||||
|
userId(userId) { |
||||||
|
const user = RocketChat.models.Users.findOneById(userId); |
||||||
|
if (user == null || !user.roles) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return user.roles.includes('bot'); |
||||||
|
} |
||||||
|
}, 5, 1000); |
@ -0,0 +1,580 @@ |
|||||||
|
RocketChat.models.Messages = new class extends RocketChat.models._Base { |
||||||
|
constructor() { |
||||||
|
super('message'); |
||||||
|
|
||||||
|
this.tryEnsureIndex({ 'rid': 1, 'ts': 1 }); |
||||||
|
this.tryEnsureIndex({ 'ts': 1 }); |
||||||
|
this.tryEnsureIndex({ 'u._id': 1 }); |
||||||
|
this.tryEnsureIndex({ 'editedAt': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'editedBy._id': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'rid': 1, 't': 1, 'u._id': 1 }); |
||||||
|
this.tryEnsureIndex({ 'expireAt': 1 }, { expireAfterSeconds: 0 }); |
||||||
|
this.tryEnsureIndex({ 'msg': 'text' }); |
||||||
|
this.tryEnsureIndex({ 'file._id': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'mentions.username': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'pinned': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'snippeted': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'location': '2dsphere' }); |
||||||
|
this.tryEnsureIndex({ 'slackBotId': 1, 'slackTs': 1 }, { sparse: 1 }); |
||||||
|
} |
||||||
|
|
||||||
|
// FIND
|
||||||
|
findByMention(username, options) { |
||||||
|
const query = {'mentions.username': username}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByMentionAndRoomId(username, rid, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { $ne: true }, |
||||||
|
'mentions.username': username, |
||||||
|
rid |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomId(roomId, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
|
||||||
|
rid: roomId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomIdNotContainingTypes(roomId, types, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
|
||||||
|
rid: roomId |
||||||
|
}; |
||||||
|
|
||||||
|
if (Match.test(types, [String]) && (types.length > 0)) { |
||||||
|
query.t = |
||||||
|
{$nin: types}; |
||||||
|
} |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findInvisibleByRoomId(roomId, options) { |
||||||
|
const query = { |
||||||
|
_hidden: true, |
||||||
|
rid: roomId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomIdAfterTimestamp(roomId, timestamp, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
rid: roomId, |
||||||
|
ts: { |
||||||
|
$gt: timestamp |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomIdBeforeTimestamp(roomId, timestamp, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
rid: roomId, |
||||||
|
ts: { |
||||||
|
$lt: timestamp |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomIdBeforeTimestampInclusive(roomId, timestamp, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
rid: roomId, |
||||||
|
ts: { |
||||||
|
$lte: timestamp |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomIdBetweenTimestamps(roomId, afterTimestamp, beforeTimestamp, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
rid: roomId, |
||||||
|
ts: { |
||||||
|
$gt: afterTimestamp, |
||||||
|
$lt: beforeTimestamp |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomIdBetweenTimestampsInclusive(roomId, afterTimestamp, beforeTimestamp, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
rid: roomId, |
||||||
|
ts: { |
||||||
|
$gte: afterTimestamp, |
||||||
|
$lte: beforeTimestamp |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomIdBeforeTimestampNotContainingTypes(roomId, timestamp, types, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
rid: roomId, |
||||||
|
ts: { |
||||||
|
$lt: timestamp |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
if (Match.test(types, [String]) && (types.length > 0)) { |
||||||
|
query.t = |
||||||
|
{$nin: types}; |
||||||
|
} |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleByRoomIdBetweenTimestampsNotContainingTypes(roomId, afterTimestamp, beforeTimestamp, types, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
}, |
||||||
|
rid: roomId, |
||||||
|
ts: { |
||||||
|
$gt: afterTimestamp, |
||||||
|
$lt: beforeTimestamp |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
if (Match.test(types, [String]) && (types.length > 0)) { |
||||||
|
query.t = |
||||||
|
{$nin: types}; |
||||||
|
} |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findVisibleCreatedOrEditedAfterTimestamp(timestamp, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { $ne: true }, |
||||||
|
$or: [{ |
||||||
|
ts: { |
||||||
|
$gt: timestamp |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
'editedAt': { |
||||||
|
$gt: timestamp |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findStarredByUserAtRoom(userId, roomId, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { $ne: true }, |
||||||
|
'starred._id': userId, |
||||||
|
rid: roomId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findPinnedByRoom(roomId, options) { |
||||||
|
const query = { |
||||||
|
t: { $ne: 'rm' }, |
||||||
|
_hidden: { $ne: true }, |
||||||
|
pinned: true, |
||||||
|
rid: roomId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findSnippetedByRoom(roomId, options) { |
||||||
|
const query = { |
||||||
|
_hidden: { $ne: true }, |
||||||
|
snippeted: true, |
||||||
|
rid: roomId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
getLastTimestamp(options) { |
||||||
|
if (options == null) { options = {}; } |
||||||
|
const query = { ts: { $exists: 1 } }; |
||||||
|
options.sort = { ts: -1 }; |
||||||
|
options.limit = 1; |
||||||
|
const [message] = this.find(query, options).fetch(); |
||||||
|
return message && message.ts; |
||||||
|
} |
||||||
|
|
||||||
|
findByRoomIdAndMessageIds(rid, messageIds, options) { |
||||||
|
const query = { |
||||||
|
rid, |
||||||
|
_id: { |
||||||
|
$in: messageIds |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneBySlackBotIdAndSlackTs(slackBotId, slackTs) { |
||||||
|
const query = { |
||||||
|
slackBotId, |
||||||
|
slackTs |
||||||
|
}; |
||||||
|
|
||||||
|
return this.findOne(query); |
||||||
|
} |
||||||
|
|
||||||
|
findOneBySlackTs(slackTs) { |
||||||
|
const query = {slackTs}; |
||||||
|
|
||||||
|
return this.findOne(query); |
||||||
|
} |
||||||
|
|
||||||
|
cloneAndSaveAsHistoryById(_id) { |
||||||
|
const me = RocketChat.models.Users.findOneById(Meteor.userId()); |
||||||
|
const record = this.findOneById(_id); |
||||||
|
record._hidden = true; |
||||||
|
record.parent = record._id; |
||||||
|
record.editedAt = new Date; |
||||||
|
record.editedBy = { |
||||||
|
_id: Meteor.userId(), |
||||||
|
username: me.username |
||||||
|
}; |
||||||
|
delete record._id; |
||||||
|
return this.insert(record); |
||||||
|
} |
||||||
|
|
||||||
|
// UPDATE
|
||||||
|
setHiddenById(_id, hidden) { |
||||||
|
if (hidden == null) { hidden = true; } |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
_hidden: hidden |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setAsDeletedByIdAndUser(_id, user) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
msg: '', |
||||||
|
t: 'rm', |
||||||
|
urls: [], |
||||||
|
mentions: [], |
||||||
|
attachments: [], |
||||||
|
reactions: [], |
||||||
|
editedAt: new Date(), |
||||||
|
editedBy: { |
||||||
|
_id: user._id, |
||||||
|
username: user.username |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setPinnedByIdAndUserId(_id, pinnedBy, pinned, pinnedAt) { |
||||||
|
if (pinned == null) { pinned = true; } |
||||||
|
if (pinnedAt == null) { pinnedAt = 0; } |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
pinned, |
||||||
|
pinnedAt: pinnedAt || new Date, |
||||||
|
pinnedBy |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setSnippetedByIdAndUserId(message, snippetName, snippetedBy, snippeted, snippetedAt) { |
||||||
|
if (snippeted == null) { snippeted = true; } |
||||||
|
if (snippetedAt == null) { snippetedAt = 0; } |
||||||
|
const query = {_id: message._id}; |
||||||
|
|
||||||
|
const msg = `\`\`\`${ message.msg }\`\`\``; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
msg, |
||||||
|
snippeted, |
||||||
|
snippetedAt: snippetedAt || new Date, |
||||||
|
snippetedBy, |
||||||
|
snippetName |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setUrlsById(_id, urls) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
urls |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
updateAllUsernamesByUserId(userId, username) { |
||||||
|
const query = {'u._id': userId}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
'u.username': username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
updateUsernameOfEditByUserId(userId, username) { |
||||||
|
const query = {'editedBy._id': userId}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
'editedBy.username': username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
updateUsernameAndMessageOfMentionByIdAndOldUsername(_id, oldUsername, newUsername, newMessage) { |
||||||
|
const query = { |
||||||
|
_id, |
||||||
|
'mentions.username': oldUsername |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
'mentions.$.username': newUsername, |
||||||
|
'msg': newMessage |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
updateUserStarById(_id, userId, starred) { |
||||||
|
let update; |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
if (starred) { |
||||||
|
update = { |
||||||
|
$addToSet: { |
||||||
|
starred: { _id: userId } |
||||||
|
} |
||||||
|
}; |
||||||
|
} else { |
||||||
|
update = { |
||||||
|
$pull: { |
||||||
|
starred: { _id: Meteor.userId() } |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
upgradeEtsToEditAt() { |
||||||
|
const query = {ets: { $exists: 1 }}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$rename: { |
||||||
|
'ets': 'editedAt' |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
setMessageAttachments(_id, attachments) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
attachments |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setSlackBotIdAndSlackTs(_id, slackBotId, slackTs) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
slackBotId, |
||||||
|
slackTs |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// INSERT
|
||||||
|
createWithTypeRoomIdMessageAndUser(type, roomId, message, user, extraData) { |
||||||
|
const room = RocketChat.models.Rooms.findOneById(roomId, { fields: { sysMes: 1 }}); |
||||||
|
if ((room != null ? room.sysMes : undefined) === false) { |
||||||
|
return; |
||||||
|
} |
||||||
|
const record = { |
||||||
|
t: type, |
||||||
|
rid: roomId, |
||||||
|
ts: new Date, |
||||||
|
msg: message, |
||||||
|
u: { |
||||||
|
_id: user._id, |
||||||
|
username: user.username |
||||||
|
}, |
||||||
|
groupable: false |
||||||
|
}; |
||||||
|
|
||||||
|
_.extend(record, extraData); |
||||||
|
|
||||||
|
record._id = this.insertOrUpsert(record); |
||||||
|
RocketChat.models.Rooms.incMsgCountById(room._id, 1); |
||||||
|
return record; |
||||||
|
} |
||||||
|
|
||||||
|
createUserJoinWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('uj', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createUserLeaveWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('ul', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createUserRemovedWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('ru', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createUserAddedWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('au', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createCommandWithRoomIdAndUser(command, roomId, user, extraData) { |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('command', roomId, command, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createUserMutedWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('user-muted', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createUserUnmutedWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('user-unmuted', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createNewModeratorWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('new-moderator', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createModeratorRemovedWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('moderator-removed', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createNewOwnerWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('new-owner', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createOwnerRemovedWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('owner-removed', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createSubscriptionRoleAddedWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('subscription-role-added', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
createSubscriptionRoleRemovedWithRoomIdAndUser(roomId, user, extraData) { |
||||||
|
const message = user.username; |
||||||
|
return this.createWithTypeRoomIdMessageAndUser('subscription-role-removed', roomId, message, user, extraData); |
||||||
|
} |
||||||
|
|
||||||
|
// REMOVE
|
||||||
|
removeById(_id) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
|
||||||
|
removeByRoomId(roomId) { |
||||||
|
const query = {rid: roomId}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
|
||||||
|
removeByUserId(userId) { |
||||||
|
const query = {'u._id': userId}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
|
||||||
|
getMessageByFileId(fileID) { |
||||||
|
return this.findOne({ 'file._id': fileID }); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,760 @@ |
|||||||
|
class ModelRooms extends RocketChat.models._Base { |
||||||
|
constructor() { |
||||||
|
super(...arguments); |
||||||
|
|
||||||
|
this.tryEnsureIndex({ 'name': 1 }, { unique: 1, sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'default': 1 }); |
||||||
|
this.tryEnsureIndex({ 'usernames': 1 }); |
||||||
|
this.tryEnsureIndex({ 't': 1 }); |
||||||
|
this.tryEnsureIndex({ 'u._id': 1 }); |
||||||
|
|
||||||
|
this.cache.ignoreUpdatedFields.push('msgs', 'lm'); |
||||||
|
this.cache.ensureIndex(['t', 'name'], 'unique'); |
||||||
|
this.cache.options = {fields: {usernames: 0}}; |
||||||
|
} |
||||||
|
|
||||||
|
findOneByIdOrName(_idOrName, options) { |
||||||
|
const query = { |
||||||
|
$or: [{ |
||||||
|
_id: _idOrName |
||||||
|
}, { |
||||||
|
name: _idOrName |
||||||
|
}] |
||||||
|
}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByImportId(_id, options) { |
||||||
|
const query = {importIds: _id}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByName(name, options) { |
||||||
|
const query = {name}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByNameAndType(name, type, options) { |
||||||
|
const query = { |
||||||
|
name, |
||||||
|
t: type |
||||||
|
}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByIdContainingUsername(_id, username, options) { |
||||||
|
const query = { |
||||||
|
_id, |
||||||
|
usernames: username |
||||||
|
}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByNameAndTypeNotContainingUsername(name, type, username, options) { |
||||||
|
const query = { |
||||||
|
name, |
||||||
|
t: type, |
||||||
|
usernames: { |
||||||
|
$ne: username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
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) { |
||||||
|
let data; |
||||||
|
if (this.useCache) { |
||||||
|
data = RocketChat.models.Subscriptions.findByUserId(userId).fetch(); |
||||||
|
data = data.map(function(item) { |
||||||
|
if (item._room) { |
||||||
|
return item._room; |
||||||
|
} |
||||||
|
console.log('Empty Room for Subscription', item); |
||||||
|
return {}; |
||||||
|
}); |
||||||
|
return this.arrayToCursor(this.processQueryOptionsOnResult(data, options)); |
||||||
|
} |
||||||
|
|
||||||
|
data = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch(); |
||||||
|
data = data.map(item => item.rid); |
||||||
|
|
||||||
|
const query = { |
||||||
|
_id: { |
||||||
|
$in: data |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findBySubscriptionUserIdUpdatedAfter(userId, _updatedAt, options) { |
||||||
|
if (this.useCache) { |
||||||
|
let data = RocketChat.models.Subscriptions.findByUserId(userId).fetch(); |
||||||
|
data = data.map(function(item) { |
||||||
|
if (item._room) { |
||||||
|
return item._room; |
||||||
|
} |
||||||
|
console.log('Empty Room for Subscription', item); |
||||||
|
return {}; |
||||||
|
}); |
||||||
|
data = data.filter(item => item._updatedAt > _updatedAt); |
||||||
|
return this.arrayToCursor(this.processQueryOptionsOnResult(data, options)); |
||||||
|
} |
||||||
|
|
||||||
|
let ids = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch(); |
||||||
|
ids = ids.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); |
||||||
|
} |
||||||
|
|
||||||
|
findByNameContainingTypesWithUsername(name, types, options) { |
||||||
|
const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i'); |
||||||
|
|
||||||
|
const $or = []; |
||||||
|
for (const type of Array.from(types)) { |
||||||
|
const obj = {name: nameRegex, t: type.type}; |
||||||
|
if (type.username != null) { |
||||||
|
obj.usernames = type.username; |
||||||
|
} |
||||||
|
if (type.ids != null) { |
||||||
|
obj._id = {$in: type.ids}; |
||||||
|
} |
||||||
|
$or.push(obj); |
||||||
|
} |
||||||
|
|
||||||
|
const query = {$or}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findContainingTypesWithUsername(types, options) { |
||||||
|
|
||||||
|
const $or = []; |
||||||
|
for (const type of Array.from(types)) { |
||||||
|
const obj = {t: type.type}; |
||||||
|
if (type.username != null) { |
||||||
|
obj.usernames = type.username; |
||||||
|
} |
||||||
|
if (type.ids != null) { |
||||||
|
obj._id = {$in: type.ids}; |
||||||
|
} |
||||||
|
$or.push(obj); |
||||||
|
} |
||||||
|
|
||||||
|
const query = {$or}; |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
findByNameAndTypeNotContainingUsername(name, type, username, options) { |
||||||
|
const query = { |
||||||
|
t: type, |
||||||
|
name, |
||||||
|
usernames: { |
||||||
|
$ne: username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByNameStartingAndTypes(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); |
||||||
|
} |
||||||
|
|
||||||
|
findByDefaultAndTypes(defaultValue, types, options) { |
||||||
|
const query = { |
||||||
|
default: defaultValue, |
||||||
|
t: { |
||||||
|
$in: types |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByTypeContainingUsername(type, username, options) { |
||||||
|
const query = { |
||||||
|
t: type, |
||||||
|
usernames: username |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByTypeContainingUsernames(type, username, options) { |
||||||
|
const query = { |
||||||
|
t: type, |
||||||
|
usernames: { $all: [].concat(username) } |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByTypesAndNotUserIdContainingUsername(types, userId, username, options) { |
||||||
|
const query = { |
||||||
|
t: { |
||||||
|
$in: types |
||||||
|
}, |
||||||
|
uid: { |
||||||
|
$ne: userId |
||||||
|
}, |
||||||
|
usernames: username |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByContainingUsername(username, options) { |
||||||
|
const query = {usernames: username}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByTypeAndName(type, name, options) { |
||||||
|
if (this.useCache) { |
||||||
|
return this.cache.findByIndex('t,name', [type, name], options); |
||||||
|
} |
||||||
|
|
||||||
|
const query = { |
||||||
|
name, |
||||||
|
t: type |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByTypeAndNameContainingUsername(type, name, username, options) { |
||||||
|
const query = { |
||||||
|
name, |
||||||
|
t: type, |
||||||
|
usernames: username |
||||||
|
}; |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
addUsernameById(_id, username, muted) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$addToSet: { |
||||||
|
usernames: username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
if (muted) { |
||||||
|
update.$addToSet.muted = username; |
||||||
|
} |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
addUsernamesById(_id, usernames) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$addToSet: { |
||||||
|
usernames: { |
||||||
|
$each: usernames |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
addUsernameByName(name, username) { |
||||||
|
const query = {name}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$addToSet: { |
||||||
|
usernames: username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
removeUsernameById(_id, username) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$pull: { |
||||||
|
usernames: username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
removeUsernamesById(_id, usernames) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$pull: { |
||||||
|
usernames: { |
||||||
|
$in: usernames |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
removeUsernameFromAll(username) { |
||||||
|
const query = {usernames: username}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$pull: { |
||||||
|
usernames: username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
removeUsernameByName(name, username) { |
||||||
|
const query = {name}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$pull: { |
||||||
|
usernames: username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setNameById(_id, name) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
name |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
incMsgCountAndSetLastMessageTimestampById(_id, inc, lastMessageTimestamp) { |
||||||
|
if (inc == null) { inc = 1; } |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
lm: lastMessageTimestamp |
||||||
|
}, |
||||||
|
$inc: { |
||||||
|
msgs: inc |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
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) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
announcement |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
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, user, usernames, extraData) { |
||||||
|
const room = { |
||||||
|
name, |
||||||
|
t: type, |
||||||
|
usernames, |
||||||
|
msgs: 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 |
||||||
|
}; |
||||||
|
|
||||||
|
_.extend(room, extraData); |
||||||
|
|
||||||
|
this.insert(room); |
||||||
|
return room; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// REMOVE
|
||||||
|
removeById(_id) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
|
||||||
|
removeByTypeContainingUsername(type, username) { |
||||||
|
const query = { |
||||||
|
t: type, |
||||||
|
usernames: username |
||||||
|
}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
RocketChat.models.Rooms = new ModelRooms('room', true); |
@ -0,0 +1,178 @@ |
|||||||
|
class ModelSettings extends RocketChat.models._Base { |
||||||
|
constructor() { |
||||||
|
super(...arguments); |
||||||
|
|
||||||
|
this.tryEnsureIndex({ 'blocked': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'hidden': 1 }, { sparse: 1 }); |
||||||
|
} |
||||||
|
|
||||||
|
// FIND
|
||||||
|
findById(_id) { |
||||||
|
const query = {_id}; |
||||||
|
|
||||||
|
return this.find(query); |
||||||
|
} |
||||||
|
|
||||||
|
findOneNotHiddenById(_id) { |
||||||
|
const query = { |
||||||
|
_id, |
||||||
|
hidden: { $ne: true } |
||||||
|
}; |
||||||
|
|
||||||
|
return this.findOne(query); |
||||||
|
} |
||||||
|
|
||||||
|
findByIds(_id = []) { |
||||||
|
_id = [].concat(_id); |
||||||
|
|
||||||
|
const query = { |
||||||
|
_id: { |
||||||
|
$in: _id |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query); |
||||||
|
} |
||||||
|
|
||||||
|
findByRole(role, options) { |
||||||
|
const query = {role}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findPublic(options) { |
||||||
|
const query = {public: true}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findNotHiddenPublic(ids = []) { |
||||||
|
const filter = { |
||||||
|
hidden: { $ne: true }, |
||||||
|
public: true |
||||||
|
}; |
||||||
|
|
||||||
|
if (ids.length > 0) { |
||||||
|
filter._id = |
||||||
|
{$in: ids}; |
||||||
|
} |
||||||
|
|
||||||
|
return this.find(filter, { fields: {_id: 1, value: 1} }); |
||||||
|
} |
||||||
|
|
||||||
|
findNotHiddenPublicUpdatedAfter(updatedAt) { |
||||||
|
const filter = { |
||||||
|
hidden: { $ne: true }, |
||||||
|
public: true, |
||||||
|
_updatedAt: { |
||||||
|
$gt: updatedAt |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(filter, { fields: {_id: 1, value: 1} }); |
||||||
|
} |
||||||
|
|
||||||
|
findNotHiddenPrivate() { |
||||||
|
return this.find({ |
||||||
|
hidden: { $ne: true }, |
||||||
|
public: { $ne: true } |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
findNotHidden(options) { |
||||||
|
return this.find({ hidden: { $ne: true } }, options); |
||||||
|
} |
||||||
|
|
||||||
|
findNotHiddenUpdatedAfter(updatedAt) { |
||||||
|
return this.find({ |
||||||
|
hidden: { $ne: true }, |
||||||
|
_updatedAt: { |
||||||
|
$gt: updatedAt |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
// UPDATE
|
||||||
|
updateValueById(_id, value) { |
||||||
|
const query = { |
||||||
|
blocked: { $ne: true }, |
||||||
|
value: { $ne: value }, |
||||||
|
_id |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
value |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
updateValueAndEditorById(_id, value, editor) { |
||||||
|
const query = { |
||||||
|
blocked: { $ne: true }, |
||||||
|
value: { $ne: value }, |
||||||
|
_id |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
value, |
||||||
|
editor |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
updateValueNotHiddenById(_id, value) { |
||||||
|
const query = { |
||||||
|
_id, |
||||||
|
hidden: { $ne: true }, |
||||||
|
blocked: { $ne: true } |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
value |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
updateOptionsById(_id, options) { |
||||||
|
const query = { |
||||||
|
blocked: { $ne: true }, |
||||||
|
_id |
||||||
|
}; |
||||||
|
|
||||||
|
const update = {$set: options}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
// INSERT
|
||||||
|
createWithIdAndValue(_id, value) { |
||||||
|
const record = { |
||||||
|
_id, |
||||||
|
value, |
||||||
|
_createdAt: new Date |
||||||
|
}; |
||||||
|
|
||||||
|
return this.insert(record); |
||||||
|
} |
||||||
|
|
||||||
|
// REMOVE
|
||||||
|
removeById(_id) { |
||||||
|
const query = { |
||||||
|
blocked: { $ne: true }, |
||||||
|
_id |
||||||
|
}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
RocketChat.models.Settings = new ModelSettings('settings', true); |
@ -0,0 +1,570 @@ |
|||||||
|
class ModelSubscriptions extends RocketChat.models._Base { |
||||||
|
constructor() { |
||||||
|
super(...arguments); |
||||||
|
|
||||||
|
this.tryEnsureIndex({ 'rid': 1, 'u._id': 1 }, { unique: 1 }); |
||||||
|
this.tryEnsureIndex({ 'rid': 1, 'alert': 1, 'u._id': 1 }); |
||||||
|
this.tryEnsureIndex({ 'rid': 1, 'roles': 1 }); |
||||||
|
this.tryEnsureIndex({ 'u._id': 1, 'name': 1, 't': 1 }); |
||||||
|
this.tryEnsureIndex({ 'u._id': 1, 'name': 1, 't': 1, 'code': 1 }, { unique: 1 }); |
||||||
|
this.tryEnsureIndex({ 'open': 1 }); |
||||||
|
this.tryEnsureIndex({ 'alert': 1 }); |
||||||
|
this.tryEnsureIndex({ 'unread': 1 }); |
||||||
|
this.tryEnsureIndex({ 'ts': 1 }); |
||||||
|
this.tryEnsureIndex({ 'ls': 1 }); |
||||||
|
this.tryEnsureIndex({ 'audioNotification': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'desktopNotifications': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'mobilePushNotifications': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'emailNotifications': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'autoTranslate': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'autoTranslateLanguage': 1 }, { sparse: 1 }); |
||||||
|
|
||||||
|
this.cache.ensureIndex('rid', 'array'); |
||||||
|
this.cache.ensureIndex('u._id', 'array'); |
||||||
|
this.cache.ensureIndex('name', 'array'); |
||||||
|
this.cache.ensureIndex(['rid', 'u._id'], 'unique'); |
||||||
|
this.cache.ensureIndex(['name', 'u._id'], 'unique'); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// FIND ONE
|
||||||
|
findOneByRoomIdAndUserId(roomId, userId) { |
||||||
|
if (this.useCache) { |
||||||
|
return this.cache.findByIndex('rid,u._id', [roomId, userId]).fetch(); |
||||||
|
} |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.findOne(query); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByRoomNameAndUserId(roomName, userId) { |
||||||
|
if (this.useCache) { |
||||||
|
return this.cache.findByIndex('name,u._id', [roomName, userId]).fetch(); |
||||||
|
} |
||||||
|
const query = { |
||||||
|
name: roomName, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.findOne(query); |
||||||
|
} |
||||||
|
|
||||||
|
// FIND
|
||||||
|
findByUserId(userId, options) { |
||||||
|
if (this.useCache) { |
||||||
|
return this.cache.findByIndex('u._id', userId, options); |
||||||
|
} |
||||||
|
|
||||||
|
const query = |
||||||
|
{'u._id': userId}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByUserIdUpdatedAfter(userId, updatedAt, options) { |
||||||
|
const query = { |
||||||
|
'u._id': userId, |
||||||
|
_updatedAt: { |
||||||
|
$gt: updatedAt |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
// FIND
|
||||||
|
findByRoomIdAndRoles(roomId, roles, options) { |
||||||
|
roles = [].concat(roles); |
||||||
|
const query = { |
||||||
|
'rid': roomId, |
||||||
|
'roles': { $in: roles } |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByType(types, options) { |
||||||
|
const query = { |
||||||
|
t: { |
||||||
|
$in: types |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByTypeAndUserId(type, userId, options) { |
||||||
|
const query = { |
||||||
|
t: type, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByTypeNameAndUserId(type, name, userId, options) { |
||||||
|
const query = { |
||||||
|
t: type, |
||||||
|
name, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByRoomId(roomId, options) { |
||||||
|
if (this.useCache) { |
||||||
|
return this.cache.findByIndex('rid', roomId, options); |
||||||
|
} |
||||||
|
|
||||||
|
const query = |
||||||
|
{rid: roomId}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByRoomIdAndNotUserId(roomId, userId, options) { |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': { |
||||||
|
$ne: userId |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
getLastSeen(options) { |
||||||
|
if (options == null) { options = {}; } |
||||||
|
const query = { ls: { $exists: 1 } }; |
||||||
|
options.sort = { ls: -1 }; |
||||||
|
options.limit = 1; |
||||||
|
const [subscription] = this.find(query, options).fetch(); |
||||||
|
return subscription && subscription.ls; |
||||||
|
} |
||||||
|
|
||||||
|
findByRoomIdAndUserIds(roomId, userIds) { |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': { |
||||||
|
$in: userIds |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query); |
||||||
|
} |
||||||
|
|
||||||
|
// UPDATE
|
||||||
|
archiveByRoomId(roomId) { |
||||||
|
const query = |
||||||
|
{rid: roomId}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
alert: false, |
||||||
|
open: false, |
||||||
|
archived: true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
unarchiveByRoomId(roomId) { |
||||||
|
const query = |
||||||
|
{rid: roomId}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
alert: false, |
||||||
|
open: true, |
||||||
|
archived: false |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
hideByRoomIdAndUserId(roomId, userId) { |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
alert: false, |
||||||
|
open: false |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
openByRoomIdAndUserId(roomId, userId) { |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
open: true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setAsReadByRoomIdAndUserId(roomId, userId) { |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
open: true, |
||||||
|
alert: false, |
||||||
|
unread: 0, |
||||||
|
ls: new Date |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setAsUnreadByRoomIdAndUserId(roomId, userId, firstMessageUnreadTimestamp) { |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
open: true, |
||||||
|
alert: true, |
||||||
|
ls: firstMessageUnreadTimestamp |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setFavoriteByRoomIdAndUserId(roomId, userId, favorite) { |
||||||
|
if (favorite == null) { favorite = true; } |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
f: favorite |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
updateNameAndAlertByRoomId(roomId, name) { |
||||||
|
const query = |
||||||
|
{rid: roomId}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
name, |
||||||
|
alert: true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
updateNameByRoomId(roomId, name) { |
||||||
|
const query = |
||||||
|
{rid: roomId}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
name |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
setUserUsernameByUserId(userId, username) { |
||||||
|
const query = |
||||||
|
{'u._id': userId}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
'u.username': username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
setNameForDirectRoomsWithOldName(oldName, name) { |
||||||
|
const query = { |
||||||
|
name: oldName, |
||||||
|
t: 'd' |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
name |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
incUnreadOfDirectForRoomIdExcludingUserId(roomId, userId, inc) { |
||||||
|
if (inc == null) { inc = 1; } |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
t: 'd', |
||||||
|
'u._id': { |
||||||
|
$ne: userId |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
alert: true, |
||||||
|
open: true |
||||||
|
}, |
||||||
|
$inc: { |
||||||
|
unread: inc |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
incUnreadForRoomIdExcludingUserId(roomId, userId, inc) { |
||||||
|
if (inc == null) { inc = 1; } |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': { |
||||||
|
$ne: userId |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
alert: true, |
||||||
|
open: true |
||||||
|
}, |
||||||
|
$inc: { |
||||||
|
unread: inc |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
incUnreadForRoomIdAndUserIds(roomId, userIds, inc) { |
||||||
|
if (inc == null) { inc = 1; } |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': { |
||||||
|
$in: userIds |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
alert: true, |
||||||
|
open: true |
||||||
|
}, |
||||||
|
$inc: { |
||||||
|
unread: inc |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
setAlertForRoomIdExcludingUserId(roomId, userId) { |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': { |
||||||
|
$ne: userId |
||||||
|
}, |
||||||
|
$or: [ |
||||||
|
{ alert: { $ne: true } }, |
||||||
|
{ open: { $ne: true } } |
||||||
|
] |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
alert: true, |
||||||
|
open: true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
setBlockedByRoomId(rid, blocked, blocker) { |
||||||
|
const query = { |
||||||
|
rid, |
||||||
|
'u._id': blocked |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
blocked: true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const query2 = { |
||||||
|
rid, |
||||||
|
'u._id': blocker |
||||||
|
}; |
||||||
|
|
||||||
|
const update2 = { |
||||||
|
$set: { |
||||||
|
blocker: true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update) && this.update(query2, update2); |
||||||
|
} |
||||||
|
|
||||||
|
unsetBlockedByRoomId(rid, blocked, blocker) { |
||||||
|
const query = { |
||||||
|
rid, |
||||||
|
'u._id': blocked |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$unset: { |
||||||
|
blocked: 1 |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const query2 = { |
||||||
|
rid, |
||||||
|
'u._id': blocker |
||||||
|
}; |
||||||
|
|
||||||
|
const update2 = { |
||||||
|
$unset: { |
||||||
|
blocker: 1 |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update) && this.update(query2, update2); |
||||||
|
} |
||||||
|
|
||||||
|
updateTypeByRoomId(roomId, type) { |
||||||
|
const query = |
||||||
|
{rid: roomId}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
t: type |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
addRoleById(_id, role) { |
||||||
|
const query = |
||||||
|
{_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$addToSet: { |
||||||
|
roles: role |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
removeRoleById(_id, role) { |
||||||
|
const query = |
||||||
|
{_id}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$pull: { |
||||||
|
roles: role |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setArchivedByUsername(username, archived) { |
||||||
|
const query = { |
||||||
|
t: 'd', |
||||||
|
name: username |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
archived |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
// INSERT
|
||||||
|
createWithRoomAndUser(room, user, extraData) { |
||||||
|
const subscription = { |
||||||
|
open: false, |
||||||
|
alert: false, |
||||||
|
unread: 0, |
||||||
|
ts: room.ts, |
||||||
|
rid: room._id, |
||||||
|
name: room.name, |
||||||
|
t: room.t, |
||||||
|
u: { |
||||||
|
_id: user._id, |
||||||
|
username: user.username |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
_.extend(subscription, extraData); |
||||||
|
|
||||||
|
return this.insert(subscription); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// REMOVE
|
||||||
|
removeByUserId(userId) { |
||||||
|
const query = |
||||||
|
{'u._id': userId}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
|
||||||
|
removeByRoomId(roomId) { |
||||||
|
const query = |
||||||
|
{rid: roomId}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
|
||||||
|
removeByRoomIdAndUserId(roomId, userId) { |
||||||
|
const query = { |
||||||
|
rid: roomId, |
||||||
|
'u._id': userId |
||||||
|
}; |
||||||
|
|
||||||
|
return this.remove(query); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
RocketChat.models.Subscriptions = new ModelSubscriptions('subscription', true); |
@ -0,0 +1,91 @@ |
|||||||
|
RocketChat.models.Uploads = new class extends RocketChat.models._Base { |
||||||
|
constructor() { |
||||||
|
super('uploads'); |
||||||
|
|
||||||
|
this.tryEnsureIndex({ 'rid': 1 }); |
||||||
|
this.tryEnsureIndex({ 'uploadedAt': 1 }); |
||||||
|
} |
||||||
|
|
||||||
|
findNotHiddenFilesOfRoom(roomId, limit) { |
||||||
|
const fileQuery = { |
||||||
|
rid: roomId, |
||||||
|
complete: true, |
||||||
|
uploading: false, |
||||||
|
_hidden: { |
||||||
|
$ne: true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const fileOptions = { |
||||||
|
limit, |
||||||
|
sort: { |
||||||
|
uploadedAt: -1 |
||||||
|
}, |
||||||
|
fields: { |
||||||
|
_id: 1, |
||||||
|
userId: 1, |
||||||
|
rid: 1, |
||||||
|
name: 1, |
||||||
|
description: 1, |
||||||
|
type: 1, |
||||||
|
url: 1, |
||||||
|
uploadedAt: 1 |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(fileQuery, fileOptions); |
||||||
|
} |
||||||
|
|
||||||
|
insertFileInit(roomId, userId, store, file, extra) { |
||||||
|
const fileData = { |
||||||
|
rid: roomId, |
||||||
|
userId, |
||||||
|
store, |
||||||
|
complete: false, |
||||||
|
uploading: true, |
||||||
|
progress: 0, |
||||||
|
extension: s.strRightBack(file.name, '.'), |
||||||
|
uploadedAt: new Date() |
||||||
|
}; |
||||||
|
|
||||||
|
_.extend(fileData, file, extra); |
||||||
|
|
||||||
|
if ((this.model.direct != null ? this.model.direct.insert : undefined) != null) { |
||||||
|
file = this.model.direct.insert(fileData); |
||||||
|
} else { |
||||||
|
file = this.insert(fileData); |
||||||
|
} |
||||||
|
|
||||||
|
return file; |
||||||
|
} |
||||||
|
|
||||||
|
updateFileComplete(fileId, userId, file) { |
||||||
|
let result; |
||||||
|
if (!fileId) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
const filter = { |
||||||
|
_id: fileId, |
||||||
|
userId |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
complete: true, |
||||||
|
uploading: false, |
||||||
|
progress: 1 |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
update.$set = _.extend(file, update.$set); |
||||||
|
|
||||||
|
if ((this.model.direct != null ? this.model.direct.insert : undefined) != null) { |
||||||
|
result = this.model.direct.update(filter, update); |
||||||
|
} else { |
||||||
|
result = this.update(filter, update); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,538 @@ |
|||||||
|
class ModelUsers extends RocketChat.models._Base { |
||||||
|
constructor() { |
||||||
|
super(...arguments); |
||||||
|
|
||||||
|
this.tryEnsureIndex({ 'roles': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'name': 1 }); |
||||||
|
this.tryEnsureIndex({ 'lastLogin': 1 }); |
||||||
|
this.tryEnsureIndex({ 'status': 1 }); |
||||||
|
this.tryEnsureIndex({ 'active': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'statusConnection': 1 }, { sparse: 1 }); |
||||||
|
this.tryEnsureIndex({ 'type': 1 }); |
||||||
|
|
||||||
|
this.cache.ensureIndex('username', 'unique'); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByImportId(_id, options) { |
||||||
|
return this.findOne({ importIds: _id }, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByUsername(username, options) { |
||||||
|
const query = {username}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByEmailAddress(emailAddress, options) { |
||||||
|
const query = {'emails.address': new RegExp(`^${ s.escapeRegExp(emailAddress) }$`, 'i')}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneAdmin(admin, options) { |
||||||
|
const query = {admin}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findOneByIdAndLoginToken(_id, token, options) { |
||||||
|
const query = { |
||||||
|
_id, |
||||||
|
'services.resume.loginTokens.hashedToken' : Accounts._hashLoginToken(token) |
||||||
|
}; |
||||||
|
|
||||||
|
return this.findOne(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// FIND
|
||||||
|
findById(userId) { |
||||||
|
const query = {_id: userId}; |
||||||
|
|
||||||
|
return this.find(query); |
||||||
|
} |
||||||
|
|
||||||
|
findUsersNotOffline(options) { |
||||||
|
const query = { |
||||||
|
username: { |
||||||
|
$exists: 1 |
||||||
|
}, |
||||||
|
status: { |
||||||
|
$in: ['online', 'away', 'busy'] |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
findByUsername(username, options) { |
||||||
|
const query = {username}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findUsersByUsernamesWithHighlights(usernames, options) { |
||||||
|
if (this.useCache) { |
||||||
|
const result = { |
||||||
|
fetch() { |
||||||
|
return RocketChat.models.Users.getDynamicView('highlights').data().filter(record => usernames.indexOf(record.username) > -1); |
||||||
|
}, |
||||||
|
count() { |
||||||
|
return result.fetch().length; |
||||||
|
}, |
||||||
|
forEach(fn) { |
||||||
|
return result.fetch().forEach(fn); |
||||||
|
} |
||||||
|
}; |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
const query = { |
||||||
|
username: { $in: usernames }, |
||||||
|
'settings.preferences.highlights.0': { |
||||||
|
$exists: true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findActiveByUsernameOrNameRegexWithExceptions(searchTerm, exceptions, options) { |
||||||
|
if (exceptions == null) { exceptions = []; } |
||||||
|
if (options == null) { options = {}; } |
||||||
|
if (!_.isArray(exceptions)) { |
||||||
|
exceptions = [ exceptions ]; |
||||||
|
} |
||||||
|
|
||||||
|
const termRegex = new RegExp(s.escapeRegExp(searchTerm), 'i'); |
||||||
|
const query = { |
||||||
|
$or: [{ |
||||||
|
username: termRegex |
||||||
|
}, { |
||||||
|
name: termRegex |
||||||
|
}], |
||||||
|
active: true, |
||||||
|
type: { |
||||||
|
$in: ['user', 'bot'] |
||||||
|
}, |
||||||
|
$and: [{ |
||||||
|
username: { |
||||||
|
$exists: true |
||||||
|
} |
||||||
|
}, { |
||||||
|
username: { |
||||||
|
$nin: exceptions |
||||||
|
} |
||||||
|
}] |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByActiveUsersExcept(searchTerm, exceptions, options) { |
||||||
|
if (exceptions == null) { exceptions = []; } |
||||||
|
if (options == null) { options = {}; } |
||||||
|
if (!_.isArray(exceptions)) { |
||||||
|
exceptions = [ exceptions ]; |
||||||
|
} |
||||||
|
|
||||||
|
const termRegex = new RegExp(s.escapeRegExp(searchTerm), 'i'); |
||||||
|
const query = { |
||||||
|
$and: [ |
||||||
|
{ |
||||||
|
active: true, |
||||||
|
$or: [ |
||||||
|
{ |
||||||
|
username: termRegex |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: termRegex |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
username: { $exists: true, $nin: exceptions } |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findUsersByNameOrUsername(nameOrUsername, options) { |
||||||
|
const query = { |
||||||
|
username: { |
||||||
|
$exists: 1 |
||||||
|
}, |
||||||
|
|
||||||
|
$or: [ |
||||||
|
{name: nameOrUsername}, |
||||||
|
{username: nameOrUsername} |
||||||
|
], |
||||||
|
|
||||||
|
type: { |
||||||
|
$in: ['user'] |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findByUsernameNameOrEmailAddress(usernameNameOrEmailAddress, options) { |
||||||
|
const query = { |
||||||
|
$or: [ |
||||||
|
{name: usernameNameOrEmailAddress}, |
||||||
|
{username: usernameNameOrEmailAddress}, |
||||||
|
{'emails.address': usernameNameOrEmailAddress} |
||||||
|
], |
||||||
|
type: { |
||||||
|
$in: ['user', 'bot'] |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findLDAPUsers(options) { |
||||||
|
const query = {ldap: true}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
findCrowdUsers(options) { |
||||||
|
const query = {crowd: true}; |
||||||
|
|
||||||
|
return this.find(query, options); |
||||||
|
} |
||||||
|
|
||||||
|
getLastLogin(options) { |
||||||
|
if (options == null) { options = {}; } |
||||||
|
const query = { lastLogin: { $exists: 1 } }; |
||||||
|
options.sort = { lastLogin: -1 }; |
||||||
|
options.limit = 1; |
||||||
|
const [user] = this.find(query, options).fetch(); |
||||||
|
return user && user.lastLogin; |
||||||
|
} |
||||||
|
|
||||||
|
findUsersByUsernames(usernames, options) { |
||||||
|
const query = { |
||||||
|
username: { |
||||||
|
$in: usernames |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
updateLastLoginById(_id) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
lastLogin: new Date |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setServiceId(_id, serviceName, serviceId) { |
||||||
|
const update = |
||||||
|
{$set: {}}; |
||||||
|
|
||||||
|
const serviceIdKey = `services.${ serviceName }.id`; |
||||||
|
update.$set[serviceIdKey] = serviceId; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setUsername(_id, username) { |
||||||
|
const update = |
||||||
|
{$set: {username}}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setEmail(_id, email) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
emails: [{ |
||||||
|
address: email, |
||||||
|
verified: false |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setEmailVerified(_id, email) { |
||||||
|
const query = { |
||||||
|
_id, |
||||||
|
emails: { |
||||||
|
$elemMatch: { |
||||||
|
address: email, |
||||||
|
verified: false |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
'emails.$.verified': true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
setName(_id, name) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
name |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setCustomFields(_id, fields) { |
||||||
|
const values = {}; |
||||||
|
Object.keys(fields).reduce(key => { |
||||||
|
const value = fields[key]; |
||||||
|
values[`customFields.${ key }`] = value; |
||||||
|
}); |
||||||
|
|
||||||
|
const update = {$set: values}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setAvatarOrigin(_id, origin) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
avatarOrigin: origin |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
unsetAvatarOrigin(_id) { |
||||||
|
const update = { |
||||||
|
$unset: { |
||||||
|
avatarOrigin: 1 |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setUserActive(_id, active) { |
||||||
|
if (active == null) { active = true; } |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
active |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setAllUsersActive(active) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
active |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update({}, update, { multi: true }); |
||||||
|
} |
||||||
|
|
||||||
|
unsetLoginTokens(_id) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
'services.resume.loginTokens' : [] |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
unsetRequirePasswordChange(_id) { |
||||||
|
const update = { |
||||||
|
$unset: { |
||||||
|
'requirePasswordChange' : true, |
||||||
|
'requirePasswordChangeReason' : true |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
resetPasswordAndSetRequirePasswordChange(_id, requirePasswordChange, requirePasswordChangeReason) { |
||||||
|
const update = { |
||||||
|
$unset: { |
||||||
|
'services.password': 1 |
||||||
|
}, |
||||||
|
$set: { |
||||||
|
requirePasswordChange, |
||||||
|
requirePasswordChangeReason |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setLanguage(_id, language) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
language |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setProfile(_id, profile) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
'settings.profile': profile |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setPreferences(_id, preferences) { |
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
'settings.preferences': preferences |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(_id, update); |
||||||
|
} |
||||||
|
|
||||||
|
setUtcOffset(_id, utcOffset) { |
||||||
|
const query = { |
||||||
|
_id, |
||||||
|
utcOffset: { |
||||||
|
$ne: utcOffset |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const update = { |
||||||
|
$set: { |
||||||
|
utcOffset |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return this.update(query, update); |
||||||
|
} |
||||||
|
|
||||||
|
saveUserById(_id, data) { |
||||||
|
const setData = {}; |
||||||
|
const unsetData = {}; |
||||||
|
|
||||||
|
if (data.name != null) { |
||||||
|
if (!_.isEmpty(s.trim(data.name))) { |
||||||
|
setData.name = s.trim(data.name); |
||||||
|
} else { |
||||||
|
unsetData.name = 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (data.email != null) { |
||||||
|
if (!_.isEmpty(s.trim(data.email))) { |
||||||
|
setData.emails = [{address: s.trim(data.email)}]; |
||||||
|
} else { |
||||||
|
unsetData.emails = 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (data.phone != null) { |
||||||
|
if (!_.isEmpty(s.trim(data.phone))) { |
||||||
|
setData.phone = [{phoneNumber: s.trim(data.phone)}]; |
||||||
|
} else { |
||||||
|
unsetData.phone = 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const update = {}; |
||||||
|
|
||||||
|
if (!_.isEmpty(setData)) { |
||||||
|
update.$set = setData; |
||||||
|
} |
||||||
|
|
||||||
|
if (!_.isEmpty(unsetData)) { |
||||||
|
update.$unset = unsetData; |
||||||
|
} |
||||||
|
|
||||||
|
if (_.isEmpty(update)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
return this.update({ _id }, update); |
||||||
|
} |
||||||
|
|
||||||
|
// INSERT
|
||||||
|
create(data) { |
||||||
|
const user = { |
||||||
|
createdAt: new Date, |
||||||
|
avatarOrigin: 'none' |
||||||
|
}; |
||||||
|
|
||||||
|
_.extend(user, data); |
||||||
|
|
||||||
|
return this.insert(user); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// REMOVE
|
||||||
|
removeById(_id) { |
||||||
|
return this.remove(_id); |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
Find users to send a message by email if: |
||||||
|
- he is not online |
||||||
|
- has a verified email |
||||||
|
- has not disabled email notifications |
||||||
|
- `active` is equal to true (false means they were deactivated and can't login) |
||||||
|
*/ |
||||||
|
getUsersToSendOfflineEmail(usersIds) { |
||||||
|
const query = { |
||||||
|
_id: { |
||||||
|
$in: usersIds |
||||||
|
}, |
||||||
|
active: true, |
||||||
|
status: 'offline', |
||||||
|
statusConnection: { |
||||||
|
$ne: 'online' |
||||||
|
}, |
||||||
|
'emails.verified': true |
||||||
|
}; |
||||||
|
|
||||||
|
return this.find(query, { fields: { name: 1, username: 1, emails: 1, 'settings.preferences.emailNotificationMode': 1 } }); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
RocketChat.models.Users = new ModelUsers(Meteor.users, true); |
Loading…
Reference in new issue