diff --git a/spec/EmailVerificationToken.spec.js b/spec/EmailVerificationToken.spec.js index 7f8c982333..3b8421e8d3 100644 --- a/spec/EmailVerificationToken.spec.js +++ b/spec/EmailVerificationToken.spec.js @@ -487,6 +487,7 @@ describe("Email Verification Token Expiration: ", () => { var user = new Parse.User(); var sendEmailOptions; var sendVerificationEmailCallCount = 0; + let userBeforeRequest; var emailAdapter = { sendVerificationEmail: options => { sendEmailOptions = options; @@ -509,6 +510,15 @@ describe("Email Verification Token Expiration: ", () => { return user.signUp(); }) .then(() => { + const config = Config.get('test'); + return config.database.find('_User', {username: 'resends_verification_token'}).then((results) => { + return results[0]; + }); + }) + .then((newUser) => { + // store this user before we make our email request + userBeforeRequest = newUser; + expect(sendVerificationEmailCallCount).toBe(1); return requestp.post({ @@ -523,13 +533,25 @@ describe("Email Verification Token Expiration: ", () => { json: true, resolveWithFullResponse: true, simple: false // this promise is only rejected if the call itself failed - }) - .then((response) => { - expect(response.statusCode).toBe(200); - expect(sendVerificationEmailCallCount).toBe(2); - expect(sendEmailOptions).toBeDefined(); - done(); - }); + }); + }) + .then((response) => { + expect(response.statusCode).toBe(200); + expect(sendVerificationEmailCallCount).toBe(2); + expect(sendEmailOptions).toBeDefined(); + + // query for this user again + const config = Config.get('test'); + return config.database.find('_User', {username: 'resends_verification_token'}).then((results) => { + return results[0]; + }); + }) + .then((userAfterRequest) => { + // verify that our token & expiration has been changed for this new request + expect(typeof userAfterRequest).toBe('object'); + expect(userBeforeRequest._email_verify_token).not.toEqual(userAfterRequest._email_verify_token); + expect(userBeforeRequest._email_verify_token_expires_at).not.toEqual(userAfterRequest.__email_verify_token_expires_at); + done(); }) .catch(error => { jfail(error); diff --git a/src/Controllers/UserController.js b/src/Controllers/UserController.js index bf7934c492..76a5066242 100644 --- a/src/Controllers/UserController.js +++ b/src/Controllers/UserController.js @@ -135,13 +135,23 @@ export class UserController extends AdaptableController { }); } + /** + * Regenerates the given user's email verification token + * + * @param user + * @returns {*} + */ + regenerateEmailVerifyToken(user) { + this.setEmailVerifyToken(user); + return this.config.database.update('_User', { username: user.username }, user); + } + resendVerificationEmail(username) { return this.getUserIfNeeded({username: username}).then((aUser) => { if (!aUser || aUser.emailVerified) { throw undefined; } - this.setEmailVerifyToken(aUser); - return this.config.database.update('_User', {username}, aUser).then(() => { + return this.regenerateEmailVerifyToken(aUser).then(() => { this.sendVerificationEmail(aUser); }); }); diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index 86763d7eea..0863f99136 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -268,14 +268,19 @@ export class UsersRouter extends ClassesRouter { throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, `No user found with email ${email}`); } const user = results[0]; + + // remove password field, messes with saving on postgres + delete user.password; if (user.emailVerified) { throw new Parse.Error(Parse.Error.OTHER_CAUSE, `Email ${email} is already verified.`); } const userController = req.config.userController; - userController.sendVerificationEmail(user); - return { response: {} }; + return userController.regenerateEmailVerifyToken(user).then(() => { + userController.sendVerificationEmail(user); + return { response: {} }; + }); }); }