mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-13 04:37:36 +01:00
* downcase updating an email to be consistent with creating * add tests to ensure downcase of email for create/update * create migration to downcase existing User objects * delete 'only' * change gmail to example * add trailing comma from lint error * search for emails with at least one capital letter * fix query in order to search for any email with at least one capital letter * batch process effected users with at least one capital in email * update script for batch process effected users
This commit is contained in:
committed by
Matteo Pagliazzi
parent
b9a6d9ceec
commit
04b4912d59
88
migrations/20171211_sanitize_emails.js
Normal file
88
migrations/20171211_sanitize_emails.js
Normal file
@@ -0,0 +1,88 @@
|
||||
var migrationName = '20171211_sanitize_emails.js';
|
||||
var authorName = 'Julius'; // in case script author needs to know when their ...
|
||||
var authorUuid = 'dd16c270-1d6d-44bd-b4f9-737342e79be6'; //... own data is done
|
||||
|
||||
/*
|
||||
User creation saves email as lowercase, but updating an email did not.
|
||||
Run this script to ensure all lowercased emails in db AFTER fix for updating emails is implemented.
|
||||
This will fix inconsistent querying for an email when attempting to password reset.
|
||||
*/
|
||||
|
||||
var monk = require('monk');
|
||||
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
var dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
function processUsers(lastId) {
|
||||
var query = {
|
||||
'auth.local.email': /[A-Z]/
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId
|
||||
}
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data)
|
||||
'auth.local.email'
|
||||
],
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch(function (err) {
|
||||
console.log(err);
|
||||
return exiting(1, 'ERROR! ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
var progressCount = 1000;
|
||||
var count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
displayData();
|
||||
return;
|
||||
}
|
||||
|
||||
var userPromises = users.map(updateUser);
|
||||
var lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPromises)
|
||||
.then(function () {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
var push;
|
||||
var set = {
|
||||
'auth.local.email': user.auth.local.email.toLowerCase()
|
||||
};
|
||||
|
||||
dbUsers.update({_id: user._id}, {$set: set});
|
||||
|
||||
if (count % progressCount == 0) console.warn(count + ' ' + user._id);
|
||||
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||
}
|
||||
|
||||
function displayData() {
|
||||
console.warn('\n' + count + ' users processed\n');
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting(code, msg) {
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) { msg = 'ERROR!'; }
|
||||
if (msg) {
|
||||
if (code) { console.error(msg); }
|
||||
else { console.log( msg); }
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
module.exports = processUsers;
|
||||
@@ -357,6 +357,21 @@ describe('POST /user/auth/local/register', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('sanitizes email params to a lowercase string before creating the user', async () => {
|
||||
let username = generateRandomUserName();
|
||||
let email = 'ISANEmAiL@ExAmPle.coM';
|
||||
let password = 'password';
|
||||
|
||||
let user = await api.post('/user/auth/local/register', {
|
||||
username,
|
||||
email,
|
||||
password,
|
||||
confirmPassword: password,
|
||||
});
|
||||
|
||||
expect(user.auth.local.email).to.equal(email.toLowerCase());
|
||||
});
|
||||
|
||||
it('fails on a habitica.com email', async () => {
|
||||
let username = generateRandomUserName();
|
||||
let email = `${username}@habitica.com`;
|
||||
|
||||
@@ -13,7 +13,7 @@ import nconf from 'nconf';
|
||||
const ENDPOINT = '/user/auth/update-email';
|
||||
|
||||
describe('PUT /user/auth/update-email', () => {
|
||||
let newEmail = 'some-new-email_2@example.net';
|
||||
let newEmail = 'SOmE-nEw-emAIl_2@example.net';
|
||||
let oldPassword = 'password'; // from habitrpg/test/helpers/api-integration/v3/object-generators.js
|
||||
|
||||
context('Local Authenticaion User', async () => {
|
||||
@@ -53,14 +53,15 @@ describe('PUT /user/auth/update-email', () => {
|
||||
});
|
||||
|
||||
it('changes email if new email and existing password are provided', async () => {
|
||||
let lowerCaseNewEmail = newEmail.toLowerCase();
|
||||
let response = await user.put(ENDPOINT, {
|
||||
newEmail,
|
||||
password: oldPassword,
|
||||
});
|
||||
expect(response).to.eql({ email: 'some-new-email_2@example.net' });
|
||||
expect(response.email).to.eql(lowerCaseNewEmail);
|
||||
|
||||
await user.sync();
|
||||
expect(user.auth.local.email).to.eql(newEmail);
|
||||
expect(user.auth.local.email).to.eql(lowerCaseNewEmail);
|
||||
});
|
||||
|
||||
it('rejects if email is already taken', async () => {
|
||||
|
||||
@@ -629,7 +629,7 @@ api.updateEmail = {
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let emailAlreadyInUse = await User.findOne({
|
||||
'auth.local.email': req.body.newEmail,
|
||||
'auth.local.email': req.body.newEmail.toLowerCase(),
|
||||
}).select({_id: 1}).lean().exec();
|
||||
|
||||
if (emailAlreadyInUse) throw new NotAuthorized(res.t('cannotFulfillReq', { techAssistanceEmail: TECH_ASSISTANCE_EMAIL }));
|
||||
@@ -643,7 +643,7 @@ api.updateEmail = {
|
||||
await passwordUtils.convertToBcrypt(user, password);
|
||||
}
|
||||
|
||||
user.auth.local.email = req.body.newEmail;
|
||||
user.auth.local.email = req.body.newEmail.toLowerCase();
|
||||
await user.save();
|
||||
|
||||
return res.respond(200, { email: user.auth.local.email });
|
||||
|
||||
Reference in New Issue
Block a user