Slackbridge refactoring

pull/4139/head
Marcelo Schmidt 9 years ago
parent 6d3f3e51a1
commit 748eee62f7
No known key found for this signature in database
GPG Key ID: CA48C21A7B66097E
  1. 17
      packages/rocketchat-lib/package.js
  2. 25
      packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js
  3. 42
      packages/rocketchat-lib/server/functions/addUserToRoom.js
  4. 4
      packages/rocketchat-lib/server/functions/archiveRoom.js
  5. 83
      packages/rocketchat-lib/server/functions/createRoom.js
  6. 31
      packages/rocketchat-lib/server/functions/deleteMessage.js
  7. 23
      packages/rocketchat-lib/server/functions/removeUserFromRoom.js
  8. 55
      packages/rocketchat-lib/server/functions/setUserAvatar.js
  9. 4
      packages/rocketchat-lib/server/functions/unarchiveRoom.js
  10. 30
      packages/rocketchat-lib/server/functions/updateMessage.js
  11. 24
      packages/rocketchat-lib/server/methods/addUserToRoom.coffee
  12. 9
      packages/rocketchat-lib/server/methods/archiveRoom.coffee
  13. 9
      packages/rocketchat-lib/server/methods/createChannel.coffee
  14. 2
      packages/rocketchat-lib/server/methods/createPrivateGroup.coffee
  15. 25
      packages/rocketchat-lib/server/methods/deleteMessage.coffee
  16. 27
      packages/rocketchat-lib/server/methods/joinDefaultChannels.coffee
  17. 14
      packages/rocketchat-lib/server/methods/joinRoom.coffee
  18. 17
      packages/rocketchat-lib/server/methods/leaveRoom.coffee
  19. 9
      packages/rocketchat-lib/server/methods/unarchiveRoom.coffee
  20. 27
      packages/rocketchat-lib/server/methods/updateMessage.coffee
  21. 7
      packages/rocketchat-lib/server/models/Messages.coffee
  22. 6
      packages/rocketchat-lib/server/models/Subscriptions.coffee
  23. 160
      packages/rocketchat-slackbridge/slackbridge.js
  24. 65
      server/methods/createChannel.coffee
  25. 39
      server/methods/joinRoom.coffee
  26. 48
      server/methods/setAvatarFromService.coffee

@ -56,14 +56,21 @@ Package.onUse(function(api) {
api.addFiles('server/lib/RateLimiter.coffee', 'server');
// SERVER FUNCTIONS
api.addFiles('server/functions/addUserToDefaultChannels.js', 'server');
api.addFiles('server/functions/addUserToRoom.js', 'server');
api.addFiles('server/functions/archiveRoom.js', 'server');
api.addFiles('server/functions/checkUsernameAvailability.coffee', 'server');
api.addFiles('server/functions/checkEmailAvailability.js', 'server');
api.addFiles('server/functions/createPrivateGroup.js', 'server');
api.addFiles('server/functions/createRoom.js', 'server');
api.addFiles('server/functions/deleteMessage.js', 'server');
api.addFiles('server/functions/deleteUser.js', 'server');
api.addFiles('server/functions/removeUserFromRoom.js', 'server');
api.addFiles('server/functions/sendMessage.coffee', 'server');
api.addFiles('server/functions/settings.coffee', 'server');
api.addFiles('server/functions/setUserAvatar.js', 'server');
api.addFiles('server/functions/setUsername.coffee', 'server');
api.addFiles('server/functions/setEmail.js', 'server');
api.addFiles('server/functions/updateMessage.js', 'server');
api.addFiles('server/functions/Notifications.coffee', 'server');
// SERVER LIB
@ -89,12 +96,18 @@ Package.onUse(function(api) {
// SERVER METHODS
api.addFiles('server/methods/addOAuthService.coffee', 'server');
api.addFiles('server/methods/addUserToRoom.coffee', 'server');
api.addFiles('server/methods/archiveRoom.coffee', 'server');
api.addFiles('server/methods/checkRegistrationSecretURL.coffee', 'server');
api.addFiles('server/methods/createChannel.coffee', 'server');
api.addFiles('server/methods/createPrivateGroup.coffee', 'server');
api.addFiles('server/methods/deleteMessage.coffee', 'server');
api.addFiles('server/methods/deleteUserOwnAccount.js', 'server');
api.addFiles('server/methods/getRoomRoles.js', 'server');
api.addFiles('server/methods/getUserRoles.js', 'server');
api.addFiles('server/methods/joinRoom.coffee', 'server');
api.addFiles('server/methods/joinDefaultChannels.coffee', 'server');
api.addFiles('server/methods/leaveRoom.coffee', 'server');
api.addFiles('server/methods/removeOAuthService.coffee', 'server');
api.addFiles('server/methods/robotMethods.coffee', 'server');
api.addFiles('server/methods/saveSetting.coffee', 'server');
@ -107,6 +120,8 @@ Package.onUse(function(api) {
api.addFiles('server/methods/insertOrUpdateUser.coffee', 'server');
api.addFiles('server/methods/setEmail.js', 'server');
api.addFiles('server/methods/restartServer.coffee', 'server');
api.addFiles('server/methods/unarchiveRoom.coffee', 'server');
api.addFiles('server/methods/updateMessage.coffee', 'server');
api.addFiles('server/methods/filterBadWords.js', ['server']);
api.addFiles('server/methods/filterATAllTag.js', 'server');

@ -0,0 +1,25 @@
RocketChat.addUserToDefaultChannels = function(user, silenced) {
RocketChat.callbacks.run('beforeJoinDefaultChannels', user);
let defaultRooms = RocketChat.models.Rooms.findByDefaultAndTypes(true, ['c', 'p'], {fields: {usernames: 0}}).fetch();
defaultRooms.forEach((room) => {
// put user in default rooms
RocketChat.models.Rooms.addUsernameById(room._id, user.username);
if (!RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id)) {
// Add a subscription to this user
RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
ts: new Date(),
open: true,
alert: true,
unread: 1
});
// Insert user joined message
if (!silenced) {
RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(room._id, user);
}
}
});
};

@ -0,0 +1,42 @@
RocketChat.addUserToRoom = function(rid, user, inviter) {
let now = new Date();
let room = RocketChat.models.Rooms.findOneById(rid);
// Check if user is already in room
let subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
if (subscription) {
return;
}
if (room.t === 'c') {
RocketChat.callbacks.run('beforeJoinRoom', user, room);
}
RocketChat.models.Rooms.addUsernameById(rid, user.username);
RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
ts: now,
open: true,
alert: true,
unread: 1
});
if (inviter) {
RocketChat.models.Messages.createUserAddedWithRoomIdAndUser(rid, user, {
ts: now,
u: {
_id: inviter._id,
username: inviter.username
}
});
} else {
RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(rid, user, { ts: now });
}
if (room.t === 'c') {
Meteor.defer(function() {
RocketChat.callbacks.run('afterJoinRoom', user, room);
});
}
return true;
};

@ -0,0 +1,4 @@
RocketChat.archiveRoom = function(rid) {
RocketChat.models.Rooms.archiveById(rid);
RocketChat.models.Subscriptions.archiveByRoomId(rid);
};

@ -0,0 +1,83 @@
/* globals RocketChat */
RocketChat.createRoom = function(type, name, owner, members) {
name = s.trim(name);
owner = s.trim(owner);
members = [].concat(members);
if (!name) {
throw new Meteor.Error('error-invalid-name', 'Invalid name', { function: 'RocketChat.createRoom' });
}
owner = RocketChat.models.Users.findOneByUsername(owner, { fields: { username: 1 }});
if (!owner) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { function: 'RocketChat.createRoom' });
}
let nameValidation;
try {
nameValidation = new RegExp('^' + RocketChat.settings.get('UTF8_Names_Validation') + '$');
} catch (error) {
nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
}
if (!nameValidation.test(name)) {
throw new Meteor.Error('error-invalid-name', 'Invalid name', { function: 'RocketChat.createRoom' });
}
let now = new Date();
if (!_.contains(members, owner.username)) {
members.push(owner.username);
}
// avoid duplicate names
let room = RocketChat.models.Rooms.findOneByName(name);
if (room) {
if (room.archived) {
throw new Meteor.Error('error-archived-duplicate-name', 'There\'s an archived channel with name ' + name, { function: 'RocketChat.createRoom', room_name: name });
} else {
throw new Meteor.Error('error-duplicate-channel-name', 'A channel with name \'' + name + '\' exists', { function: 'RocketChat.createRoom', room_name: name });
}
}
if (type === 'c') {
RocketChat.callbacks.run('beforeCreateChannel', owner, {
t: 'c',
name: name,
ts: now,
usernames: members,
u: {
_id: owner._id,
username: owner.username
}
});
}
room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames(type, name, owner.username, members, { ts: now });
for (let username of members) {
let member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }});
if (!member) {
continue;
}
let extra = { open: true };
if (username === owner.username) {
extra.ls = now;
}
RocketChat.models.Subscriptions.createWithRoomAndUser(room, member, extra);
}
RocketChat.authz.addUserRoles(owner._id, ['owner'], room._id);
if (type === 'c') {
Meteor.defer(() => {
RocketChat.callbacks.run('afterCreateChannel', owner, room);
});
}
return {
rid: room._id
};
};

@ -0,0 +1,31 @@
/* globals FileUpload */
RocketChat.deleteMessage = function(message, user) {
let keepHistory = RocketChat.settings.get('Message_KeepHistory');
let showDeletedStatus = RocketChat.settings.get('Message_ShowDeletedStatus');
if (keepHistory) {
if (showDeletedStatus) {
RocketChat.models.Messages.cloneAndSaveAsHistoryById(message._id);
} else {
RocketChat.models.Messages.setHiddenById(message._id, true);
}
if (message.file && message.file._id) {
RocketChat.models.Uploads.update(message.file._id, { $set: { _hidden: true } });
}
} else {
if (!showDeletedStatus) {
RocketChat.models.Messages.removeById(message._id);
}
if (message.file && message.file._id) {
FileUpload.delete(message.file._id);
}
}
if (showDeletedStatus) {
RocketChat.models.Messages.setAsDeletedByIdAndUser(message._id, user);
} else {
RocketChat.Notifications.notifyRoom(message.rid, 'deleteMessage', { _id: message._id });
}
};

@ -0,0 +1,23 @@
RocketChat.removeUserFromRoom = function(rid, user) {
let room = RocketChat.models.Rooms.findOneById(rid);
if (room) {
RocketChat.callbacks.run('beforeLeaveRoom', user, room);
RocketChat.models.Rooms.removeUsernameById(rid, user.username);
if (room.usernames.indexOf(user.username) !== -1) {
let removedUser = user;
RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(rid, removedUser);
}
if (room.t === 'l') {
RocketChat.models.Messages.createCommandWithRoomIdAndUser('survey', rid, user);
}
RocketChat.models.Subscriptions.removeByRoomIdAndUserId(rid, user._id);
Meteor.defer(function() {
RocketChat.callbacks.run('afterLeaveRoom', user, room);
});
}
};

@ -0,0 +1,55 @@
RocketChat.setUserAvatar = function(user, dataURI, contentType, service) {
if (service === 'initials') {
return RocketChat.models.Users.setAvatarOrigin(user._id, service);
}
if (service === 'url') {
let result = null;
try {
result = HTTP.get(dataURI, { npmRequestOptions: {encoding: 'binary'} });
} catch (error) {
console.log(`Error while handling the setting of the avatar from a url (${dataURI}) for ${user.username}:`, error);
throw new Meteor.Error('error-avatar-url-handling', `Error while handling avatar setting from a URL (${dataURI}) for ${user.username}`, { function: 'RocketChat.setUserAvatar', url: dataURI, username: user.username });
}
if (result.statusCode !== 200) {
console.log(`Not a valid response, ${result.statusCode}, from the avatar url: ${dataURI}`);
throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${dataURI}`, { function: 'RocketChat.setUserAvatar', url: dataURI });
}
if (!/image\/.+/.test(result.headers['content-type'])) {
console.log(`Not a valid content-type from the provided url, ${result.headers['content-type']}, from the avatar url: ${dataURI}`);
throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${dataURI}`, { function: 'RocketChat.setUserAvatar', url: dataURI });
}
let ars = RocketChatFile.bufferToStream(new Buffer(result.content, 'binary'));
RocketChatFileAvatarInstance.deleteFile(encodeURIComponent(`${user.username}.jpg`));
let aws = RocketChatFileAvatarInstance.createWriteStream(encodeURIComponent(`${user.username}.jpg`), result.headers['content-type']);
aws.on('end', Meteor.bindEnvironment(function() {
Meteor.setTimeout(function() {
console.log(`Set ${user.username}'s avatar from the url: ${dataURI}`);
RocketChat.models.Users.setAvatarOrigin(user._id, service);
RocketChat.Notifications.notifyAll('updateAvatar', { username: user.username });
}, 500);
}));
ars.pipe(aws);
return;
}
let fileData = RocketChatFile.dataURIParse(dataURI);
let image = fileData.image;
contentType = fileData.contentType;
let rs = RocketChatFile.bufferToStream(new Buffer(image, 'base64'));
RocketChatFileAvatarInstance.deleteFile(encodeURIComponent(`${user.username}.jpg`));
let ws = RocketChatFileAvatarInstance.createWriteStream(encodeURIComponent(`${user.username}.jpg`), contentType);
ws.on('end', Meteor.bindEnvironment(function() {
Meteor.setTimeout(function() {
RocketChat.models.Users.setAvatarOrigin(user._id, service);
RocketChat.Notifications.notifyAll('updateAvatar', {username: user.username});
}, 500);
}));
rs.pipe(ws);
};

@ -0,0 +1,4 @@
RocketChat.unarchiveRoom = function(rid) {
RocketChat.models.Rooms.unarchiveById(rid);
RocketChat.models.Subscriptions.unarchiveByRoomId(rid);
};

@ -0,0 +1,30 @@
RocketChat.updateMessage = function(message, user) {
// If we keep history of edits, insert a new message to store history information
if (RocketChat.settings.get('Message_KeepHistory')) {
RocketChat.models.Messages.cloneAndSaveAsHistoryById(message._id);
}
message.editedAt = new Date();
message.editedBy = {
_id: user._id,
username: user.username
};
let 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((url) => { return { url: url } });
}
message = RocketChat.callbacks.run('beforeSaveMessage', message);
let tempid = message._id;
delete message._id;
RocketChat.models.Messages.update({ _id: tempid }, { $set: message });
let room = RocketChat.models.Rooms.findOneById(message.rid);
Meteor.defer(function() {
RocketChat.callbacks.run('afterSaveMessage', RocketChat.models.Messages.findOneById(tempid), room);
});
};

@ -3,7 +3,6 @@ Meteor.methods
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'addUserToRoom' }
fromId = Meteor.userId()
unless Match.test data?.rid, String
throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'addUserToRoom' }
@ -15,34 +14,15 @@ Meteor.methods
if room.usernames.indexOf(Meteor.user().username) is -1
throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'addUserToRoom' }
# if room.username isnt Meteor.user().username and room.t is 'c'
fromId = Meteor.userId()
if not RocketChat.authz.hasPermission(fromId, 'add-user-to-room', room._id)
throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'addUserToRoom' }
if room.t is 'd'
throw new Meteor.Error 'error-cant-invite-for-direct-room', 'Can\'t invite user to direct rooms', { method: 'addUserToRoom' }
# verify if user is already in room
if room.usernames.indexOf(data.username) isnt -1
return
newUser = RocketChat.models.Users.findOneByUsername data.username
RocketChat.models.Rooms.addUsernameById data.rid, data.username
now = new Date()
RocketChat.models.Subscriptions.createWithRoomAndUser room, newUser,
ts: now
open: true
alert: true
unread: 1
fromUser = RocketChat.models.Users.findOneById fromId
RocketChat.models.Messages.createUserAddedWithRoomIdAndUser data.rid, newUser,
ts: now
u:
_id: fromUser._id
username: fromUser.username
RocketChat.addUserToRoom(data.rid, newUser, Meteor.user());
return true

@ -11,11 +11,4 @@ Meteor.methods
unless RocketChat.authz.hasPermission(Meteor.userId(), 'archive-room', room._id)
throw new Meteor.Error 'error-not-authorized', 'Not authorized', { method: 'archiveRoom' }
RocketChat.models.Rooms.archiveById rid
for username in room.usernames
member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }})
if not member?
continue
RocketChat.models.Subscriptions.archiveByRoomIdAndUserId rid, member._id
RocketChat.archiveRoom(rid)

@ -0,0 +1,9 @@
Meteor.methods
createChannel: (name, members) ->
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', "Invalid user", { method: 'createChannel' }
if RocketChat.authz.hasPermission(Meteor.userId(), 'create-c') isnt true
throw new Meteor.Error 'error-not-allowed', "Not allowed", { method: 'createChannel' }
return RocketChat.createRoom('c', name, Meteor.user()?.username, members);

@ -6,4 +6,4 @@ Meteor.methods
unless RocketChat.authz.hasPermission(Meteor.userId(), 'create-p')
throw new Meteor.Error 'error-not-allowed', "Not allowed", { method: 'createPrivateGroup' }
return RocketChat.createPrivateGroup(name, Meteor.user()?.username, members);
return RocketChat.createRoom('p', name, Meteor.user()?.username, members);

@ -22,27 +22,4 @@ Meteor.methods
if currentTsDiff > blockDeleteInMinutes
throw new Meteor.Error 'error-message-deleting-blocked', 'Message deleting is blocked', { method: 'deleteMessage' }
keepHistory = RocketChat.settings.get 'Message_KeepHistory'
showDeletedStatus = RocketChat.settings.get 'Message_ShowDeletedStatus'
if keepHistory
if showDeletedStatus
RocketChat.models.Messages.cloneAndSaveAsHistoryById originalMessage._id
else
RocketChat.models.Messages.setHiddenById originalMessage._id, true
if originalMessage.file?._id?
RocketChat.models.Uploads.update originalMessage.file._id, {$set: {_hidden: true}}
else
if not showDeletedStatus
RocketChat.models.Messages.removeById originalMessage._id
if originalMessage.file?._id?
FileUpload.delete(originalMessage.file._id)
if showDeletedStatus
RocketChat.models.Messages.setAsDeletedById originalMessage._id
else
RocketChat.Notifications.notifyRoom originalMessage.rid, 'deleteMessage', {_id: originalMessage._id}
RocketChat.deleteMessage(originalMessage, Meteor.user());

@ -3,28 +3,5 @@ Meteor.methods
if not Meteor.userId()
throw new Meteor.Error('error-invalid-user', "Invalid user", { method: 'joinDefaultChannels' })
this.unblock()
user = Meteor.user()
RocketChat.callbacks.run 'beforeJoinDefaultChannels', user
defaultRooms = RocketChat.models.Rooms.findByDefaultAndTypes(true, ['c', 'p'], {fields: {usernames: 0}}).fetch()
defaultRooms.forEach (room) ->
# put user in default rooms
RocketChat.models.Rooms.addUsernameById room._id, user.username
if not RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id)?
# Add a subscription to this user
RocketChat.models.Subscriptions.createWithRoomAndUser room, user,
ts: new Date()
open: true
alert: true
unread: 1
# Insert user joined message
if not silenced
RocketChat.models.Messages.createUserJoinWithRoomIdAndUser room._id, user
this.unblock();
RocketChat.addUserToDefaultChannels(Meteor.user(), silenced);

@ -0,0 +1,14 @@
Meteor.methods
joinRoom: (rid) ->
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'joinRoom' }
room = RocketChat.models.Rooms.findOneById rid
if not room?
throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'joinRoom' }
if room.t isnt 'c' or RocketChat.authz.hasPermission(Meteor.userId(), 'view-c-room') isnt true
throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'joinRoom' }
RocketChat.addUserToRoom(rid, Meteor.user())

@ -15,19 +15,4 @@ Meteor.methods
if numOwners is 1
throw new Meteor.Error 'error-you-are-last-owner', 'You are the last owner. Please set new owner before leaving the room.', { method: 'leaveRoom' }
RocketChat.callbacks.run 'beforeLeaveRoom', user, room
RocketChat.models.Rooms.removeUsernameById rid, user.username
if room.usernames.indexOf(user.username) isnt -1
removedUser = user
RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser rid, removedUser
if room.t is 'l'
RocketChat.models.Messages.createCommandWithRoomIdAndUser 'survey', rid, user
RocketChat.models.Subscriptions.removeByRoomIdAndUserId rid, Meteor.userId()
Meteor.defer ->
RocketChat.callbacks.run 'afterLeaveRoom', user, room
RocketChat.removeUserFromRoom(rid, Meteor.user());

@ -11,11 +11,4 @@ Meteor.methods
unless RocketChat.authz.hasPermission(Meteor.userId(), 'unarchive-room', room._id)
throw new Meteor.Error 'error-not-authorized', 'Not authorized', { method: 'unarchiveRoom' }
RocketChat.models.Rooms.unarchiveById rid
for username in room.usernames
member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }})
if not member?
continue
RocketChat.models.Subscriptions.unarchiveByRoomIdAndUserId rid, member._id
RocketChat.unarchiveRoom(rid);

@ -24,29 +24,4 @@ Meteor.methods
if currentTsDiff > blockEditInMinutes
throw new Meteor.Error 'error-message-editing-blocked', 'Message editing is blocked', { method: 'updateMessage' }
# If we keep history of edits, insert a new message to store history information
if RocketChat.settings.get 'Message_KeepHistory'
RocketChat.models.Messages.cloneAndSaveAsHistoryById originalMessage._id
message.editedAt = new Date()
message.editedBy =
_id: Meteor.userId()
username: me.username
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
tempid = message._id
delete message._id
RocketChat.models.Messages.update
_id: tempid
,
$set: message
room = RocketChat.models.Rooms.findOneById message.rid
Meteor.defer ->
RocketChat.callbacks.run 'afterSaveMessage', RocketChat.models.Messages.findOneById(tempid), room
RocketChat.updateMessage(message, Meteor.user());

@ -152,8 +152,7 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base
return @update query, update
setAsDeletedById: (_id) ->
me = RocketChat.models.Users.findOneById Meteor.userId()
setAsDeletedByIdAndUser: (_id, user) ->
query =
_id: _id
@ -166,8 +165,8 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base
attachments: []
editedAt: new Date()
editedBy:
_id: Meteor.userId()
username: me.username
_id: user._id
username: user.username
return @update query, update

@ -87,10 +87,9 @@ RocketChat.models.Subscriptions = new class extends RocketChat.models._Base
return @find query
# UPDATE
archiveByRoomIdAndUserId: (roomId, userId) ->
archiveByRoomId: (roomId) ->
query =
rid: roomId
'u._id': userId
update =
$set:
@ -100,10 +99,9 @@ RocketChat.models.Subscriptions = new class extends RocketChat.models._Base
return @update query, update
unarchiveByRoomIdAndUserId: (roomId, userId) ->
unarchiveByRoomId: (roomId) ->
query =
rid: roomId
'u._id': userId
update =
$set:

@ -124,13 +124,8 @@ class SlackBridge {
}
try {
if (isGroup) {
let channel = RocketChat.createPrivateGroup(channelData, users);
channelData.rocketId = channel._id;
} else {
let channel = Meteor.call('createChannel', channelData.name, users);
channelData.rocketId = channel._id;
}
let channel = RocketChat.createRoom(isGroup ? 'p' : 'c', channelData.name, creator, users);
channelData.rocketId = channel._id;
} catch (e) {
if (!hasRetried) {
// If first time trying to create channel fails, could be because of multiple messages received at the same time. Try again once after 1s.
@ -178,30 +173,37 @@ class SlackBridge {
userData.name = existingUser.username;
} else {
userData.rocketId = Accounts.createUser({ email: userData.profile.email, password: Date.now() + userData.name + userData.profile.email.toUpperCase() });
Meteor.runAsUser(userData.rocketId, () => {
Meteor.call('setUsername', userData.name);
Meteor.call('joinDefaultChannels', true);
let url = null;
if (userData.profile.image_original) {
url = userData.profile.image_original;
} else if (userData.profile.image_512) {
url = userData.profile.image_512;
}
Meteor.call('setAvatarFromService', url, null, 'url');
// Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600
if (userData.tz_offset) {
Meteor.call('userSetUtcOffset', userData.tz_offset / 3600);
}
if (userData.profile.real_name) {
RocketChat.models.Users.setName(userData.rocketId, userData.profile.real_name);
let userUpdate = {
$set: {
username: userData.name,
utcOffset: userData.tz_offset / 3600 // Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600
}
});
// Deleted users are 'inactive' users in Rocket.Chat
};
if (userData.profile.real_name) {
userUpdate['name'] = userData.profile.real_name;
}
if (userData.deleted) {
RocketChat.models.Users.setUserActive(userData.rocketId, false);
RocketChat.models.Users.unsetLoginTokens(userData.rocketId);
userUpdate['active'] = false;
userUpdate['services.resume.loginTokens'] = [];
}
RocketChat.models.Users.update({ _id: userData.rocketId }, { $set: userUpdate });
let user = RocketChat.models.Users.findOneById(userData.rocketId);
let url = null;
if (userData.profile.image_original) {
url = userData.profile.image_original;
} else if (userData.profile.image_512) {
url = userData.profile.image_512;
}
RocketChat.setUserAvatar(user, url);
RocketChat.addUserToDefaultChannels(user);
}
RocketChat.models.Users.update({ _id: userData.rocketId }, { $addToSet: { importIds: userData.id } });
if (!this.userTags[userId]) {
this.userTags[userId] = { slack: `<@${userId}>`, rocket: `@${userData.name}` };
@ -306,45 +308,48 @@ class SlackBridge {
this.editMessage(room, user, message);
return;
case 'message_deleted':
msgObj = RocketChat.models.Messages.findOneById(`${message.channel}S${message.deleted_ts}`);
if (msgObj) {
Meteor.runAsUser(user._id, () => {
Meteor.call('deleteMessage', msgObj);
});
if (message.previous_message) {
let _id = `slack-${message.channel}-${message.previous_message.ts.replace(/\./g, '-')}`;
msgObj = RocketChat.models.Messages.findOneById(_id);
if (msgObj) {
RocketChat.deleteMessage(msgObj, user);
}
}
return;
case 'channel_join':
return this.joinRoom(room, user);
RocketChat.addUserToRoom(room._id, user);
return;
case 'group_join':
if (message.inviter) {
let inviter = message.inviter ? this.findUser(message.inviter) || this.addUser(message.inviter) : null;
if (inviter) {
return this.joinPrivateGroup(inviter, room, user);
}
RocketChat.addUserToRoom(room._id, user, inviter);
return;
}
break;
case 'channel_leave':
case 'group_leave':
return this.leaveRoom(room, user);
RocketChat.removeUserFromRoom(room._id, user);
return;
case 'channel_topic':
case 'group_topic':
this.setRoomTopic(room, user, message.topic);
RocketChat.saveRoomTopic(room._id, message.topic, user);
return;
case 'channel_purpose':
case 'group_purpose':
this.setRoomTopic(room, user, message.purpose);
RocketChat.saveRoomTopic(room._id, message.purpose, user);
return;
case 'channel_name':
case 'group_name':
this.setRoomName(room, user, message.name);
let name = RocketChat.saveRoomName(room._id, message.name);
RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser(room._id, name, user);
return;
case 'channel_archive':
case 'group_archive':
this.archiveRoom(room, user);
RocketChat.archiveRoom(room);
return;
case 'channel_unarchive':
case 'group_unarchive':
this.unarchiveRoom(room, user);
RocketChat.unarchiveRoom(room);
return;
case 'file_share':
if (message.file && message.file.url_private_download !== undefined) {
@ -395,81 +400,18 @@ class SlackBridge {
}
}
/**
* Archives a room
**/
archiveRoom(room, user) {
Meteor.runAsUser(user._id, () => {
return Meteor.call('archiveRoom', room._id);
});
}
/**
* Unarchives a room
**/
unarchiveRoom(room, user) {
Meteor.runAsUser(user._id, () => {
return Meteor.call('unarchiveRoom', room._id);
});
}
/**
* Adds user to room and sends a message
**/
joinRoom(room, user) {
Meteor.runAsUser(user._id, () => {
return Meteor.call('joinRoom', room._id);
});
}
/**
* Adds user to room and sends a message
**/
joinPrivateGroup(inviter, room, user) {
Meteor.runAsUser(inviter._id, () => {
return Meteor.call('addUserToRoom', { rid: room._id, username: user.username });
});
}
/**
* Removes user from room and sends a message
**/
leaveRoom(room, user) {
Meteor.runAsUser(user._id, () => {
return Meteor.call('leaveRoom', room._id);
});
}
/**
* Sets room topic
**/
setRoomTopic(room, user, topic) {
Meteor.runAsUser(user._id, () => {
return Meteor.call('saveRoomSettings', room._id, 'roomTopic', topic);
});
}
/**
* Sets room name
**/
setRoomName(room, user, name) {
Meteor.runAsUser(user._id, () => {
return Meteor.call('saveRoomSettings', room._id, 'roomName', name);
});
}
/**
* Edits a message
**/
editMessage(room, user, message) {
let msgObj = {
_id: `${message.channel}S${message.message.ts}`,
//@TODO _id
_id: `slack-${message.channel}-${message.message.ts.replace(/\./g, '-')}`,
rid: room._id,
msg: this.convertSlackMessageToRocketChat(message.message.text)
};
Meteor.runAsUser(user._id, () => {
return Meteor.call('updateMessage', msgObj);
});
RocketChat.updateMessage(msgObj, user);
}
/**

@ -1,65 +0,0 @@
Meteor.methods
createChannel: (name, members) ->
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', "Invalid user", { method: 'createChannel' }
try
nameValidation = new RegExp '^' + RocketChat.settings.get('UTF8_Names_Validation') + '$'
catch
nameValidation = new RegExp '^[0-9a-zA-Z-_.]+$'
if not nameValidation.test name
throw new Meteor.Error 'error-invalid-name', "Invalid name", { method: 'createChannel' }
if RocketChat.authz.hasPermission(Meteor.userId(), 'create-c') isnt true
throw new Meteor.Error 'error-not-allowed', "Not allowed", { method: 'createChannel' }
now = new Date()
user = Meteor.user()
members.push user.username if user.username not in members
# avoid duplicate names
if RocketChat.models.Rooms.findOneByName name
if RocketChat.models.Rooms.findOneByName(name).archived
throw new Meteor.Error 'error-archived-duplicate-name', "There's an archived channel with name " + name, { method: 'createChannel', room_name: name }
else
throw new Meteor.Error 'error-duplicate-channel-name', "A channel with name '" + name + "' exists", { method: 'createChannel', room_name: name }
# name = s.slugify name
RocketChat.callbacks.run 'beforeCreateChannel', user,
t: 'c'
name: name
ts: now
usernames: members
u:
_id: user._id
username: user.username
# create new room
room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames 'c', name, user, members,
ts: now
for username in members
member = RocketChat.models.Users.findOneByUsername username
if not member?
continue
extra =
open: true
if username is user.username
extra.ls = now
RocketChat.models.Subscriptions.createWithRoomAndUser room, member, extra
# set creator as channel moderator. permission limited to channel by scoping to rid
RocketChat.authz.addUserRoles(Meteor.userId(), ['owner'], room._id)
Meteor.defer ->
RocketChat.callbacks.run 'afterCreateChannel', user, room
return {
rid: room._id
}

@ -1,39 +0,0 @@
Meteor.methods
joinRoom: (rid) ->
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'joinRoom' }
room = RocketChat.models.Rooms.findOneById rid
if not room?
throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'joinRoom' }
if room.t isnt 'c' or RocketChat.authz.hasPermission(Meteor.userId(), 'view-c-room') isnt true
throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'joinRoom' }
now = new Date()
# Check if user is already in room
subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, Meteor.userId()
if subscription?
return
user = RocketChat.models.Users.findOneById Meteor.userId()
RocketChat.callbacks.run 'beforeJoinRoom', user, room
RocketChat.models.Rooms.addUsernameById rid, user.username
RocketChat.models.Subscriptions.createWithRoomAndUser room, user,
ts: now
open: true
alert: true
unread: 1
RocketChat.models.Messages.createUserJoinWithRoomIdAndUser rid, user,
ts: now
Meteor.defer ->
RocketChat.callbacks.run 'afterJoinRoom', user, room
return true

@ -8,53 +8,7 @@ Meteor.methods
user = Meteor.user()
if service is 'initials'
RocketChat.models.Users.setAvatarOrigin user._id, service
return
if service is 'url'
result = null
try
result = HTTP.get dataURI, npmRequestOptions: {encoding: 'binary'}
catch e
console.log "Error while handling the setting of the avatar from a url (#{dataURI}) for #{user.username}:", e
throw new Meteor.Error('error-avatar-url-handling', 'Error while handling avatar setting from a URL ('+ dataURI +') for ' + user.username, { method: 'setAvatarFromService', url: dataURI, username: user.username });
if result.statusCode isnt 200
console.log "Not a valid response, #{result.statusCode}, from the avatar url: #{dataURI}"
throw new Meteor.Error('error-avatar-invalid-url', 'Invalid avatar URL: ' + dataURI, { method: 'setAvatarFromService', url: dataURI })
if not /image\/.+/.test result.headers['content-type']
console.log "Not a valid content-type from the provided url, #{result.headers['content-type']}, from the avatar url: #{dataURI}"
throw new Meteor.Error('error-avatar-invalid-url', 'Invalid avatar URL: ' + dataURI, { method: 'setAvatarFromService', url: dataURI })
ars = RocketChatFile.bufferToStream new Buffer(result.content, 'binary')
RocketChatFileAvatarInstance.deleteFile encodeURIComponent("#{user.username}.jpg")
aws = RocketChatFileAvatarInstance.createWriteStream encodeURIComponent("#{user.username}.jpg"), result.headers['content-type']
aws.on 'end', Meteor.bindEnvironment ->
Meteor.setTimeout ->
console.log "Set #{user.username}'s avatar from the url: #{dataURI}"
RocketChat.models.Users.setAvatarOrigin user._id, service
RocketChat.Notifications.notifyAll 'updateAvatar', { username: user.username }
, 500
ars.pipe(aws)
return
{image, contentType} = RocketChatFile.dataURIParse dataURI
rs = RocketChatFile.bufferToStream new Buffer(image, 'base64')
RocketChatFileAvatarInstance.deleteFile encodeURIComponent("#{user.username}.jpg")
ws = RocketChatFileAvatarInstance.createWriteStream encodeURIComponent("#{user.username}.jpg"), contentType
ws.on 'end', Meteor.bindEnvironment ->
Meteor.setTimeout ->
RocketChat.models.Users.setAvatarOrigin user._id, service
RocketChat.Notifications.notifyAll 'updateAvatar', {username: user.username}
, 500
rs.pipe(ws)
return
return RocketChat.setUserAvatar(user, dataURI, contentType, service);
DDPRateLimiter.addRule
type: 'method'

Loading…
Cancel
Save