From d067403959d9ec1c6f925847d869381511442966 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 15 Jun 2016 21:46:17 -0500 Subject: [PATCH] chore: Add migration file for fixing invalid emails --- migrations/20160615_fix_bad_emails.js | 95 +++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 migrations/20160615_fix_bad_emails.js diff --git a/migrations/20160615_fix_bad_emails.js b/migrations/20160615_fix_bad_emails.js new file mode 100644 index 0000000000..0413452e31 --- /dev/null +++ b/migrations/20160615_fix_bad_emails.js @@ -0,0 +1,95 @@ +'use strict'; + +/**************************************** + * Author: Blade Barringer @crookedneighbor + * + * Reason: Old code didn't properly validate email + * addresses, so we have some users in the db + * that do not have valid emails. When a party + * or challenge attempts to save the user, + * the validation fails. This collects + * the bad emails and changes the email to + * @example.com + ***************************************/ + +global.Promise = require('bluebird'); +const TaskQueue = require('cwait').TaskQueue; +const logger = require('./utils/logger'); +const Timer = require('./utils/timer'); +const connectToDb = require('./utils/connect').connectToDb; +const closeDb = require('./utils/connect').closeDb; +const validator = require('validator'); + +const timer = new Timer(); + +const DB_URI = 'mongodb://username:password@dsXXXXXX-a0.mlab.com:XXXXX,dsXXXXXX-a1.mlab.com:XXXXX/habitica?replicaSet=rs-dsXXXXXX'; + +let Users; + +connectToDb(DB_URI).then((db) => { + Users = db.collection('users'); + + return Promise.resolve(); +}) +// cached the lookup as a json file +// .then(findUsersWithBadEmails) +.then(correctEmails) +.then(() => { + timer.stop(); + closeDb(); +}).catch(reportError); + +function reportError (err) { + logger.error('Uh oh, an error occurred'); + closeDb(); + timer.stop(); + throw err; +} + +function findUsersWithBadEmails (users) { + logger.warn('Fetching users with bad emails...'); + + return Users.find({'auth.local.email': {$exists: true}}, ['auth.local.email']).toArray().then((docs) => { + let invalidEmails = docs.filter((user) => { + return !validator.isEmail(user.auth.local.email); + }); + + let result = invalidEmails.map((user) => { + return { _id: user._id, email: user.auth.local.email }; + }); + + logger.warn('number of invalid emails:', invalidEmails.length) + console.log(result) + + return Promise.resolve(invalidEmails); + }); +} + +function updateUserById (user) { + return Users.findOneAndUpdate({ + _id: user._id}, + {$set: {'auth.local.email': user._id + '@example.com'} + }, {returnOriginal: false}) +} + +// cached lookup of bad emails +const emails = require('../email_logs.json'); + +function correctEmails () { + let queue = new TaskQueue(Promise, 300); + + logger.warn('About to update', emails.length, 'user email addresses...'); + + return Promise.map(emails, queue.wrap(updateUserById)).then((result) => { + let updates = result.filter(res => res.lastErrorObject && res.lastErrorObject.updatedExisting) + let failures = result.filter(res => !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); + + logger.warn(updates.length, 'users have been fixed'); + + if (failures.length > 0) { + logger.error(failures.length, 'users could not be found'); + } + + return Promise.resolve(); + }); +}