From aef7ec99069f32c138efd5e8937b10c543eb65e0 Mon Sep 17 00:00:00 2001 From: graywolf336 Date: Fri, 11 Mar 2016 09:46:04 -0600 Subject: [PATCH 01/13] Remove the try/catches around the imports --- .../server/HipChatImporter.coffee | 366 ++++++------- .../server/SlackImporter.coffee | 512 +++++++++--------- 2 files changed, 439 insertions(+), 439 deletions(-) diff --git a/packages/rocketchat-importer-hipchat/server/HipChatImporter.coffee b/packages/rocketchat-importer-hipchat/server/HipChatImporter.coffee index b411d319adb..d3266cc7a9d 100644 --- a/packages/rocketchat-importer-hipchat/server/HipChatImporter.coffee +++ b/packages/rocketchat-importer-hipchat/server/HipChatImporter.coffee @@ -9,95 +9,95 @@ Importer.HipChat = class Importer.HipChat extends Importer.Base prepare: (dataURI, sentContentType, fileName) => super(dataURI, sentContentType, fileName) - try - {image, contentType} = RocketChatFile.dataURIParse dataURI - zip = new @AdmZip(new Buffer(image, 'base64')) - zipEntries = zip.getEntries() - - tempRooms = [] - tempUsers = [] - tempMessages = {} - for entry in zipEntries - do (entry) => - if not entry.isDirectory - if entry.entryName.indexOf(Importer.HipChat.RoomPrefix) > -1 - roomName = entry.entryName.split(Importer.HipChat.RoomPrefix)[1] - if roomName is 'list.json' - @updateProgress Importer.ProgressStep.PREPARING_CHANNELS - tempRooms = JSON.parse(entry.getData().toString()).rooms - for room in tempRooms - room.name = _.slugify room.name - else if roomName.indexOf('/') > -1 - item = roomName.split('/') - roomName = _.slugify item[0] #random - msgGroupData = item[1].split('.')[0] #2015-10-04 - if not tempMessages[roomName] - tempMessages[roomName] = {} - # For some reason some of the json files in the HipChat export aren't valid JSON - # files, so we need to catch those and just ignore them (sadly). - try - tempMessages[roomName][msgGroupData] = JSON.parse entry.getData().toString() - catch - console.warn "#{entry.entryName} is not a valid JSON file! Unable to import it." - else if entry.entryName.indexOf(Importer.HipChat.UsersPrefix) > -1 - usersName = entry.entryName.split(Importer.HipChat.UsersPrefix)[1] - if usersName is 'list.json' - @updateProgress Importer.ProgressStep.PREPARING_USERS - tempUsers = JSON.parse(entry.getData().toString()).users - else - console.warn "Unexpected file in the #{@name} import: #{entry.entryName}" - - # Insert the users record, eventually this might have to be split into several ones as well - # if someone tries to import a several thousands users instance - usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers } - @users = @collection.findOne usersId - @updateRecord { 'count.users': tempUsers.length } - @addCountToTotal tempUsers.length - - # Insert the rooms records. - channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempRooms } - @channels = @collection.findOne channelsId - @updateRecord { 'count.channels': tempRooms.length } - @addCountToTotal tempRooms.length - - # Insert the messages records - @updateProgress Importer.ProgressStep.PREPARING_MESSAGES - messagesCount = 0 - for channel, messagesObj of tempMessages - do (channel, messagesObj) => - if not @messages[channel] - @messages[channel] = {} - for date, msgs of messagesObj - messagesCount += msgs.length - @updateRecord { 'messagesstatus': "#{channel}/#{date}" } - - if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize - for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs) - messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg } - @messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId + # try + {image, contentType} = RocketChatFile.dataURIParse dataURI + zip = new @AdmZip(new Buffer(image, 'base64')) + zipEntries = zip.getEntries() + + tempRooms = [] + tempUsers = [] + tempMessages = {} + for entry in zipEntries + do (entry) => + if not entry.isDirectory + if entry.entryName.indexOf(Importer.HipChat.RoomPrefix) > -1 + roomName = entry.entryName.split(Importer.HipChat.RoomPrefix)[1] + if roomName is 'list.json' + @updateProgress Importer.ProgressStep.PREPARING_CHANNELS + tempRooms = JSON.parse(entry.getData().toString()).rooms + for room in tempRooms + room.name = _.slugify room.name + else if roomName.indexOf('/') > -1 + item = roomName.split('/') + roomName = _.slugify item[0] #random + msgGroupData = item[1].split('.')[0] #2015-10-04 + if not tempMessages[roomName] + tempMessages[roomName] = {} + # For some reason some of the json files in the HipChat export aren't valid JSON + # files, so we need to catch those and just ignore them (sadly). + try + tempMessages[roomName][msgGroupData] = JSON.parse entry.getData().toString() + catch + console.warn "#{entry.entryName} is not a valid JSON file! Unable to import it." + else if entry.entryName.indexOf(Importer.HipChat.UsersPrefix) > -1 + usersName = entry.entryName.split(Importer.HipChat.UsersPrefix)[1] + if usersName is 'list.json' + @updateProgress Importer.ProgressStep.PREPARING_USERS + tempUsers = JSON.parse(entry.getData().toString()).users else - messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs } - @messages[channel][date] = @collection.findOne messagesId - - @updateRecord { 'count.messages': messagesCount, 'messagesstatus': null } - @addCountToTotal messagesCount - - if tempUsers.length is 0 or tempRooms.length is 0 or messagesCount is 0 - @updateProgress Importer.ProgressStep.ERROR - return @getProgress() - - selectionUsers = tempUsers.map (user) -> - #HipChat's export doesn't contain bot users, from the data I've seen - return new Importer.SelectionUser user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot - selectionChannels = tempRooms.map (room) -> - return new Importer.SelectionChannel room.room_id, room.name, room.is_archived, true + console.warn "Unexpected file in the #{@name} import: #{entry.entryName}" + + # Insert the users record, eventually this might have to be split into several ones as well + # if someone tries to import a several thousands users instance + usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers } + @users = @collection.findOne usersId + @updateRecord { 'count.users': tempUsers.length } + @addCountToTotal tempUsers.length + + # Insert the rooms records. + channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempRooms } + @channels = @collection.findOne channelsId + @updateRecord { 'count.channels': tempRooms.length } + @addCountToTotal tempRooms.length + + # Insert the messages records + @updateProgress Importer.ProgressStep.PREPARING_MESSAGES + messagesCount = 0 + for channel, messagesObj of tempMessages + do (channel, messagesObj) => + if not @messages[channel] + @messages[channel] = {} + for date, msgs of messagesObj + messagesCount += msgs.length + @updateRecord { 'messagesstatus': "#{channel}/#{date}" } + + if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize + for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs) + messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg } + @messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId + else + messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs } + @messages[channel][date] = @collection.findOne messagesId + + @updateRecord { 'count.messages': messagesCount, 'messagesstatus': null } + @addCountToTotal messagesCount + + if tempUsers.length is 0 or tempRooms.length is 0 or messagesCount is 0 + @updateProgress Importer.ProgressStep.ERROR + return @getProgress() + + selectionUsers = tempUsers.map (user) -> + #HipChat's export doesn't contain bot users, from the data I've seen + return new Importer.SelectionUser user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot + selectionChannels = tempRooms.map (room) -> + return new Importer.SelectionChannel room.room_id, room.name, room.is_archived, true - @updateProgress Importer.ProgressStep.USER_SELECTION - return new Importer.Selection @name, selectionUsers, selectionChannels - catch error - @updateRecord { 'failed': true, 'error': error } - console.error Importer.ProgressStep.ERROR - throw new Error 'import-hipchat-error', error + @updateProgress Importer.ProgressStep.USER_SELECTION + return new Importer.Selection @name, selectionUsers, selectionChannels + # catch error + # @updateRecord { 'failed': true, 'error': error } + # console.error Importer.ProgressStep.ERROR + # throw new Error 'import-hipchat-error', error startImport: (importSelection) => super(importSelection) @@ -115,105 +115,105 @@ Importer.HipChat = class Importer.HipChat extends Importer.Base startedByUserId = Meteor.userId() Meteor.defer => - try - @updateProgress Importer.ProgressStep.IMPORTING_USERS - for user in @users.users when user.do_import - do (user) => - Meteor.runAsUser startedByUserId, () => - existantUser = RocketChat.models.Users.findOneByEmailAddress user.email - if existantUser - user.rocketId = existantUser._id - @userTags.push - hipchat: "@#{user.mention_name}" - rocket: "@#{existantUser.username}" - else - userId = Accounts.createUser { email: user.email, password: Date.now() + user.name + user.email.toUpperCase() } - user.rocketId = userId - @userTags.push - hipchat: "@#{user.mention_name}" - rocket: "@#{user.mention_name}" + # try + @updateProgress Importer.ProgressStep.IMPORTING_USERS + for user in @users.users when user.do_import + do (user) => + Meteor.runAsUser startedByUserId, () => + existantUser = RocketChat.models.Users.findOneByEmailAddress user.email + if existantUser + user.rocketId = existantUser._id + @userTags.push + hipchat: "@#{user.mention_name}" + rocket: "@#{existantUser.username}" + else + userId = Accounts.createUser { email: user.email, password: Date.now() + user.name + user.email.toUpperCase() } + user.rocketId = userId + @userTags.push + hipchat: "@#{user.mention_name}" + rocket: "@#{user.mention_name}" + Meteor.runAsUser userId, () => + Meteor.call 'setUsername', user.mention_name + Meteor.call 'joinDefaultChannels', true + Meteor.call 'setAvatarFromService', user.photo_url, null, 'url' + Meteor.call 'updateUserUtcOffset', parseInt moment().tz(user.timezone).format('Z').toString().split(':')[0] + + if user.name? + RocketChat.models.Users.setName userId, user.name + + #Deleted users are 'inactive' users in Rocket.Chat + if user.is_deleted + Meteor.call 'setUserActiveStatus', userId, false + @addCountCompleted 1 + @collection.update { _id: @users._id }, { $set: { 'users': @users.users }} + + @updateProgress Importer.ProgressStep.IMPORTING_CHANNELS + for channel in @channels.channels when channel.do_import + do (channel) => + Meteor.runAsUser startedByUserId, () => + channel.name = channel.name.replace(/ /g, '') + existantRoom = RocketChat.models.Rooms.findOneByName channel.name + if existantRoom + channel.rocketId = existantRoom._id + else + userId = '' + for user in @users.users when user.user_id is channel.owner_user_id + userId = user.rocketId + + if userId isnt '' Meteor.runAsUser userId, () => - Meteor.call 'setUsername', user.mention_name - Meteor.call 'joinDefaultChannels', true - Meteor.call 'setAvatarFromService', user.photo_url, null, 'url' - Meteor.call 'updateUserUtcOffset', parseInt moment().tz(user.timezone).format('Z').toString().split(':')[0] - - if user.name? - RocketChat.models.Users.setName userId, user.name - - #Deleted users are 'inactive' users in Rocket.Chat - if user.is_deleted - Meteor.call 'setUserActiveStatus', userId, false - @addCountCompleted 1 - @collection.update { _id: @users._id }, { $set: { 'users': @users.users }} - - @updateProgress Importer.ProgressStep.IMPORTING_CHANNELS - for channel in @channels.channels when channel.do_import - do (channel) => - Meteor.runAsUser startedByUserId, () => - channel.name = channel.name.replace(/ /g, '') - existantRoom = RocketChat.models.Rooms.findOneByName channel.name - if existantRoom - channel.rocketId = existantRoom._id + returned = Meteor.call 'createChannel', channel.name, [] + channel.rocketId = returned.rid + RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: { 'ts': new Date(channel.created * 1000) }} else - userId = '' - for user in @users.users when user.user_id is channel.owner_user_id - userId = user.rocketId - - if userId isnt '' - Meteor.runAsUser userId, () => - returned = Meteor.call 'createChannel', channel.name, [] - channel.rocketId = returned.rid - RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: { 'ts': new Date(channel.created * 1000) }} - else - console.warn "Failed to find the channel creator for #{channel.name}." - @addCountCompleted 1 - @collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }} - - @updateProgress Importer.ProgressStep.IMPORTING_MESSAGES - nousers = {}; - for channel, messagesObj of @messages - do (channel, messagesObj) => - Meteor.runAsUser startedByUserId, () => - hipchatChannel = @getHipChatChannelFromName channel - if hipchatChannel?.do_import - room = RocketChat.models.Rooms.findOneById hipchatChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } } - for date, msgs of messagesObj - @updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" } - for message in msgs.messages - if message.from? - user = @getRocketUser(message.from.user_id) - if user? - msgObj = - msg: @convertHipChatMessageToRocketChat(message.message) - ts: new Date(message.date) - u: - _id: user._id - username: user.username - - RocketChat.sendMessage user, msgObj, room - else - if not nousers[message.from.user_id] - nousers[message.from.user_id] = message.from + console.warn "Failed to find the channel creator for #{channel.name}." + @addCountCompleted 1 + @collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }} + + @updateProgress Importer.ProgressStep.IMPORTING_MESSAGES + nousers = {}; + for channel, messagesObj of @messages + do (channel, messagesObj) => + Meteor.runAsUser startedByUserId, () => + hipchatChannel = @getHipChatChannelFromName channel + if hipchatChannel?.do_import + room = RocketChat.models.Rooms.findOneById hipchatChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } } + for date, msgs of messagesObj + @updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" } + for message in msgs.messages + if message.from? + user = @getRocketUser(message.from.user_id) + if user? + msgObj = + msg: @convertHipChatMessageToRocketChat(message.message) + ts: new Date(message.date) + u: + _id: user._id + username: user.username + + RocketChat.sendMessage user, msgObj, room else - if not _.isArray message - console.warn 'Please report the following:', message - @addCountCompleted 1 - console.warn 'The following did not have users:', nousers - - @updateProgress Importer.ProgressStep.FINISHING - for channel in @channels.channels when channel.do_import and channel.is_archived - do (channel) => - Meteor.runAsUser startedByUserId, () => - Meteor.call 'archiveRoom', channel.rocketId - - @updateProgress Importer.ProgressStep.DONE - timeTook = Date.now() - start - console.log "Import took #{timeTook} milliseconds." - catch error - @updateRecord { 'failed': true, 'error': error } - console.error Importer.ProgressStep.ERROR - throw new Error 'import-hipchat-error', error + if not nousers[message.from.user_id] + nousers[message.from.user_id] = message.from + else + if not _.isArray message + console.warn 'Please report the following:', message + @addCountCompleted 1 + console.warn 'The following did not have users:', nousers + + @updateProgress Importer.ProgressStep.FINISHING + for channel in @channels.channels when channel.do_import and channel.is_archived + do (channel) => + Meteor.runAsUser startedByUserId, () => + Meteor.call 'archiveRoom', channel.rocketId + + @updateProgress Importer.ProgressStep.DONE + timeTook = Date.now() - start + console.log "Import took #{timeTook} milliseconds." + # catch error + # @updateRecord { 'failed': true, 'error': error } + # console.error Importer.ProgressStep.ERROR + # throw new Error 'import-hipchat-error', error return @getProgress() diff --git a/packages/rocketchat-importer-slack/server/SlackImporter.coffee b/packages/rocketchat-importer-slack/server/SlackImporter.coffee index fcca408db66..4853cde10ee 100644 --- a/packages/rocketchat-importer-slack/server/SlackImporter.coffee +++ b/packages/rocketchat-importer-slack/server/SlackImporter.coffee @@ -7,88 +7,88 @@ Importer.Slack = class Importer.Slack extends Importer.Base prepare: (dataURI, sentContentType, fileName) => super(dataURI, sentContentType, fileName) - try - {image, contentType} = RocketChatFile.dataURIParse dataURI - zip = new @AdmZip(new Buffer(image, 'base64')) - zipEntries = zip.getEntries() - - tempChannels = [] - tempUsers = [] - tempMessages = {} - for entry in zipEntries - do (entry) => - if entry.entryName == 'channels.json' - @updateProgress Importer.ProgressStep.PREPARING_CHANNELS - tempChannels = JSON.parse entry.getData().toString() - else if entry.entryName == 'users.json' - @updateProgress Importer.ProgressStep.PREPARING_USERS - tempUsers = JSON.parse entry.getData().toString() - - for user in tempUsers when user.is_bot - @bots[user.profile.bot_id] = user - - else if not entry.isDirectory and entry.entryName.indexOf('/') > -1 - item = entry.entryName.split('/') #random/2015-10-04.json - channelName = item[0] #random - msgGroupData = item[1].split('.')[0] #2015-10-04 - if not tempMessages[channelName] - tempMessages[channelName] = {} - # Catch files which aren't valid JSON files, ignore them - try - tempMessages[channelName][msgGroupData] = JSON.parse entry.getData().toString() - catch - console.warn "#{entry.entryName} is not a valid JSON file! Unable to import it." - - # Insert the users record, eventually this might have to be split into several ones as well - # if someone tries to import a several thousands users instance - usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers } - @users = @collection.findOne usersId - @updateRecord { 'count.users': tempUsers.length } - @addCountToTotal tempUsers.length - - # Insert the channels records. - channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempChannels } - @channels = @collection.findOne channelsId - @updateRecord { 'count.channels': tempChannels.length } - @addCountToTotal tempChannels.length - - # Insert the messages records - @updateProgress Importer.ProgressStep.PREPARING_MESSAGES - messagesCount = 0 - for channel, messagesObj of tempMessages - do (channel, messagesObj) => - if not @messages[channel] - @messages[channel] = {} - for date, msgs of messagesObj - messagesCount += msgs.length - @updateRecord { 'messagesstatus': "#{channel}/#{date}" } - - if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize - for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs) - messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg } - @messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId - else - messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs } - @messages[channel][date] = @collection.findOne messagesId - - @updateRecord { 'count.messages': messagesCount, 'messagesstatus': null } - @addCountToTotal messagesCount - - if tempUsers.length is 0 or tempChannels.length is 0 or messagesCount is 0 - @updateProgress Importer.ProgressStep.ERROR - return @getProgress() - - selectionUsers = tempUsers.map (user) -> - return new Importer.SelectionUser user.id, user.name, user.profile.email, user.deleted, user.is_bot, !user.is_bot - selectionChannels = tempChannels.map (channel) -> - return new Importer.SelectionChannel channel.id, channel.name, channel.is_archived, true + # try + {image, contentType} = RocketChatFile.dataURIParse dataURI + zip = new @AdmZip(new Buffer(image, 'base64')) + zipEntries = zip.getEntries() + + tempChannels = [] + tempUsers = [] + tempMessages = {} + for entry in zipEntries + do (entry) => + if entry.entryName == 'channels.json' + @updateProgress Importer.ProgressStep.PREPARING_CHANNELS + tempChannels = JSON.parse entry.getData().toString() + else if entry.entryName == 'users.json' + @updateProgress Importer.ProgressStep.PREPARING_USERS + tempUsers = JSON.parse entry.getData().toString() + + for user in tempUsers when user.is_bot + @bots[user.profile.bot_id] = user + + else if not entry.isDirectory and entry.entryName.indexOf('/') > -1 + item = entry.entryName.split('/') #random/2015-10-04.json + channelName = item[0] #random + msgGroupData = item[1].split('.')[0] #2015-10-04 + if not tempMessages[channelName] + tempMessages[channelName] = {} + # Catch files which aren't valid JSON files, ignore them + try + tempMessages[channelName][msgGroupData] = JSON.parse entry.getData().toString() + catch + console.warn "#{entry.entryName} is not a valid JSON file! Unable to import it." + + # Insert the users record, eventually this might have to be split into several ones as well + # if someone tries to import a several thousands users instance + usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers } + @users = @collection.findOne usersId + @updateRecord { 'count.users': tempUsers.length } + @addCountToTotal tempUsers.length + + # Insert the channels records. + channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempChannels } + @channels = @collection.findOne channelsId + @updateRecord { 'count.channels': tempChannels.length } + @addCountToTotal tempChannels.length + + # Insert the messages records + @updateProgress Importer.ProgressStep.PREPARING_MESSAGES + messagesCount = 0 + for channel, messagesObj of tempMessages + do (channel, messagesObj) => + if not @messages[channel] + @messages[channel] = {} + for date, msgs of messagesObj + messagesCount += msgs.length + @updateRecord { 'messagesstatus': "#{channel}/#{date}" } + + if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize + for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs) + messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg } + @messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId + else + messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs } + @messages[channel][date] = @collection.findOne messagesId + + @updateRecord { 'count.messages': messagesCount, 'messagesstatus': null } + @addCountToTotal messagesCount + + if tempUsers.length is 0 or tempChannels.length is 0 or messagesCount is 0 + @updateProgress Importer.ProgressStep.ERROR + return @getProgress() + + selectionUsers = tempUsers.map (user) -> + return new Importer.SelectionUser user.id, user.name, user.profile.email, user.deleted, user.is_bot, !user.is_bot + selectionChannels = tempChannels.map (channel) -> + return new Importer.SelectionChannel channel.id, channel.name, channel.is_archived, true - @updateProgress Importer.ProgressStep.USER_SELECTION - return new Importer.Selection @name, selectionUsers, selectionChannels - catch error - @updateRecord { 'failed': true, 'error': error } - console.error Importer.ProgressStep.ERROR - throw new Error 'import-slack-error', error + @updateProgress Importer.ProgressStep.USER_SELECTION + return new Importer.Selection @name, selectionUsers, selectionChannels + # catch error + # @updateRecord { 'failed': true, 'error': error } + # console.error Importer.ProgressStep.ERROR + # throw new Error 'import-slack-error', error startImport: (importSelection) => super(importSelection) @@ -106,183 +106,183 @@ Importer.Slack = class Importer.Slack extends Importer.Base startedByUserId = Meteor.userId() Meteor.defer => - try - @updateProgress Importer.ProgressStep.IMPORTING_USERS - for user in @users.users when user.do_import - do (user) => - Meteor.runAsUser startedByUserId, () => - existantUser = RocketChat.models.Users.findOneByEmailAddress user.profile.email - if existantUser - user.rocketId = existantUser._id - @userTags.push - slack: "<@#{user.id}>" - slackLong: "<@#{user.id}|#{user.name}>" - rocket: "@#{existantUser.username}" - else - userId = Accounts.createUser { email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() } - Meteor.runAsUser userId, () => - Meteor.call 'setUsername', user.name - Meteor.call 'joinDefaultChannels', true - url = null - if user.profile.image_original - url = user.profile.image_original - else if user.profile.image_512 - url = user.profile.image_512 - Meteor.call 'setAvatarFromService', url, null, 'url' - # Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600 - if user.tz_offset - Meteor.call 'updateUserUtcOffset', user.tz_offset / 3600 - - if user.profile.real_name - RocketChat.models.Users.setName userId, user.profile.real_name - #Deleted users are 'inactive' users in Rocket.Chat - if user.deleted - Meteor.call 'setUserActiveStatus', userId, false - #TODO: Maybe send emails? - user.rocketId = userId - @userTags.push - slack: "<@#{user.id}>" - slackLong: "<@#{user.id}|#{user.name}>" - rocket: "@#{user.name}" - @addCountCompleted 1 - @collection.update { _id: @users._id }, { $set: { 'users': @users.users }} - - @updateProgress Importer.ProgressStep.IMPORTING_CHANNELS - for channel in @channels.channels when channel.do_import - do (channel) => - Meteor.runAsUser startedByUserId, () => - existantRoom = RocketChat.models.Rooms.findOneByName channel.name - if existantRoom or channel.is_general - if channel.is_general and channel.name isnt existantRoom?.name - Meteor.call 'saveRoomSettings', 'GENERAL', 'roomName', channel.name - channel.rocketId = if channel.is_general then 'GENERAL' else existantRoom._id - else - users = [] - for member in channel.members when member isnt channel.creator - user = @getRocketUser member - if user? - users.push user.username - - userId = '' - for user in @users.users when user.id is channel.creator - userId = user.rocketId - - Meteor.runAsUser userId, () => - returned = Meteor.call 'createChannel', channel.name, users - channel.rocketId = returned.rid - - # @TODO implement model specific function - roomUpdate = - ts: new Date(channel.created * 1000) - - if not _.isEmpty channel.topic?.value - roomUpdate.topic = channel.topic.value - lastSetTopic = channel.topic.last_set - - if not _.isEmpty(channel.purpose?.value) and channel.purpose.last_set > lastSetTopic - roomUpdate.topic = channel.purpose.value - - RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: roomUpdate } - - @addCountCompleted 1 - @collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }} - - missedTypes = {} - ignoreTypes = { 'bot_add': true, 'file_comment': true, 'file_mention': true, 'channel_name': true } - @updateProgress Importer.ProgressStep.IMPORTING_MESSAGES - for channel, messagesObj of @messages - do (channel, messagesObj) => - Meteor.runAsUser startedByUserId, () => - slackChannel = @getSlackChannelFromName channel - if slackChannel?.do_import - room = RocketChat.models.Rooms.findOneById slackChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } } - for date, msgs of messagesObj - @updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" } - for message in msgs.messages - if message.type is 'message' - if message.subtype? - if message.subtype is 'channel_join' - if @getRocketUser(message.user)? - RocketChat.models.Messages.createUserJoinWithRoomIdAndUser room._id, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) } - else if message.subtype is 'channel_leave' - if @getRocketUser(message.user)? - RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser room._id, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) } - else if message.subtype is 'me_message' - RocketChat.sendMessage @getRocketUser(message.user), { msg: '_' + @convertSlackMessageToRocketChat(message.text) + '_', ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }, room - else if message.subtype is 'bot_message' - botUser = RocketChat.models.Users.findOneById 'rocket.cat', { fields: { username: 1 }} - botUsername = if @bots[message.bot_id] then @bots[message.bot_id]?.name else message.username - msgObj = - msg: if message.text then message.text else '' - ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) + # try + @updateProgress Importer.ProgressStep.IMPORTING_USERS + for user in @users.users when user.do_import + do (user) => + Meteor.runAsUser startedByUserId, () => + existantUser = RocketChat.models.Users.findOneByEmailAddress user.profile.email + if existantUser + user.rocketId = existantUser._id + @userTags.push + slack: "<@#{user.id}>" + slackLong: "<@#{user.id}|#{user.name}>" + rocket: "@#{existantUser.username}" + else + userId = Accounts.createUser { email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() } + Meteor.runAsUser userId, () => + Meteor.call 'setUsername', user.name + Meteor.call 'joinDefaultChannels', true + url = null + if user.profile.image_original + url = user.profile.image_original + else if user.profile.image_512 + url = user.profile.image_512 + Meteor.call 'setAvatarFromService', url, null, 'url' + # Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600 + if user.tz_offset + Meteor.call 'updateUserUtcOffset', user.tz_offset / 3600 + + if user.profile.real_name + RocketChat.models.Users.setName userId, user.profile.real_name + #Deleted users are 'inactive' users in Rocket.Chat + if user.deleted + Meteor.call 'setUserActiveStatus', userId, false + #TODO: Maybe send emails? + user.rocketId = userId + @userTags.push + slack: "<@#{user.id}>" + slackLong: "<@#{user.id}|#{user.name}>" + rocket: "@#{user.name}" + @addCountCompleted 1 + @collection.update { _id: @users._id }, { $set: { 'users': @users.users }} + + @updateProgress Importer.ProgressStep.IMPORTING_CHANNELS + for channel in @channels.channels when channel.do_import + do (channel) => + Meteor.runAsUser startedByUserId, () => + existantRoom = RocketChat.models.Rooms.findOneByName channel.name + if existantRoom or channel.is_general + if channel.is_general and channel.name isnt existantRoom?.name + Meteor.call 'saveRoomSettings', 'GENERAL', 'roomName', channel.name + channel.rocketId = if channel.is_general then 'GENERAL' else existantRoom._id + else + users = [] + for member in channel.members when member isnt channel.creator + user = @getRocketUser member + if user? + users.push user.username + + userId = '' + for user in @users.users when user.id is channel.creator + userId = user.rocketId + + Meteor.runAsUser userId, () => + returned = Meteor.call 'createChannel', channel.name, users + channel.rocketId = returned.rid + + # @TODO implement model specific function + roomUpdate = + ts: new Date(channel.created * 1000) + + if not _.isEmpty channel.topic?.value + roomUpdate.topic = channel.topic.value + lastSetTopic = channel.topic.last_set + + if not _.isEmpty(channel.purpose?.value) and channel.purpose.last_set > lastSetTopic + roomUpdate.topic = channel.purpose.value + + RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: roomUpdate } + + @addCountCompleted 1 + @collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }} + + missedTypes = {} + ignoreTypes = { 'bot_add': true, 'file_comment': true, 'file_mention': true, 'channel_name': true } + @updateProgress Importer.ProgressStep.IMPORTING_MESSAGES + for channel, messagesObj of @messages + do (channel, messagesObj) => + Meteor.runAsUser startedByUserId, () => + slackChannel = @getSlackChannelFromName channel + if slackChannel?.do_import + room = RocketChat.models.Rooms.findOneById slackChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } } + for date, msgs of messagesObj + @updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" } + for message in msgs.messages + if message.type is 'message' + if message.subtype? + if message.subtype is 'channel_join' + if @getRocketUser(message.user)? + RocketChat.models.Messages.createUserJoinWithRoomIdAndUser room._id, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) } + else if message.subtype is 'channel_leave' + if @getRocketUser(message.user)? + RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser room._id, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) } + else if message.subtype is 'me_message' + RocketChat.sendMessage @getRocketUser(message.user), { msg: '_' + @convertSlackMessageToRocketChat(message.text) + '_', ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }, room + else if message.subtype is 'bot_message' + botUser = RocketChat.models.Users.findOneById 'rocket.cat', { fields: { username: 1 }} + botUsername = if @bots[message.bot_id] then @bots[message.bot_id]?.name else message.username + msgObj = + msg: if message.text then message.text else '' + ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) + rid: room._id + bot: true + attachments: message.attachments + username: if botUsername then botUsername else undefined + + if message.edited? + msgObj.ets = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000) + + if message.icons? + msgObj.emoji = message.icons.emoji + + msgObj.msg = @convertSlackMessageToRocketChat(msgObj.msg) + + RocketChat.sendMessage botUser, msgObj, room + else if message.subtype is 'channel_purpose' + RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.purpose, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) } + else if message.subtype is 'channel_topic' + RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.topic, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) } + else if message.subtype is 'pinned_item' + RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user), + ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) + attachments: [ + "text" : @convertSlackMessageToRocketChat message.attachments[0].text + "author_name" : message.attachments[0].author_subname + "author_icon" : getAvatarUrlFromUsername(message.attachments[0].author_subname) + ] + else if message.subtype is 'file_share' + if message.file?.url_private_download isnt undefined + details = + name: message.file.name + size: message.file.size + type: message.file.mimetype rid: room._id - bot: true - attachments: message.attachments - username: if botUsername then botUsername else undefined - - if message.edited? - msgObj.ets = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000) - - if message.icons? - msgObj.emoji = message.icons.emoji - - msgObj.msg = @convertSlackMessageToRocketChat(msgObj.msg) - - RocketChat.sendMessage botUser, msgObj, room - else if message.subtype is 'channel_purpose' - RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.purpose, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) } - else if message.subtype is 'channel_topic' - RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.topic, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) } - else if message.subtype is 'pinned_item' - RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user), - ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) - attachments: [ - "text" : @convertSlackMessageToRocketChat message.attachments[0].text - "author_name" : message.attachments[0].author_subname - "author_icon" : getAvatarUrlFromUsername(message.attachments[0].author_subname) - ] - else if message.subtype is 'file_share' - if message.file?.url_private_download isnt undefined - details = - name: message.file.name - size: message.file.size - type: message.file.mimetype - rid: room._id - @uploadFile details, message.file.url_private_download, @getRocketUser(message.user), room, new Date(parseInt(message.ts.split('.')[0]) * 1000) - else - if not missedTypes[message.subtype] and not ignoreTypes[message.subtype] - missedTypes[message.subtype] = message + @uploadFile details, message.file.url_private_download, @getRocketUser(message.user), room, new Date(parseInt(message.ts.split('.')[0]) * 1000) else - user = @getRocketUser(message.user) - if user? - msgObj = - msg: @convertSlackMessageToRocketChat message.text - ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) - rid: room._id - u: - _id: user._id - username: user.username - - if message.edited? - msgObj.ets = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000) - - RocketChat.sendMessage @getRocketUser(message.user), msgObj, room - @addCountCompleted 1 - console.log missedTypes - @updateProgress Importer.ProgressStep.FINISHING - for channel in @channels.channels when channel.do_import and channel.is_archived - do (channel) => - Meteor.runAsUser startedByUserId, () => - Meteor.call 'archiveRoom', channel.rocketId - - @updateProgress Importer.ProgressStep.DONE - timeTook = Date.now() - start - console.log "Import took #{timeTook} milliseconds." - catch error - @updateRecord { 'failed': true, 'error': error } - @updateProgress Importer.ProgressStep.ERROR - console.error Importer.ProgressStep.ERROR - throw new Error 'import-slack-error', error + if not missedTypes[message.subtype] and not ignoreTypes[message.subtype] + missedTypes[message.subtype] = message + else + user = @getRocketUser(message.user) + if user? + msgObj = + msg: @convertSlackMessageToRocketChat message.text + ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) + rid: room._id + u: + _id: user._id + username: user.username + + if message.edited? + msgObj.ets = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000) + + RocketChat.sendMessage @getRocketUser(message.user), msgObj, room + @addCountCompleted 1 + console.log missedTypes + @updateProgress Importer.ProgressStep.FINISHING + for channel in @channels.channels when channel.do_import and channel.is_archived + do (channel) => + Meteor.runAsUser startedByUserId, () => + Meteor.call 'archiveRoom', channel.rocketId + + @updateProgress Importer.ProgressStep.DONE + timeTook = Date.now() - start + console.log "Import took #{timeTook} milliseconds." + # catch error + # @updateRecord { 'failed': true, 'error': error } + # @updateProgress Importer.ProgressStep.ERROR + # console.error Importer.ProgressStep.ERROR + # throw new Error 'import-slack-error', error return @getProgress() From 7c1b1d4f0841e4b38fb109a1a8442997a8876e95 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 17 Mar 2016 17:42:03 -0300 Subject: [PATCH 02/13] Closes #2172; Accepts markdown for room topic. --- .../client/views/channelSettings.html | 2 +- .../message/message.coffee | 18 ++++++++++++------ packages/rocketchat-ui/views/app/room.html | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/rocketchat-channel-settings/client/views/channelSettings.html b/packages/rocketchat-channel-settings/client/views/channelSettings.html index cf20528f348..37f64696658 100644 --- a/packages/rocketchat-channel-settings/client/views/channelSettings.html +++ b/packages/rocketchat-channel-settings/client/views/channelSettings.html @@ -24,7 +24,7 @@ {{#if editing 'roomTopic'}} {{else}} - {{roomTopic}}{{#if canEdit}} {{/if}} + {{{RocketChatMarkdown roomTopic}}}{{#if canEdit}} {{/if}} {{/if}} diff --git a/packages/rocketchat-ui-message/message/message.coffee b/packages/rocketchat-ui-message/message/message.coffee index 9cb1406d384..37539a9421b 100644 --- a/packages/rocketchat-ui-message/message/message.coffee +++ b/packages/rocketchat-ui-message/message/message.coffee @@ -80,24 +80,30 @@ Template.message.onCreated -> @wasEdited = msg.editedAt? and not RocketChat.MessageTypes.isSystemMessage(msg) @body = do -> + isSystemMessage = RocketChat.MessageTypes.isSystemMessage(msg) messageType = RocketChat.MessageTypes.getType(msg) if messageType?.render? - return messageType.render(msg) + msg = messageType.render(msg) else if messageType?.template? # render template else if messageType?.message? if messageType.data?(msg)? - return TAPi18n.__(messageType.message, messageType.data(msg)) + msg = TAPi18n.__(messageType.message, messageType.data(msg)) else - return TAPi18n.__(messageType.message) + msg = TAPi18n.__(messageType.message) else if msg.u?.username is RocketChat.settings.get('Chatops_Username') msg.html = msg.msg - message = RocketChat.callbacks.run 'renderMentions', msg + msg = RocketChat.callbacks.run 'renderMentions', msg # console.log JSON.stringify message - return msg.html + msg = msg.html + else + msg = renderMessageBody msg - return renderMessageBody msg + if isSystemMessage + return RocketChat.Markdown msg + else + return msg Template.message.onViewRendered = (context) -> view = this diff --git a/packages/rocketchat-ui/views/app/room.html b/packages/rocketchat-ui/views/app/room.html index e2e048f1483..1278b02c441 100644 --- a/packages/rocketchat-ui/views/app/room.html +++ b/packages/rocketchat-ui/views/app/room.html @@ -14,7 +14,7 @@ {{/if}} {{roomName}} - {{roomTopic}} + {{{RocketChatMarkdown roomTopic}}}
From d4aec52d4fa73c1c38943369df1354c68d17d67f Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 17 Mar 2016 17:42:46 -0300 Subject: [PATCH 03/13] Add history --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index e3a38cf3886..fd4c47cea68 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ - Fixes #2477: Admin settings, plain-text SMTP password. - Closes #625: Filter and sorts direct messages and private groups. +- Closes #2172; Accepts markdown for room topic. ## 0.22.0, 2016-Mar-14 From 3a5623296a9c8f80bd3bc73524d9392534bc9338 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 17 Mar 2016 17:44:08 -0300 Subject: [PATCH 04/13] Add history --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index fd4c47cea68..fc68d7c87d0 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,7 +2,7 @@ - Fixes #2477: Admin settings, plain-text SMTP password. - Closes #625: Filter and sorts direct messages and private groups. -- Closes #2172; Accepts markdown for room topic. +- Closes #2172: Accepts markdown for room topic. ## 0.22.0, 2016-Mar-14 From b66fd24b5223829f4577162895185091fe1bdbc5 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Thu, 17 Mar 2016 18:47:32 -0300 Subject: [PATCH 05/13] Rebuild the cordova index when change the Site Url --- .../rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee b/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee index 8764db6ce1e..dffbc0918bb 100644 --- a/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee +++ b/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee @@ -13,4 +13,5 @@ RocketChat.settings.get 'Site_Url', (key, value) -> process.env.MOBILE_ROOT_URL = value process.env.MOBILE_DDP_URL = value - # WebAppInternals.generateBoilerplate() + if WebAppInternals?.generateBoilerplate + WebAppInternals.generateBoilerplate() From f9cbd9e203038e910f19fddec32e17e32af2885a Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Thu, 17 Mar 2016 18:48:19 -0300 Subject: [PATCH 06/13] Add ENV to set HOME to /tmp in docker files --- .docker/develop/Dockerfile | 3 ++- .docker/latest/Dockerfile | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.docker/develop/Dockerfile b/.docker/develop/Dockerfile index 7e4d028d5fa..81db355aa7f 100644 --- a/.docker/develop/Dockerfile +++ b/.docker/develop/Dockerfile @@ -24,7 +24,8 @@ WORKDIR /app/bundle ENV MONGO_URL=mongodb://mongo:27017/rocketchat \ PORT=3000 \ ROOT_URL=http://localhost:3000 \ - Accounts_AvatarStorePath=/app/uploads + Accounts_AvatarStorePath=/app/uploads \ + HOME=/tmp EXPOSE 3000 diff --git a/.docker/latest/Dockerfile b/.docker/latest/Dockerfile index 184c04efe52..e5f1ba34462 100644 --- a/.docker/latest/Dockerfile +++ b/.docker/latest/Dockerfile @@ -24,7 +24,8 @@ WORKDIR /app/bundle ENV MONGO_URL=mongodb://mongo:27017/rocketchat \ PORT=3000 \ ROOT_URL=http://localhost:3000 \ - Accounts_AvatarStorePath=/app/uploads + Accounts_AvatarStorePath=/app/uploads \ + HOME=/tmp EXPOSE 3000 From 17cf089e1a96cec309a35368244fc9d241fa481e Mon Sep 17 00:00:00 2001 From: corecache Date: Thu, 17 Mar 2016 23:08:21 +0100 Subject: [PATCH 07/13] CAS Plugin: Fixed messed up indentation - no code canges --- packages/rocketchat-cas/cas_server.js | 66 +++++++++++++++------------ 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/packages/rocketchat-cas/cas_server.js b/packages/rocketchat-cas/cas_server.js index 7041312ae78..95978940af1 100644 --- a/packages/rocketchat-cas/cas_server.js +++ b/packages/rocketchat-cas/cas_server.js @@ -91,41 +91,47 @@ var casTicket = function (req, token, callback) { */ Accounts.registerLoginHandler(function (options) { - if (!options.cas) - return undefined; + if (!options.cas) + return undefined; - if (!_hasCredential(options.cas.credentialToken)) { - throw new Meteor.Error(Accounts.LoginCancelledError.numericError, - 'no matching login attempt found'); - } + if (!_hasCredential(options.cas.credentialToken)) { + throw new Meteor.Error(Accounts.LoginCancelledError.numericError, + 'no matching login attempt found'); + } + + var result = _retrieveCredential(options.cas.credentialToken); + var options = { profile: { name: result.id } }; - var result = _retrieveCredential(options.cas.credentialToken); - var options = { profile: { name: result.id } }; - - logger.debug("Looking up user with username: " + result.id ); - var user = Meteor.users.findOne({ 'services.cas.external_id': result.id }); - - if (user) { - logger.debug("Using existing user for '" + result.id + "' with id: " + user._id); - } else { - var newUser = { - username: result.id, - active: true, - globalRoles: ['user'], - services: { - cas: { - external_id: result.id + // Search existing user by its external service id + logger.debug("Looking up user with username: " + result.id ); + var user = Meteor.users.findOne({ 'services.cas.external_id': result.id }); + + if (user) { + logger.debug("Using existing user for '" + result.id + "' with id: " + user._id); + } else { + + // Define new user + var newUser = { + username: result.id, + active: true, + globalRoles: ['user'], + services: { + cas: { + external_id: result.id + } } - } - }; + }; - logger.debug("User '" + result.id + "'does not exist yet, creating it"); - var userId = Accounts.insertUserDoc({}, newUser); - user = Meteor.users.findOne(userId); - logger.debug("Created new user for '" + result.id + "' with id: " + user._id); - } + // Create the user + logger.debug("User '" + result.id + "'does not exist yet, creating it"); + var userId = Accounts.insertUserDoc({}, newUser); + + // Fetch and use it + user = Meteor.users.findOne(userId); + logger.debug("Created new user for '" + result.id + "' with id: " + user._id); + } - return { userId: user._id }; + return { userId: user._id }; }); var _hasCredential = function(credentialToken) { From ab42deb09aa950d19c0ac2bd73ca47fa62713366 Mon Sep 17 00:00:00 2001 From: corecache Date: Thu, 17 Mar 2016 23:09:42 +0100 Subject: [PATCH 08/13] CAS Plugin: Join freshly created users to default channels. Fixes #2526 --- packages/rocketchat-cas/cas_server.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/rocketchat-cas/cas_server.js b/packages/rocketchat-cas/cas_server.js index 95978940af1..cb5c6b40a46 100644 --- a/packages/rocketchat-cas/cas_server.js +++ b/packages/rocketchat-cas/cas_server.js @@ -129,6 +129,12 @@ var casTicket = function (req, token, callback) { // Fetch and use it user = Meteor.users.findOne(userId); logger.debug("Created new user for '" + result.id + "' with id: " + user._id); + + logger.debug('Joining user to default channels'); + Meteor.runAsUser(user._id, function() { + Meteor.call('joinDefaultChannels'); + }); + } return { userId: user._id }; From f2a174682995b4f2a29678e1e9cd2b582cf12238 Mon Sep 17 00:00:00 2001 From: corecache Date: Thu, 17 Mar 2016 23:27:51 +0100 Subject: [PATCH 09/13] CAS Plugin: more indentation fixes - no code changes. --- packages/rocketchat-cas/cas_client.js | 38 ++++---- packages/rocketchat-cas/cas_server.js | 134 +++++++++++++------------- 2 files changed, 85 insertions(+), 87 deletions(-) diff --git a/packages/rocketchat-cas/cas_client.js b/packages/rocketchat-cas/cas_client.js index 3537311d1a3..454eb3c6b98 100644 --- a/packages/rocketchat-cas/cas_client.js +++ b/packages/rocketchat-cas/cas_client.js @@ -6,7 +6,7 @@ Meteor.loginWithCas = function(callback) { var popup_width = RocketChat.settings.get("CAS_popup_width"); var popup_height = RocketChat.settings.get("CAS_popup_height"); - if (!login_url) { + if (!login_url) { return; } @@ -45,25 +45,23 @@ Meteor.loginWithCas = function(callback) { }; var openCenteredPopup = function(url, width, height) { - var screenX = typeof window.screenX !== 'undefined' - ? window.screenX : window.screenLeft; - var screenY = typeof window.screenY !== 'undefined' - ? window.screenY : window.screenTop; - var outerWidth = typeof window.outerWidth !== 'undefined' - ? window.outerWidth : document.body.clientWidth; - var outerHeight = typeof window.outerHeight !== 'undefined' - ? window.outerHeight : (document.body.clientHeight - 22); - // XXX what is the 22? - // Use `outerWidth - width` and `outerHeight - height` for help in - // positioning the popup centered relative to the current window - var left = screenX + (outerWidth - width) / 2; - var top = screenY + (outerHeight - height) / 2; - var features = ('width=' + width + ',height=' + height + - ',left=' + left + ',top=' + top + ',scrollbars=yes'); + var screenX = typeof window.screenX !== 'undefined' ? window.screenX : window.screenLeft; + var screenY = typeof window.screenY !== 'undefined' ? window.screenY : window.screenTop; + var outerWidth = typeof window.outerWidth !== 'undefined' ? window.outerWidth : document.body.clientWidth; + var outerHeight = typeof window.outerHeight !== 'undefined' ? window.outerHeight : (document.body.clientHeight - 22); + // XXX what is the 22? - var newwindow = window.open(url, 'Login', features); - if (newwindow.focus) - newwindow.focus(); -return newwindow; + // Use `outerWidth - width` and `outerHeight - height` for help in + // positioning the popup centered relative to the current window + var left = screenX + (outerWidth - width) / 2; + var top = screenY + (outerHeight - height) / 2; + var features = ('width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',scrollbars=yes'); + + var newwindow = window.open(url, 'Login', features); + if (newwindow.focus) { + newwindow.focus(); + } + + return newwindow; }; diff --git a/packages/rocketchat-cas/cas_server.js b/packages/rocketchat-cas/cas_server.js index cb5c6b40a46..858882752fa 100644 --- a/packages/rocketchat-cas/cas_server.js +++ b/packages/rocketchat-cas/cas_server.js @@ -8,77 +8,77 @@ RoutePolicy.declare('/_cas/', 'network'); // Listen to incoming OAuth http requests WebApp.connectHandlers.use(function(req, res, next) { - // Need to create a Fiber since we're using synchronous http calls and nothing - // else is wrapping this in a fiber automatically - Fiber(function () { - middleware(req, res, next); - }).run(); + // Need to create a Fiber since we're using synchronous http calls and nothing + // else is wrapping this in a fiber automatically + Fiber(function () { + middleware(req, res, next); + }).run(); }); var middleware = function (req, res, next) { - // Make sure to catch any exceptions because otherwise we'd crash - // the runner - try { - var barePath = req.url.substring(0, req.url.indexOf('?')); - var splitPath = barePath.split('/'); - - // Any non-cas request will continue down the default - // middlewares. - if (splitPath[1] !== '_cas') { - next(); - return; - } + // Make sure to catch any exceptions because otherwise we'd crash + // the runner + try { + var barePath = req.url.substring(0, req.url.indexOf('?')); + var splitPath = barePath.split('/'); + + // Any non-cas request will continue down the default + // middlewares. + if (splitPath[1] !== '_cas') { + next(); + return; + } + + // get auth token + var credentialToken = splitPath[2]; + if (!credentialToken) { + closePopup(res); + return; + } + + // validate ticket + casTicket(req, credentialToken, function() { + closePopup(res); + }); - // get auth token - var credentialToken = splitPath[2]; - if (!credentialToken) { - closePopup(res); - return; + } catch (err) { + logger.error("Unexpected error : " + err.message); + closePopup(res); } - - // validate ticket - casTicket(req, credentialToken, function() { - closePopup(res); - }); - - } catch (err) { - logger.error("Unexpected error : " + err.message); - closePopup(res); - } }; var casTicket = function (req, token, callback) { - // get configuration - if (!RocketChat.settings.get("CAS_enabled")) { - logger.error("Got ticket validation request, but CAS is not enabled"); - callback(); - } - - // get ticket and validate. - var parsedUrl = url.parse(req.url, true); - var ticketId = parsedUrl.query.ticket; - var baseUrl = RocketChat.settings.get("CAS_base_url"); - logger.debug("Using CAS_base_url: " + baseUrl); - - var cas = new CAS({ - base_url: baseUrl, - service: Meteor.absoluteUrl() + "_cas/" + token - }); - - cas.validate(ticketId, function(err, status, username) { - if (err) { - logger.error("error when trying to validate " + err); - } else { - if (status) { - logger.info("Validated user: " + username); - _casCredentialTokens[token] = { id: username }; - } else { - logger.error("Unable to validate ticket: " + ticketId); - } + // get configuration + if (!RocketChat.settings.get("CAS_enabled")) { + logger.error("Got ticket validation request, but CAS is not enabled"); + callback(); } - callback(); + // get ticket and validate. + var parsedUrl = url.parse(req.url, true); + var ticketId = parsedUrl.query.ticket; + var baseUrl = RocketChat.settings.get("CAS_base_url"); + logger.debug("Using CAS_base_url: " + baseUrl); + + var cas = new CAS({ + base_url: baseUrl, + service: Meteor.absoluteUrl() + "_cas/" + token + }); + + cas.validate(ticketId, function(err, status, username) { + if (err) { + logger.error("error when trying to validate " + err); + } else { + if (status) { + logger.info("Validated user: " + username); + _casCredentialTokens[token] = { id: username }; + } else { + logger.error("Unable to validate ticket: " + ticketId); + } + } + + callback(); }); return; @@ -141,20 +141,20 @@ var casTicket = function (req, token, callback) { }); var _hasCredential = function(credentialToken) { - return _.has(_casCredentialTokens, credentialToken); + return _.has(_casCredentialTokens, credentialToken); } /* * Retrieve token and delete it to avoid replaying it. */ var _retrieveCredential = function(credentialToken) { - var result = _casCredentialTokens[credentialToken]; - delete _casCredentialTokens[credentialToken]; - return result; + var result = _casCredentialTokens[credentialToken]; + delete _casCredentialTokens[credentialToken]; + return result; } var closePopup = function(res) { - res.writeHead(200, {'Content-Type': 'text/html'}); - var content = ''; - res.end(content, 'utf-8'); + res.writeHead(200, {'Content-Type': 'text/html'}); + var content = ''; + res.end(content, 'utf-8'); } From b80e4b448046e3534888147677d6456008336386 Mon Sep 17 00:00:00 2001 From: Gabriel Engel Date: Thu, 17 Mar 2016 19:50:46 -0300 Subject: [PATCH 10/13] meteor update --- .meteor/versions | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.meteor/versions b/.meteor/versions index 24c68b72eb2..32c1e547cfc 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -40,7 +40,7 @@ ecmascript-runtime@0.2.6 edgee:slingshot@0.7.1 ejson@1.0.7 email@1.0.8 -emojione:emojione@2.1.1 +emojione:emojione@2.1.2 facebook@1.2.2 fastclick@1.0.7 francocatena:status@1.5.1 @@ -101,7 +101,7 @@ mrt:moment@2.8.1 mrt:moment-timezone@0.2.1 mrt:reactive-store@0.0.1 mystor:device-detection@0.2.0 -nimble:restivus@0.8.7 +nimble:restivus@0.8.9 nooitaf:colors@0.0.3 npm-bcrypt@0.7.8_2 npm-mongo@1.4.39_1 @@ -110,11 +110,11 @@ oauth1@1.1.5 oauth2@1.1.5 observe-sequence@1.0.7 ordered-dict@1.0.4 -ostrio:cookies@2.0.1 +ostrio:cookies@2.0.2 pauli:accounts-linkedin@1.2.0 pauli:linkedin@1.2.0 -peerlibrary:aws-sdk@2.0.17_2 -peerlibrary:blocking@0.4.3 +peerlibrary:aws-sdk@2.2.42_1 +peerlibrary:blocking@0.5.2 perak:codemirror@1.2.9 percolate:synced-cron@1.3.0 pntbr:js-yaml-client@0.0.1 @@ -198,19 +198,19 @@ service-configuration@1.0.5 session@1.1.1 sha@1.0.4 simple:highlight.js@1.2.0 -simple:json-routes@2.0.1 +simple:json-routes@2.1.0 smoral:sweetalert@1.1.1 spacebars@1.0.7 spacebars-compiler@1.0.7 srp@1.0.4 standard-minifiers@1.0.2 steffo:meteor-accounts-saml@0.0.1 -tap:i18n@1.7.0 +tap:i18n@1.8.0 templating@1.1.5 templating-tools@1.0.0 tmeasday:crypto-base@3.1.2 tmeasday:crypto-md5@3.1.2 -todda00:friendly-slugs@0.3.6 +todda00:friendly-slugs@0.4.0 tracker@1.0.9 twitter@1.1.5 ui@1.0.8 From df9830cfc6d35b4af76beee8a0e6500dcf99e5d1 Mon Sep 17 00:00:00 2001 From: Gabriel Engel Date: Thu, 17 Mar 2016 19:57:38 -0300 Subject: [PATCH 11/13] reorder env vars --- .docker/develop/Dockerfile | 4 ++-- .docker/latest/Dockerfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.docker/develop/Dockerfile b/.docker/develop/Dockerfile index 81db355aa7f..15aa19a7a0d 100644 --- a/.docker/develop/Dockerfile +++ b/.docker/develop/Dockerfile @@ -22,10 +22,10 @@ WORKDIR /app/bundle # needs a mongoinstance - defaults to container linking with alias 'mongo' ENV MONGO_URL=mongodb://mongo:27017/rocketchat \ + HOME=/tmp \ PORT=3000 \ ROOT_URL=http://localhost:3000 \ - Accounts_AvatarStorePath=/app/uploads \ - HOME=/tmp + Accounts_AvatarStorePath=/app/uploads EXPOSE 3000 diff --git a/.docker/latest/Dockerfile b/.docker/latest/Dockerfile index e5f1ba34462..91e7b43dfd2 100644 --- a/.docker/latest/Dockerfile +++ b/.docker/latest/Dockerfile @@ -22,10 +22,10 @@ WORKDIR /app/bundle # needs a mongoinstance - defaults to container linking with alias 'mongo' ENV MONGO_URL=mongodb://mongo:27017/rocketchat \ + HOME=/tmp \ PORT=3000 \ ROOT_URL=http://localhost:3000 \ - Accounts_AvatarStorePath=/app/uploads \ - HOME=/tmp + Accounts_AvatarStorePath=/app/uploads EXPOSE 3000 From 34f414f682005f74e22d330df58b386b4093f863 Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Thu, 17 Mar 2016 19:22:37 -0400 Subject: [PATCH 12/13] Fix restricted domain registration regex The current regex for checking restricted domains is not escaped and can be easily tricked. For example, if the restricted domain is "example.com", we currently accept "tester@hackedexample.com". This change forces the full domain to be correct, and also escapes it to prevent metacharacters from causing false matches. --- server/lib/accounts.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/accounts.coffee b/server/lib/accounts.coffee index 5379d49a745..b17b60ed0dd 100644 --- a/server/lib/accounts.coffee +++ b/server/lib/accounts.coffee @@ -7,7 +7,7 @@ RocketChat.settings.get 'Accounts_AllowedDomainsList', (_id, value) -> restrictCreationByEmailDomain = (email) -> ret = false for domain in domainWhiteList - if email.match(domain + '$') + if email.match('@' + RegExp.escape(domain) + '$') ret = true break; From 3b615750cb3fc267e15a0565a1c63a8510c7aa3b Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Thu, 17 Mar 2016 19:46:56 -0400 Subject: [PATCH 13/13] Pass restricted domain as string when only one restrictCreationByEmailDomain accepts either a function or a string. When it is a string, it will be used by some of the OAuth integrations (like google) to proactively restrict logins. For my use case this means that employees are automatically asked by google to login with their work credentials instead of first having to select between their personal and work accounts. --- server/lib/accounts.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/accounts.coffee b/server/lib/accounts.coffee index 5379d49a745..6af38abb2fa 100644 --- a/server/lib/accounts.coffee +++ b/server/lib/accounts.coffee @@ -4,7 +4,7 @@ Accounts.config accountsConfig RocketChat.settings.get 'Accounts_AllowedDomainsList', (_id, value) -> domainWhiteList = _.map value.split(','), (domain) -> domain.trim() - restrictCreationByEmailDomain = (email) -> + restrictCreationByEmailDomain = if domainWhiteList.length == 1 then domainWhiteList[0] else (email) -> ret = false for domain in domainWhiteList if email.match(domain + '$')