From 64688e661dde9d5c1c26a0b537def240a89a1195 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 15 May 2014 16:50:38 +0100 Subject: [PATCH] written password reset controller --- .../PasswordResetController.coffee | 38 ++++++---- .../PasswordReset/PasswordResetHandler.coffee | 21 +++--- .../PasswordReset/PasswordResetRouter.coffee | 6 +- .../PasswordResetControllerTests.coffee | 71 +++++++++++++++++-- .../PasswordResetHandlerTests.coffee | 10 +-- 5 files changed, 107 insertions(+), 39 deletions(-) diff --git a/services/web/app/coffee/Features/PasswordReset/PasswordResetController.coffee b/services/web/app/coffee/Features/PasswordReset/PasswordResetController.coffee index c88c8f8b3f..36173b4589 100644 --- a/services/web/app/coffee/Features/PasswordReset/PasswordResetController.coffee +++ b/services/web/app/coffee/Features/PasswordReset/PasswordResetController.coffee @@ -1,21 +1,31 @@ +PasswordResetHandler = require("./PasswordResetHandler") module.exports = - requestPasswordReset: -> + renderRequestResetForm: (req, res)-> + res.render "user/passwordReset", + title:"Reset Password" + + requestReset: (req, res)-> + email = req.body.email.trim() + PasswordResetHandler.generateAndEmailResetToken email, (err)-> + if err? + res.send 500 + else + res.send 200 - - # check user exists - # generate token - # send email token link + renderSetPasswordForm: (req, res)-> + res.render "user/setPassword", + title:"Set Password" - renderPasswordResetForm: -> - # check that the token is valid - # render html - - changeUsersPasswordFromReset: -> - # check auth again - # check both passwords match - # set passowrd - # redir to login form + setNewUserPassword: (req, res)-> + {token, password} = req.body + if !password? or password.length < 4 or !token? or token.length == 0 + return res.send 500 + PasswordResetHandler.setNewUserPassword token?.trim(), password?.trim(), (err)-> + if err? + res.send 500 + else + res.send 200 \ No newline at end of file diff --git a/services/web/app/coffee/Features/PasswordReset/PasswordResetHandler.coffee b/services/web/app/coffee/Features/PasswordReset/PasswordResetHandler.coffee index 1c1851778f..31e00b5334 100644 --- a/services/web/app/coffee/Features/PasswordReset/PasswordResetHandler.coffee +++ b/services/web/app/coffee/Features/PasswordReset/PasswordResetHandler.coffee @@ -7,20 +7,19 @@ AuthenticationManager = require("../Authentication/AuthenticationManager") module.exports = - generateAndEmailResetToken:(user_id, callback)-> - async.series - user: (cb)-> UserGetter.getUser _id:user_id, cb - token: (cb)-> TokenGenerator.getNewToken user_id, cb - , (err, results)-> + generateAndEmailResetToken:(email, callback)-> + UserGetter.getUser email:email, (err, user)-> if err then return callback(err) - if !results.user? + if !user? return callback("no user found") - emailOptions = - to : results.user.email - setNewPasswordUrl : "#{settings.siteUrl}/user/password/set?resetToken=#{results.token}" - EmailHandler.sendEmail "passwordResetRequested", emailOptions, callback + TokenGenerator.getNewToken user._id, (err, token)-> + if err then return callback(err) + emailOptions = + to : email + setNewPasswordUrl : "#{settings.siteUrl}/user/password/set?resetToken=#{token}" + EmailHandler.sendEmail "passwordResetRequested", emailOptions, callback - setNewUserPassowrd: (token, password, callback)-> + setNewUserPassword: (token, password, callback)-> TokenGenerator.getUserIdFromToken token, (err, user_id)-> if err then return callback(err) if !user_id? diff --git a/services/web/app/coffee/Features/PasswordReset/PasswordResetRouter.coffee b/services/web/app/coffee/Features/PasswordReset/PasswordResetRouter.coffee index 931d4d3b69..a40b2b5612 100644 --- a/services/web/app/coffee/Features/PasswordReset/PasswordResetRouter.coffee +++ b/services/web/app/coffee/Features/PasswordReset/PasswordResetRouter.coffee @@ -1,9 +1,9 @@ module.exports = apply: (app) -> - app.get '/user/password/reset', PasswordResetController.renderRequestReset - app.post '/user/password/reset', ProjectDownloadsController.requestRest + app.get '/user/password/reset', PasswordResetController.renderRequestResetForm + app.post '/user/password/reset', ProjectDownloadsController.requestReset - app.get '/user/password/set', PasswordResetController.renderSetPassword + app.get '/user/password/set', PasswordResetController.renderSetPasswordForm app.post '/user/password/set', PasswordResetController.setNewUserPassword diff --git a/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetControllerTests.coffee b/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetControllerTests.coffee index 31b31028c7..be053afe38 100644 --- a/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetControllerTests.coffee @@ -11,21 +11,80 @@ describe "PasswordResetController", -> beforeEach -> @settings = {} + @PasswordResetHandler = + generateAndEmailResetToken:sinon.stub() + setNewUserPassword:sinon.stub() @PasswordResetController = SandboxedModule.require modulePath, requires: "settings-sharelatex":@settings + "./PasswordResetHandler":@PasswordResetHandler "logger-sharelatex": log:-> + @email = "bob@bob.com " + @token = "my security token that was emailed to me" + @password = "my new password" + @req = + body: + email:@email + token:@token + password:@password - describe "requestPasswordReset", -> + @res ={} - it "should check the user exists", (done)-> - done() + describe "requestReset", -> - it "should get a unique token and send the email", (done)-> - done() + it "should tell the handler to process that email", (done)-> + @PasswordResetHandler.generateAndEmailResetToken.callsArgWith(1) + @res.send = (code)=> + code.should.equal 200 + @PasswordResetHandler.generateAndEmailResetToken.calledWith(@email.trim()).should.equal true + done() + @PasswordResetController.requestReset @req, @res + + + it "should send a 500 if there is an error", (done)-> + @PasswordResetHandler.generateAndEmailResetToken.callsArgWith(1, "error") + @res.send = (code)=> + code.should.equal 500 + done() + @PasswordResetController.requestReset @req, @res + + describe "setNewUserPassword", -> + + it "should tell the user handler to reset the password", (done)-> + @PasswordResetHandler.setNewUserPassword.callsArgWith(2) + @res.send = (code)=> + code.should.equal 200 + @PasswordResetHandler.setNewUserPassword.calledWith(@token, @password).should.equal true + done() + @PasswordResetController.setNewUserPassword @req, @res + + it "should send a 500 if there is an error", (done)-> + @PasswordResetHandler.setNewUserPassword.callsArgWith(2, "error") + @res.send = (code)=> + code.should.equal 500 + done() + @PasswordResetController.setNewUserPassword @req, @res + + it "should error if there is no password", (done)-> + @req.body.password = "" + @PasswordResetHandler.setNewUserPassword.callsArgWith(2) + @res.send = (code)=> + code.should.equal 500 + @PasswordResetHandler.setNewUserPassword.called.should.equal false + done() + @PasswordResetController.setNewUserPassword @req, @res - + it "should error if there is no password", (done)-> + @req.body.token = "" + @PasswordResetHandler.setNewUserPassword.callsArgWith(2) + @res.send = (code)=> + code.should.equal 500 + @PasswordResetHandler.setNewUserPassword.called.should.equal false + done() + @PasswordResetController.setNewUserPassword @req, @res + + diff --git a/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee b/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee index 885ed40b9d..bc0228f4dc 100644 --- a/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee @@ -40,7 +40,7 @@ describe "PasswordResetHandler", -> it "should check the user exists", (done)-> @UserGetter.getUser.callsArgWith(1) @TokenGenerator.getNewToken.callsArgWith(1) - @PasswordResetHandler.generateAndEmailResetToken @user_id, (err)-> + @PasswordResetHandler.generateAndEmailResetToken @user.email, (err)=> err.should.exists done() @@ -50,7 +50,7 @@ describe "PasswordResetHandler", -> @UserGetter.getUser.callsArgWith(1, null, @user) @TokenGenerator.getNewToken.callsArgWith(1, null, @token) @EmailHandler.sendEmail.callsArgWith(2) - @PasswordResetHandler.generateAndEmailResetToken @user_id, (err)=> + @PasswordResetHandler.generateAndEmailResetToken @user.email, (err)=> @EmailHandler.sendEmail.called.should.equal true args = @EmailHandler.sendEmail.args[0] args[0].should.equal "passwordResetRequested" @@ -58,11 +58,11 @@ describe "PasswordResetHandler", -> done() - describe "setNewUserPassowrd", -> + describe "setNewUserPassword", -> it "should return err if no user id can be found", (done)-> @TokenGenerator.getUserIdFromToken.callsArgWith(1) - @PasswordResetHandler.setNewUserPassowrd @token, @password, (err)=> + @PasswordResetHandler.setNewUserPassword @token, @password, (err)=> err.should.exists @AuthenticationManager.setUserPassword.called.should.equal false done() @@ -70,7 +70,7 @@ describe "PasswordResetHandler", -> it "should set the user password", (done)-> @TokenGenerator.getUserIdFromToken.callsArgWith(1, null, @user_id) @AuthenticationManager.setUserPassword.callsArgWith(2) - @PasswordResetHandler.setNewUserPassowrd @token, @password, (err)=> + @PasswordResetHandler.setNewUserPassword @token, @password, (err)=> @AuthenticationManager.setUserPassword.calledWith(@user_id, @password).should.equal true done()