diff --git a/services/web/app/coffee/Features/Email/EmailBuilder.coffee b/services/web/app/coffee/Features/Email/EmailBuilder.coffee index e7b458d444..85a7b9f86b 100644 --- a/services/web/app/coffee/Features/Email/EmailBuilder.coffee +++ b/services/web/app/coffee/Features/Email/EmailBuilder.coffee @@ -130,6 +130,17 @@ templates.verifyEmailToJoinTeam = CTAEmailTemplate({ ctaURL: (opts) -> opts.acceptInviteUrl }) +templates.dropboxUnlinkedDuplicate = CTAEmailTemplate({ + subject: () -> "Your Dropbox Account has been Unlinked - #{settings.appName}" + message: (opts) -> """ +Our automated systems have detected that your Dropbox account was linked to more than one Overleaf accounts. This should not have been allowed and might be causing issues with the Dropbox sync feature. + +We have now unlinked all your Dropbox and Overleaf Accounts. To ensure your project will keep syncing you can link your Dropbox account to the Overleaf account of your choice now. +""" + ctaText: () -> "Link Dropbox Account" + ctaURL: (opts) -> "#{settings.siteUrl}/user/settings" +}) + templates.testEmail = CTAEmailTemplate({ subject: () -> "A Test Email from #{settings.appName}" title: () -> "A Test Email from #{settings.appName}" diff --git a/services/web/scripts/dropbox/remove_duplicate_uids.js b/services/web/scripts/dropbox/remove_duplicate_uids.js new file mode 100644 index 0000000000..078b5a189d --- /dev/null +++ b/services/web/scripts/dropbox/remove_duplicate_uids.js @@ -0,0 +1,72 @@ +const { db } = require('../../app/js/infrastructure/mongojs') +const DropboxHandler = require('../../modules/dropbox/app/js/DropboxHandler') +const EmailHandler = require('../../app/js/Features/Email/EmailHandler') +const async = require('async') +const minimist = require('minimist') + +const argv = minimist(process.argv.slice(2)) +const commit = argv.commit !== undefined + +if (!commit) { + console.log('DOING DRY RUN. TO SAVE CHANGES PASS --commit') +} + +db.users.aggregate( + [ + { + $group: { + // group by Dropbox access token uid and count distinct users + _id: '$dropbox.access_token.uid', + count: { $sum: 1 }, + _ids: { $addToSet: '$_id' } + } + }, + { + $match: { + // select only uids userd more than once + _id: { $ne: null }, + count: { $gt: 1 } + } + }, + { + $project: { + // filter output + _id: false, + dropbox_uid: '$_id', + _ids: '$_ids' + } + } + ], + { allowDiskUse: true }, + function(error, results) { + if (error) throw error + console.log('FOUND ' + results.length + ' DUPLICATES') + async.mapSeries(results, removeDuplicates, function(error) { + if (error) throw error + console.log('DONE') + process.exit() + }) + } +) + +function removeDuplicates(duplicate, callback) { + async.mapSeries(duplicate._ids, unlinkUser, function(error) { + callback(error) + }) +} + +function unlinkUser(_id, callback) { + db.users.findOne({ _id: _id }, function(error, user) { + if (error) return callback(error) + console.log('UNLINKING USER ' + _id + ' (' + user.email + ')') + if (!commit) return callback() + DropboxHandler.unlinkAccount(_id, function(error) { + if (error) return callback(error) + EmailHandler.sendEmail( + 'dropboxUnlinkedDuplicate', + { to: user.email }, + callback + ) + }) + }) +}