From 96d98329f17331cf3219821d350292b6b51663df Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 15 May 2014 17:58:25 +0100 Subject: [PATCH] token based reset works --- .../coffee/Features/Email/EmailBuilder.coffee | 21 +++++++++++++--- .../PasswordReset/PasswordResetHandler.coffee | 2 +- .../PasswordReset/TokenGenerator.coffee | 13 +++++----- services/web/app/views/user/login.jade | 2 +- services/web/app/views/user/setPassword.jade | 2 +- services/web/public/coffee/forms.coffee | 24 +++++++++++++------ .../PasswordResetHandlerTests.coffee | 2 +- .../PasswordReset/TokenGeneratorTests.coffee | 8 +++---- 8 files changed, 50 insertions(+), 24 deletions(-) diff --git a/services/web/app/coffee/Features/Email/EmailBuilder.coffee b/services/web/app/coffee/Features/Email/EmailBuilder.coffee index c3704ecafd..710ab089ea 100644 --- a/services/web/app/coffee/Features/Email/EmailBuilder.coffee +++ b/services/web/app/coffee/Features/Email/EmailBuilder.coffee @@ -37,16 +37,30 @@ Henry
ShareLaTeX Co-founder ''' -templates.passwordReset = +templates.passwordResetRequested = subject: _.template "Password Reset - ShareLatex.com" layout: NotificationEmailLayout type:"notification" compiledTemplate: _.template '''

Password Reset

-Your password has been reset, the new password is

<%= newPassword %> +We got a request to reset your ShareLaTeX password.

-please login here and then change your password in your user settings +

+
+
+ + + Reset password + + +
+
+
+ +If you ignore this message, your password won't be changed. +

+If you didn't request a password reset, let us know.

Thank you

@@ -79,6 +93,7 @@ module.exports = buildEmail: (templateName, opts)-> template = templates[templateName] + console.log opts opts.body = template.compiledTemplate(opts) return { subject : template.subject(opts) diff --git a/services/web/app/coffee/Features/PasswordReset/PasswordResetHandler.coffee b/services/web/app/coffee/Features/PasswordReset/PasswordResetHandler.coffee index 31e00b5334..f189641f96 100644 --- a/services/web/app/coffee/Features/PasswordReset/PasswordResetHandler.coffee +++ b/services/web/app/coffee/Features/PasswordReset/PasswordResetHandler.coffee @@ -16,7 +16,7 @@ module.exports = if err then return callback(err) emailOptions = to : email - setNewPasswordUrl : "#{settings.siteUrl}/user/password/set?resetToken=#{token}" + setNewPasswordUrl : "#{settings.siteUrl}/user/password/set?passwordResetToken=#{token}" EmailHandler.sendEmail "passwordResetRequested", emailOptions, callback setNewUserPassword: (token, password, callback)-> diff --git a/services/web/app/coffee/Features/PasswordReset/TokenGenerator.coffee b/services/web/app/coffee/Features/PasswordReset/TokenGenerator.coffee index dd94e4b4a5..f6cb21fe98 100644 --- a/services/web/app/coffee/Features/PasswordReset/TokenGenerator.coffee +++ b/services/web/app/coffee/Features/PasswordReset/TokenGenerator.coffee @@ -4,23 +4,24 @@ rclient = redis.createClient(Settings.redis.web.port, Settings.redis.web.host) rclient.auth(Settings.redis.web.password) uuid = require("node-uuid") -ONE_MIN = 60 * 1000 -ONE_HOUR_IN_MS = ONE_MIN * 60 +ONE_HOUR_IN_S = 60 * 60 + +buildKey = (token)-> return "password_token:#{token}" module.exports = getNewToken: (user_id, callback)-> token = uuid.v4() multi = rclient.multi() - multi.set token, user_id - multi.expire token, ONE_HOUR_IN_MS + multi.set buildKey(token), user_id + multi.expire buildKey(token), ONE_HOUR_IN_S multi.exec (err)-> callback(err, token) getUserIdFromToken: (token, callback)-> multi = rclient.multi() - multi.get token - multi.del token + multi.get buildKey(token) + multi.del buildKey(token) multi.exec (err, results)-> callback err, results[0] diff --git a/services/web/app/views/user/login.jade b/services/web/app/views/user/login.jade index b096dd15ab..b4ff73fd1b 100644 --- a/services/web/app/views/user/login.jade +++ b/services/web/app/views/user/login.jade @@ -20,5 +20,5 @@ block content input.span4#password.required(type='password', name='password', placeholder='********') .actions button.btn-primary.btn.btn-large#login(type='submit') Login - a#passwordReset(href='/user/passwordreset') forgot password? + a#passwordReset(href='/user/password/reset') forgot password? include ../general/small-footer diff --git a/services/web/app/views/user/setPassword.jade b/services/web/app/views/user/setPassword.jade index b07e18cebd..fa17522986 100644 --- a/services/web/app/views/user/setPassword.jade +++ b/services/web/app/views/user/setPassword.jade @@ -7,7 +7,7 @@ block content .page-header h1 Set Password .messageArea - form.validate#passwordReset(method='post') + form.validate#setPasswordReset(method='post') input(type="hidden", name="_csrf", value=csrfToken) .clearfix label(for='xlInput') Password diff --git a/services/web/public/coffee/forms.coffee b/services/web/public/coffee/forms.coffee index 1c2603ea28..6852048745 100644 --- a/services/web/public/coffee/forms.coffee +++ b/services/web/public/coffee/forms.coffee @@ -93,16 +93,26 @@ require [ event.preventDefault() formData = $(this).serialize() $.ajax - url: "/user/passwordReset" + url: "/user/password/reset" type:'POST' data: formData success: (data)-> - if data.message - new Message data.message - else if data.redir - window.location.href = data.redir - else - window.location.href = '/' + new Message text:"You have been sent an email to complete your password reset." + error:(data)-> + new Message type:"error", text:"something went wrong processing your request." + + $('form#setPasswordReset').submit (event)-> + event.preventDefault() + formData = $(this).serialize() + $.ajax + url: "/user/password/set" + type:'POST' + data: formData + success: (data)-> + new Message text:"Your password has been reset" + error:(data)-> + new Message type:"error", text:"something went wrong processing your request." + $('a#deleteUserAccount').click (e)-> diff --git a/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee b/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee index bc0228f4dc..5630898a38 100644 --- a/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee @@ -54,7 +54,7 @@ describe "PasswordResetHandler", -> @EmailHandler.sendEmail.called.should.equal true args = @EmailHandler.sendEmail.args[0] args[0].should.equal "passwordResetRequested" - args[1].setNewPasswordUrl.should.equal "#{@settings.siteUrl}/user/password/set?resetToken=#{@token}" + args[1].setNewPasswordUrl.should.equal "#{@settings.siteUrl}/user/password/set?passwordResetToken=#{@token}" done() diff --git a/services/web/test/UnitTests/coffee/PasswordReset/TokenGeneratorTests.coffee b/services/web/test/UnitTests/coffee/PasswordReset/TokenGeneratorTests.coffee index 39a5dd1733..ae3228c239 100644 --- a/services/web/test/UnitTests/coffee/PasswordReset/TokenGeneratorTests.coffee +++ b/services/web/test/UnitTests/coffee/PasswordReset/TokenGeneratorTests.coffee @@ -39,8 +39,8 @@ describe "TokenGenerator", -> it "should set a new token into redis with a ttl", (done)-> @redisMulti.exec.callsArgWith(0) @TokenGenerator.getNewToken @user_id, (err, token)=> - @redisMulti.set @stubbedToken, @user_id - @redisMulti.expire @stubbedToken, (60*1000)*60 + @redisMulti.set "password_token:#{@stubbedToken}", @user_id + @redisMulti.expire "password_token:#{@stubbedToken}", 60 * 60 done() it "should return if there was an error", (done)-> @@ -56,8 +56,8 @@ describe "TokenGenerator", -> @redisMulti.exec.callsArgWith(0, null, [@user_id]) @TokenGenerator.getUserIdFromToken @stubbedToken, (err, user_id)=> user_id.should.equal @user_id - @redisMulti.get.calledWith(@stubbedToken).should.equal true - @redisMulti.del.calledWith(@stubbedToken).should.equal true + @redisMulti.get.calledWith("password_token:#{@stubbedToken}").should.equal true + @redisMulti.del.calledWith("password_token:#{@stubbedToken}").should.equal true done()