diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 28d6c77be58a..43f7c088143a 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -807,6 +807,7 @@ "IMAP_intercepter_Not_running": "IMAP intercepter Not running", "Impersonate_user": "Impersonate User", "Impersonate_user_description": "When enabled, integration posts as the user that triggered integration", + "Import": "Import", "Importer_Archived": "Archived", "Importer_CSV_Information": "The CSV importer requires a specific format, please read the documentation for how to structure your zip file:", "Importer_done": "Importing complete!", @@ -1667,6 +1668,7 @@ "SSL": "SSL", "Star_Message": "Star Message", "Starred_Messages": "Starred Messages", + "Start": "Start", "Start_audio_call": "Start audio call", "Start_Chat": "Start Chat", "Start_of_conversation": "Start of conversation", diff --git a/packages/rocketchat-importer-slack/server.js b/packages/rocketchat-importer-slack/server.js index ea12a7928bdb..c48d5a3bc636 100644 --- a/packages/rocketchat-importer-slack/server.js +++ b/packages/rocketchat-importer-slack/server.js @@ -6,37 +6,48 @@ Importer.Slack = class extends Importer.Base { this.bots = {}; this.logger.debug('Constructed a new Slack Importer.'); } + prepare(dataURI, sentContentType, fileName) { super.prepare(dataURI, sentContentType, fileName); - const {image/*, contentType*/} = RocketChatFile.dataURIParse(dataURI); + + const { image } = RocketChatFile.dataURIParse(dataURI); const zip = new this.AdmZip(new Buffer(image, 'base64')); const zipEntries = zip.getEntries(); + let tempChannels = []; let tempUsers = []; const tempMessages = {}; + zipEntries.forEach(entry => { if (entry.entryName.indexOf('__MACOSX') > -1) { return this.logger.debug(`Ignoring the file: ${ entry.entryName }`); } + if (entry.entryName === 'channels.json') { this.updateProgress(Importer.ProgressStep.PREPARING_CHANNELS); tempChannels = JSON.parse(entry.getData().toString()).filter(channel => channel.creator != null); return; } + if (entry.entryName === 'users.json') { this.updateProgress(Importer.ProgressStep.PREPARING_USERS); tempUsers = JSON.parse(entry.getData().toString()); - return tempUsers.forEach(user => { + + tempUsers.forEach(user => { if (user.is_bot) { this.bots[user.profile.bot_id] = user; } }); + + return; } + if (!entry.isDirectory && entry.entryName.indexOf('/') > -1) { const item = entry.entryName.split('/'); const channelName = item[0]; const msgGroupData = item[1].split('.')[0]; tempMessages[channelName] = tempMessages[channelName] || {}; + try { tempMessages[channelName][msgGroupData] = JSON.parse(entry.getData().toString()); } catch (error) { @@ -65,10 +76,11 @@ Importer.Slack = class extends Importer.Base { Object.keys(tempMessages).forEach(channel => { const messagesObj = tempMessages[channel]; this.messages[channel] = this.messages[channel] || {}; + Object.keys(messagesObj).forEach(date => { const msgs = messagesObj[date]; messagesCount += msgs.length; - this.updateRecord({ 'messagesstatus': '#{channel}/#{date}' }); + this.updateRecord({ 'messagesstatus': `${ channel }/${ date }` }); if (Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize) { const tmp = Importer.Base.getBSONSafeArraysFromAnArray(msgs); Object.keys(tmp).forEach(i => { @@ -82,6 +94,7 @@ Importer.Slack = class extends Importer.Base { } }); }); + this.updateRecord({ 'count.messages': messagesCount, 'messagesstatus': null }); this.addCountToTotal(messagesCount); if ([tempUsers.length, tempChannels.length, messagesCount].some(e => e === 0)) { @@ -99,6 +112,7 @@ Importer.Slack = class extends Importer.Base { startImport(importSelection) { super.startImport(importSelection); const start = Date.now(); + Object.keys(importSelection.users).forEach(key => { const user = importSelection.users[key]; Object.keys(this.users.users).forEach(k => { @@ -109,6 +123,7 @@ Importer.Slack = class extends Importer.Base { }); }); this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }}); + Object.keys(importSelection.channels).forEach(key => { const channel = importSelection.channels[key]; Object.keys(this.channels.channels).forEach(k => { @@ -119,283 +134,310 @@ Importer.Slack = class extends Importer.Base { }); }); this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }}); + const startedByUserId = Meteor.userId(); Meteor.defer(() => { - this.updateProgress(Importer.ProgressStep.IMPORTING_USERS); - this.users.users.forEach(user => { - if (!user.do_import) { - return; - } - Meteor.runAsUser(startedByUserId, () => { - const existantUser = RocketChat.models.Users.findOneByEmailAddress(user.profile.email) || RocketChat.models.Users.findOneByUsername(user.name); - if (existantUser) { - user.rocketId = existantUser._id; - RocketChat.models.Users.update({ _id: user.rocketId }, { $addToSet: { importIds: user.id } }); - this.userTags.push({ - slack: `<@${ user.id }>`, - slackLong: `<@${ user.id }|${ user.name }>`, - rocket: `@${ existantUser.username }` - }); - } else { - const userId = user.profile.email ? Accounts.createUser({ email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() }) : Accounts.createUser({ username: user.name, password: Date.now() + user.name, joinDefaultChannelsSilenced: true }); - Meteor.runAsUser(userId, () => { - Meteor.call('setUsername', user.name, {joinDefaultChannelsSilenced: true}); - const url = user.profile.image_original || user.profile.image_512; - try { - Meteor.call('setAvatarFromService', url, undefined, 'url'); - } catch (error) { - this.logger.warn(`Failed to set ${ user.name }'s avatar from url ${ url }`); - console.log(`Failed to set ${ user.name }'s avatar from url ${ url }`); - } - // Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600 - if (user.tz_offset) { - Meteor.call('userSetUtcOffset', user.tz_offset / 3600); + try { + this.updateProgress(Importer.ProgressStep.IMPORTING_USERS); + this.users.users.forEach(user => { + if (!user.do_import) { + return; + } + + Meteor.runAsUser(startedByUserId, () => { + const existantUser = RocketChat.models.Users.findOneByEmailAddress(user.profile.email) || RocketChat.models.Users.findOneByUsername(user.name); + if (existantUser) { + user.rocketId = existantUser._id; + RocketChat.models.Users.update({ _id: user.rocketId }, { $addToSet: { importIds: user.id } }); + this.userTags.push({ + slack: `<@${ user.id }>`, + slackLong: `<@${ user.id }|${ user.name }>`, + rocket: `@${ existantUser.username }` + }); + } else { + const userId = user.profile.email ? Accounts.createUser({ email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() }) : Accounts.createUser({ username: user.name, password: Date.now() + user.name, joinDefaultChannelsSilenced: true }); + Meteor.runAsUser(userId, () => { + Meteor.call('setUsername', user.name, { joinDefaultChannelsSilenced: true }); + + const url = user.profile.image_original || user.profile.image_512; + try { + Meteor.call('setAvatarFromService', url, undefined, 'url'); + } catch (error) { + this.logger.warn(`Failed to set ${ user.name }'s avatar from url ${ url }`); + console.log(`Failed to set ${ user.name }'s avatar from url ${ url }`); + } + + // Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600 + if (user.tz_offset) { + Meteor.call('userSetUtcOffset', user.tz_offset / 3600); + } + }); + + RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: user.id } }); + + if (user.profile.real_name) { + RocketChat.models.Users.setName(userId, user.profile.real_name); } - }); - RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: user.id } }); + //Deleted users are 'inactive' users in Rocket.Chat + if (user.deleted) { + Meteor.call('setUserActiveStatus', userId, false); + } - 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); + user.rocketId = userId; + this.userTags.push({ + slack: `<@${ user.id }>`, + slackLong: `<@${ user.id }|${ user.name }>`, + rocket: `@${ user.name }` + }); } - //TODO: Maybe send emails? - user.rocketId = userId; - this.userTags.push({ - slack: `<@${ user.id }>`, - slackLong: `<@${ user.id }|${ user.name }>`, - rocket: `@${ user.name }` - }); - } - this.addCountCompleted(1); + this.addCountCompleted(1); + }); }); - }); - this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }}); - this.updateProgress(Importer.ProgressStep.IMPORTING_CHANNELS); - this.channels.channels.forEach(channel => { - if (!channel.do_import) { - return; - } - Meteor.runAsUser (startedByUserId, () => { - const existantRoom = RocketChat.models.Rooms.findOneByName(channel.name); - if (existantRoom || channel.is_general) { - if (channel.is_general && existantRoom && channel.name !== existantRoom.name) { - Meteor.call('saveRoomSettings', 'GENERAL', 'roomName', channel.name); - } - channel.rocketId = channel.is_general ? 'GENERAL' : existantRoom._id; - RocketChat.models.Rooms.update({ _id: channel.rocketId }, { $addToSet: { importIds: channel.id } }); - } else { - const users = channel.members - .reduce((ret, member) => { - if (member !== channel.creator) { - const user = this.getRocketUser(member); - if (user && user.username) { - ret.push(user.username); + this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }}); + + this.updateProgress(Importer.ProgressStep.IMPORTING_CHANNELS); + this.channels.channels.forEach(channel => { + if (!channel.do_import) { + return; + } + + Meteor.runAsUser (startedByUserId, () => { + const existantRoom = RocketChat.models.Rooms.findOneByName(channel.name); + if (existantRoom || channel.is_general) { + if (channel.is_general && existantRoom && channel.name !== existantRoom.name) { + Meteor.call('saveRoomSettings', 'GENERAL', 'roomName', channel.name); + } + + channel.rocketId = channel.is_general ? 'GENERAL' : existantRoom._id; + RocketChat.models.Rooms.update({ _id: channel.rocketId }, { $addToSet: { importIds: channel.id } }); + } else { + const users = channel.members + .reduce((ret, member) => { + if (member !== channel.creator) { + const user = this.getRocketUser(member); + if (user && user.username) { + ret.push(user.username); + } } + return ret; + }, []); + let userId = startedByUserId; + this.users.users.forEach(user => { + if (user.id === channel.creator && user.do_import) { + userId = user.rocketId; } - return ret; - }, []); - let userId = startedByUserId; - this.users.users.forEach(user => { - if (user.id === channel.creator && user.do_import) { - userId = user.rocketId; - } - }); - Meteor.runAsUser(userId, () => { - const returned = Meteor.call('createChannel', channel.name, users); - channel.rocketId = returned.rid; - }); + }); + Meteor.runAsUser(userId, () => { + const returned = Meteor.call('createChannel', channel.name, users); + channel.rocketId = returned.rid; + }); - // @TODO implement model specific function - const roomUpdate = { - ts: new Date(channel.created * 1000) - }; - if (!_.isEmpty(channel.topic && channel.topic.value)) { - roomUpdate.topic = channel.topic.value; - } - if (!_.isEmpty(channel.purpose && channel.purpose.value)) { - roomUpdate.description = channel.purpose.value; + // @TODO implement model specific function + const roomUpdate = { + ts: new Date(channel.created * 1000) + }; + if (!_.isEmpty(channel.topic && channel.topic.value)) { + roomUpdate.topic = channel.topic.value; + } + if (!_.isEmpty(channel.purpose && channel.purpose.value)) { + roomUpdate.description = channel.purpose.value; + } + RocketChat.models.Rooms.update({ _id: channel.rocketId }, { $set: roomUpdate, $addToSet: { importIds: channel.id } }); } - RocketChat.models.Rooms.update({ _id: channel.rocketId }, { $set: roomUpdate, $addToSet: { importIds: channel.id } }); - } - this.addCountCompleted(1); + this.addCountCompleted(1); + }); }); - }); - this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }}); - const missedTypes = {}; - const ignoreTypes = { 'bot_add': true, 'file_comment': true, 'file_mention': true }; - this.updateProgress(Importer.ProgressStep.IMPORTING_MESSAGES); - Object.keys(this.messages).forEach(channel => { - const messagesObj = this.messages[channel]; - - Meteor.runAsUser(startedByUserId, () =>{ - const slackChannel = this.getSlackChannelFromName(channel); - if (!slackChannel || !slackChannel.do_import) { return; } - const room = RocketChat.models.Rooms.findOneById(slackChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } }); - Object.keys(messagesObj).forEach(date => { - const msgs = messagesObj[date]; - msgs.messages.forEach(message => { - this.updateRecord({ 'messagesstatus': '#{channel}/#{date}.#{msgs.messages.length}' }); - const msgDataDefaults ={ - _id: `slack-${ slackChannel.id }-${ message.ts.replace(/\./g, '-') }`, - ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) - }; - if (message.type === 'message') { - if (message.subtype) { - if (message.subtype === 'channel_join') { - if (this.getRocketUser(message.user)) { - RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(room._id, this.getRocketUser(message.user), msgDataDefaults); - } - } else if (message.subtype === 'channel_leave') { - if (this.getRocketUser(message.user)) { - RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(room._id, this.getRocketUser(message.user), msgDataDefaults); - } - } else if (message.subtype === 'me_message') { - const msgObj = { - ...msgDataDefaults, - msg: `_${ this.convertSlackMessageToRocketChat(message.text) }_` - }; - RocketChat.sendMessage(this.getRocketUser(message.user), msgObj, room, true); - } else if (message.subtype === 'bot_message' || message.subtype === 'slackbot_response') { - const botUser = RocketChat.models.Users.findOneById('rocket.cat', { fields: { username: 1 }}); - const botUsername = this.bots[message.bot_id] ? this.bots[message.bot_id].name : message.username; - const msgObj = { - ...msgDataDefaults, - msg: this.convertSlackMessageToRocketChat(message.text), - rid: room._id, - bot: true, - attachments: message.attachments, - username: botUsername || undefined - }; - - if (message.edited) { - msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000); - const editedBy = this.getRocketUser(message.edited.user); - if (editedBy) { - msgObj.editedBy = { - _id: editedBy._id, - username: editedBy.username - }; - } - } + this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }}); - if (message.icons) { - msgObj.emoji = message.icons.emoji; - } - RocketChat.sendMessage(botUser, msgObj, room, true); - } else if (message.subtype === 'channel_purpose') { - if (this.getRocketUser(message.user)) { - RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_description', room._id, message.purpose, this.getRocketUser(message.user), msgDataDefaults); - } - } else if (message.subtype === 'channel_topic') { - if (this.getRocketUser(message.user)) { - RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', room._id, message.topic, this.getRocketUser(message.user), msgDataDefaults); - } - } else if (message.subtype === 'channel_name') { - if (this.getRocketUser(message.user)) { - RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser(room._id, message.name, this.getRocketUser(message.user), msgDataDefaults); + const missedTypes = {}; + const ignoreTypes = { 'bot_add': true, 'file_comment': true, 'file_mention': true }; + this.updateProgress(Importer.ProgressStep.IMPORTING_MESSAGES); + Object.keys(this.messages).forEach(channel => { + const messagesObj = this.messages[channel]; + + Meteor.runAsUser(startedByUserId, () =>{ + const slackChannel = this.getSlackChannelFromName(channel); + if (!slackChannel || !slackChannel.do_import) { return; } + const room = RocketChat.models.Rooms.findOneById(slackChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } }); + Object.keys(messagesObj).forEach(date => { + const msgs = messagesObj[date]; + msgs.messages.forEach(message => { + this.updateRecord({ 'messagesstatus': `${ channel }/${ date }.${ msgs.messages.length }` }); + const msgDataDefaults ={ + _id: `slack-${ slackChannel.id }-${ message.ts.replace(/\./g, '-') }`, + ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) + }; + + // Process the reactions + if (message.reactions && message.reactions.length > 0) { + msgDataDefaults.reactions = {}; + + message.reactions.forEach(reaction => { + msgDataDefaults.reactions[reaction.name] = { usernames: [] }; + + reaction.users.forEach(u => { + const rcUser = this.getRocketUser(u); + if (!rcUser) { return; } + + msgDataDefaults.reactions[reaction.name].usernames.push(rcUser.username); + }); + + if (msgDataDefaults.reactions[reaction.name].usernames.length === 0) { + delete msgDataDefaults.reactions[reaction.name]; } - } else if (message.subtype === 'pinned_item') { - if (message.attachments) { + }); + } + + if (message.type === 'message') { + if (message.subtype) { + if (message.subtype === 'channel_join') { + if (this.getRocketUser(message.user)) { + RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(room._id, this.getRocketUser(message.user), msgDataDefaults); + } + } else if (message.subtype === 'channel_leave') { + if (this.getRocketUser(message.user)) { + RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(room._id, this.getRocketUser(message.user), msgDataDefaults); + } + } else if (message.subtype === 'me_message') { const msgObj = { ...msgDataDefaults, - attachments: [{ - 'text': this.convertSlackMessageToRocketChat(message.attachments[0].text), - 'author_name' : message.attachments[0].author_subname, - 'author_icon' : getAvatarUrlFromUsername(message.attachments[0].author_subname) - }] + msg: `_${ this.convertSlackMessageToRocketChat(message.text) }_` }; - RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('message_pinned', room._id, '', this.getRocketUser(message.user), msgObj); - } else { - //TODO: make this better - this.logger.debug('Pinned item with no attachment, needs work.'); - //RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user), msgDataDefaults - } - } else if (message.subtype === 'file_share') { - if (message.file && message.file.url_private_download !== undefined) { - const details = { - message_id: `slack-${ message.ts.replace(/\./g, '-') }`, - name: message.file.name, - size: message.file.size, - type: message.file.mimetype, - rid: room._id + RocketChat.sendMessage(this.getRocketUser(message.user), msgObj, room, true); + } else if (message.subtype === 'bot_message' || message.subtype === 'slackbot_response') { + const botUser = RocketChat.models.Users.findOneById('rocket.cat', { fields: { username: 1 }}); + const botUsername = this.bots[message.bot_id] ? this.bots[message.bot_id].name : message.username; + const msgObj = { + ...msgDataDefaults, + msg: this.convertSlackMessageToRocketChat(message.text), + rid: room._id, + bot: true, + attachments: message.attachments, + username: botUsername || undefined }; - this.uploadFile(details, message.file.url_private_download, this.getRocketUser(message.user), room, new Date(parseInt(message.ts.split('.')[0]) * 1000)); - } - } else if (!missedTypes[message.subtype] && !ignoreTypes[message.subtype]) { - missedTypes[message.subtype] = message; - } - } else { - const user = this.getRocketUser(message.user); - if (user) { - const msgObj = { - ...msgDataDefaults, - msg: this.convertSlackMessageToRocketChat(message.text), - rid: room._id, - u: { - _id: user._id, - username: user.username + + if (message.edited) { + msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000); + const editedBy = this.getRocketUser(message.edited.user); + if (editedBy) { + msgObj.editedBy = { + _id: editedBy._id, + username: editedBy.username + }; + } + } + + if (message.icons) { + msgObj.emoji = message.icons.emoji; + } + RocketChat.sendMessage(botUser, msgObj, room, true); + } else if (message.subtype === 'channel_purpose') { + if (this.getRocketUser(message.user)) { + RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_description', room._id, message.purpose, this.getRocketUser(message.user), msgDataDefaults); + } + } else if (message.subtype === 'channel_topic') { + if (this.getRocketUser(message.user)) { + RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', room._id, message.topic, this.getRocketUser(message.user), msgDataDefaults); } - }; - - if (message.edited) { - msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000); - const editedBy = this.getRocketUser(message.edited.user); - if (editedBy) { - msgObj.editedBy = { - _id: editedBy._id, - username: editedBy.username + } else if (message.subtype === 'channel_name') { + if (this.getRocketUser(message.user)) { + RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser(room._id, message.name, this.getRocketUser(message.user), msgDataDefaults); + } + } else if (message.subtype === 'pinned_item') { + if (message.attachments) { + const msgObj = { + ...msgDataDefaults, + attachments: [{ + 'text': this.convertSlackMessageToRocketChat(message.attachments[0].text), + 'author_name' : message.attachments[0].author_subname, + 'author_icon' : getAvatarUrlFromUsername(message.attachments[0].author_subname) + }] + }; + RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('message_pinned', room._id, '', this.getRocketUser(message.user), msgObj); + } else { + //TODO: make this better + this.logger.debug('Pinned item with no attachment, needs work.'); + //RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user), msgDataDefaults + } + } else if (message.subtype === 'file_share') { + if (message.file && message.file.url_private_download !== undefined) { + const details = { + message_id: `slack-${ message.ts.replace(/\./g, '-') }`, + name: message.file.name, + size: message.file.size, + type: message.file.mimetype, + rid: room._id }; + this.uploadFile(details, message.file.url_private_download, this.getRocketUser(message.user), room, new Date(parseInt(message.ts.split('.')[0]) * 1000)); } + } else if (!missedTypes[message.subtype] && !ignoreTypes[message.subtype]) { + missedTypes[message.subtype] = message; } + } else { + const user = this.getRocketUser(message.user); + if (user) { + const msgObj = { + ...msgDataDefaults, + msg: this.convertSlackMessageToRocketChat(message.text), + rid: room._id, + u: { + _id: user._id, + username: user.username + } + }; + + if (message.edited) { + msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000); + const editedBy = this.getRocketUser(message.edited.user); + if (editedBy) { + msgObj.editedBy = { + _id: editedBy._id, + username: editedBy.username + }; + } + } - RocketChat.sendMessage(this.getRocketUser(message.user), msgObj, room, true); + try { + RocketChat.sendMessage(this.getRocketUser(message.user), msgObj, room, true); + } catch (e) { + this.logger.warn(`Failed to import the message: ${ msgDataDefaults._id }`); + } + } } } - } - - // Process the reactions - if (RocketChat.models.Messages.findOneById(msgDataDefaults._id) && message.reactions && message.reactions.length > 0) { - message.reactions.forEach(reaction => { - reaction.users.forEach(u => { - const rcUser = this.getRocketUser(u); - if (!rcUser) { return; } - Meteor.runAsUser(rcUser._id, () => Meteor.call('setReaction', `:${ reaction.name }:`, msgDataDefaults._id)); - }); - }); - } - this.addCountCompleted(1); + this.addCountCompleted(1); + }); }); }); }); - }); - - - if (!_.isEmpty(missedTypes)) { - console.log('Missed import types:', missedTypes); - } - this.updateProgress(Importer.ProgressStep.FINISHING); - - this.channels.channels.forEach(channel => { - if (channel.do_import && channel.is_archived) { - Meteor.runAsUser(startedByUserId, function() { - Meteor.call('archiveRoom', channel.rocketId); - }); + if (!_.isEmpty(missedTypes)) { + console.log('Missed import types:', missedTypes); } - }); - this.updateProgress(Importer.ProgressStep.DONE); - const timeTook = Date.now() - start; + this.updateProgress(Importer.ProgressStep.FINISHING); - this.logger.log(`Import took ${ timeTook } milliseconds.`); + this.channels.channels.forEach(channel => { + if (channel.do_import && channel.is_archived) { + Meteor.runAsUser(startedByUserId, function() { + Meteor.call('archiveRoom', channel.rocketId); + }); + } + }); + this.updateProgress(Importer.ProgressStep.DONE); + const timeTook = Date.now() - start; + + this.logger.log(`Import took ${ timeTook } milliseconds.`); + } catch (e) { + this.logger.error(e); + this.updateProgress(Importer.ProgressStep.ERROR); + } }); + return this.getProgress(); } getSlackChannelFromName(channelName) { diff --git a/packages/rocketchat-importer/client/admin/adminImport.html b/packages/rocketchat-importer/client/admin/adminImport.html index 3e22cbcbc29d..73977662772c 100644 --- a/packages/rocketchat-importer/client/admin/adminImport.html +++ b/packages/rocketchat-importer/client/admin/adminImport.html @@ -3,30 +3,26 @@
{{> burger}}

- Import + {{_ "Import"}}

{{#unless isAdmin}} -

You are not authorized to view this page.

+

{{_ "You_are_not_authorized_to_view_this_page"}}

{{else}} - {{#if isImporters}}
{{#each importers}}
-

{{name}}

+

{{ name }}

{{getDescription .}}
- +
{{/each}}
- {{else}} - No Importers Available - {{/if}} {{/unless}}
diff --git a/packages/rocketchat-importer/client/admin/adminImport.js b/packages/rocketchat-importer/client/admin/adminImport.js index 9bfd1e34a4c7..fde895bf7f9b 100644 --- a/packages/rocketchat-importer/client/admin/adminImport.js +++ b/packages/rocketchat-importer/client/admin/adminImport.js @@ -3,9 +3,6 @@ Template.adminImport.helpers({ isAdmin() { return RocketChat.authz.hasRole(Meteor.userId(), 'admin'); }, - isImporters() { - return Object.keys(Importer.Importers).length > 0; - }, getDescription(importer) { return TAPi18n.__('Importer_From_Description', { from: importer.name }); }, @@ -22,12 +19,15 @@ Template.adminImport.helpers({ Template.adminImport.events({ 'click .start-import'() { const importer = this; - return Meteor.call('setupImporter', importer.key, function(error) { + + Meteor.call('setupImporter', importer.key, function(error) { if (error) { console.log(t('importer_setup_error'), importer.key, error); - return handleError(error); + handleError(error); + return; } - return FlowRouter.go(`/admin/import/prepare/${ importer.key }`); + + FlowRouter.go(`/admin/import/prepare/${ importer.key }`); }); } }); diff --git a/packages/rocketchat-importer/client/admin/adminImportPrepare.html b/packages/rocketchat-importer/client/admin/adminImportPrepare.html index 82efec25c976..346ff050842b 100644 --- a/packages/rocketchat-importer/client/admin/adminImportPrepare.html +++ b/packages/rocketchat-importer/client/admin/adminImportPrepare.html @@ -9,7 +9,7 @@

{{#unless isAdmin}} -

You are not authorized to view this page.

+

{{_ "You_are_not_authorized_to_view_this_page"}}

{{else}}
diff --git a/packages/rocketchat-importer/client/admin/adminImportPrepare.js b/packages/rocketchat-importer/client/admin/adminImportPrepare.js index bdc11eb442f7..f47d996000db 100644 --- a/packages/rocketchat-importer/client/admin/adminImportPrepare.js +++ b/packages/rocketchat-importer/client/admin/adminImportPrepare.js @@ -36,7 +36,7 @@ Template.adminImportPrepare.helpers({ Template.adminImportPrepare.events({ 'change .import-file-input'(event, template) { const importer = this; - if (!importer.key) { return; } + if (!importer || !importer.key) { return; } const e = event.originalEvent || event; let { files } = e.target; @@ -44,13 +44,13 @@ Template.adminImportPrepare.events({ files = (e.dataTransfer != null ? e.dataTransfer.files : undefined) || []; } - return Array.from(files).map((blob) => { + return Array.from(files).map((file) => { template.preparing.set(true); const reader = new FileReader(); - reader.readAsDataURL(blob); + reader.readAsDataURL(file); reader.onloadend = () => { - Meteor.call('prepareImport', importer.key, reader.result, blob.type, blob.name, function(error, data) { + Meteor.call('prepareImport', importer.key, reader.result, file.type, file.name, function(error, data) { if (error) { toastr.error(t('Invalid_Import_File_Type')); template.preparing.set(false); @@ -84,7 +84,6 @@ Template.adminImportPrepare.events({ 'click .button.start'(event, template) { const btn = this; $(btn).prop('disabled', true); - // const importer = this; for (const user of Array.from(template.users.get())) { user.do_import = $(`[name=${ user.user_id }]`).is(':checked'); } @@ -93,12 +92,12 @@ Template.adminImportPrepare.events({ channel.do_import = $(`[name=${ channel.channel_id }]`).is(':checked'); } - return Meteor.call('startImport', FlowRouter.getParam('importer'), { users: template.users.get(), channels: template.channels.get() }, function(error) { + Meteor.call('startImport', FlowRouter.getParam('importer'), { users: template.users.get(), channels: template.channels.get() }, function(error) { if (error) { console.warn('Error on starting the import:', error); - return handleError(error); + handleError(error); } else { - return FlowRouter.go(`/admin/import/progress/${ FlowRouter.getParam('importer') }`); + FlowRouter.go(`/admin/import/progress/${ FlowRouter.getParam('importer') }`); } }); }, diff --git a/packages/rocketchat-importer/server/classes/ImporterBase.js b/packages/rocketchat-importer/server/classes/ImporterBase.js index 38420f695863..84422a3d81d2 100644 --- a/packages/rocketchat-importer/server/classes/ImporterBase.js +++ b/packages/rocketchat-importer/server/classes/ImporterBase.js @@ -61,17 +61,22 @@ Importer.Base = class Base { this.addCountCompleted = this.addCountCompleted.bind(this); this.updateRecord = this.updateRecord.bind(this); this.uploadFile = this.uploadFile.bind(this); + this.name = name; this.description = description; this.mimeType = mimeType; + this.logger = new Logger(`${ this.name } Importer`, {}); this.progress = new Importer.Progress(this.name); this.collection = Importer.RawImports; + const importId = Importer.Imports.insert({ 'type': this.name, 'ts': Date.now(), 'status': this.progress.step, 'valid': true, 'user': Meteor.user()._id }); this.importRecord = Importer.Imports.findOne(importId); + this.users = {}; this.channels = {}; this.messages = {}; + this.oldSettings = {}; } // Takes the uploaded file and extracts the users, channels, and messages from it. @@ -89,6 +94,7 @@ Importer.Base = class Base { if (!fileType || (fileType.mime !== this.mimeType)) { this.logger.warn(`Invalid file uploaded for the ${ this.name } importer.`); + this.updateProgress(Importer.ProgressStep.ERROR); throw new Meteor.Error('error-invalid-file-uploaded', `Invalid file uploaded to import ${ this.name } data from.`, { step: 'prepare' }); } @@ -137,6 +143,21 @@ Importer.Base = class Base { updateProgress(step) { this.progress.step = step; + switch (step) { + case Importer.ProgressStep.IMPORTING_STARTED: + this.oldSettings.Accounts_AllowedDomainsList = RocketChat.models.Settings.findOneById('Accounts_AllowedDomainsList').value; + RocketChat.models.Settings.updateValueById('Accounts_AllowedDomainsList', ''); + + this.oldSettings.Accounts_AllowUsernameChange = RocketChat.models.Settings.findOneById('Accounts_AllowUsernameChange').value; + RocketChat.models.Settings.updateValueById('Accounts_AllowUsernameChange', true); + break; + case Importer.ProgressStep.DONE: + case Importer.ProgressStep.ERROR: + RocketChat.models.Settings.updateValueById('Accounts_AllowedDomainsList', this.oldSettings.Accounts_AllowedDomainsList); + RocketChat.models.Settings.updateValueById('Accounts_AllowUsernameChange', this.oldSettings.Accounts_AllowUsernameChange); + break; + } + this.logger.debug(`${ this.name } is now at ${ step }.`); this.updateRecord({ 'status': this.progress.step }); diff --git a/packages/rocketchat-importer/server/methods/startImport.js b/packages/rocketchat-importer/server/methods/startImport.js index 352193e28a2f..4a95e315b442 100644 --- a/packages/rocketchat-importer/server/methods/startImport.js +++ b/packages/rocketchat-importer/server/methods/startImport.js @@ -7,7 +7,11 @@ Meteor.methods({ } if (!RocketChat.authz.hasPermission(Meteor.userId(), 'run-import')) { - throw new Meteor.Error('error-action-not-allowed', 'Importing is not allowed', { method: 'setupImporter'}); + throw new Meteor.Error('error-action-not-allowed', 'Importing is not allowed', { method: 'startImport'}); + } + + if (!name) { + throw new Meteor.Error('error-invalid-importer', `No defined importer by: "${ name }"`, { method: 'startImport' }); } if (Importer.Importers[name] && Importer.Importers[name].importerInstance) { diff --git a/packages/rocketchat-lib/server/methods/filterATAllTag.js b/packages/rocketchat-lib/server/methods/filterATAllTag.js index 801563172f4a..7dac2b3e4cea 100644 --- a/packages/rocketchat-lib/server/methods/filterATAllTag.js +++ b/packages/rocketchat-lib/server/methods/filterATAllTag.js @@ -20,14 +20,10 @@ RocketChat.callbacks.add('beforeSaveMessage', function(message) { }); // Also throw to stop propagation of 'sendMessage'. - throw new Meteor.Error( - 'error-action-not-allowed', - 'Notify all in this room not allowed', - { - method: 'filterATAllTag', - action: 'Notify_all_in_this_room' - } - ); + throw new Meteor.Error('error-action-not-allowed', 'Notify all in this room not allowed', { + method: 'filterATAllTag', + action: 'Notify_all_in_this_room' + }); } } diff --git a/packages/rocketchat-lib/server/methods/setUsername.js b/packages/rocketchat-lib/server/methods/setUsername.js index 9f5af1436a96..041dc6e42766 100644 --- a/packages/rocketchat-lib/server/methods/setUsername.js +++ b/packages/rocketchat-lib/server/methods/setUsername.js @@ -13,7 +13,7 @@ Meteor.methods({ throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setUsername' }); } - if (user.username === username) { + if (user.username === username || (user.username && user.username.toLowerCase() === username.toLowerCase())) { return username; } @@ -28,13 +28,7 @@ Meteor.methods({ throw new Meteor.Error('username-invalid', `${ _.escape(username) } is not a valid username, use only letters, numbers, dots, hyphens and underscores`); } - if (user.username !== undefined) { - if (!username.toLowerCase() === user.username.toLowerCase()) { - if (!RocketChat.checkUsernameAvailability(username)) { - throw new Meteor.Error('error-field-unavailable', `${ _.escape(username) } is already in use :(`, { method: 'setUsername', field: username }); - } - } - } else if (!RocketChat.checkUsernameAvailability(username)) { + if (!RocketChat.checkUsernameAvailability(username)) { throw new Meteor.Error('error-field-unavailable', `${ _.escape(username) } is already in use :(`, { method: 'setUsername', field: username }); }