PasswordResetControllerTests.coffee 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. should = require('chai').should()
  2. expect = require("chai").expect
  3. SandboxedModule = require('sandboxed-module')
  4. assert = require('assert')
  5. path = require('path')
  6. sinon = require('sinon')
  7. modulePath = path.join __dirname, "../../../../app/js/Features/PasswordReset/PasswordResetController"
  8. expect = require("chai").expect
  9. describe "PasswordResetController", ->
  10. beforeEach ->
  11. @settings = {}
  12. @PasswordResetHandler =
  13. generateAndEmailResetToken:sinon.stub()
  14. setNewUserPassword:sinon.stub()
  15. @RateLimiter =
  16. addCount: sinon.stub()
  17. @PasswordResetController = SandboxedModule.require modulePath, requires:
  18. "settings-sharelatex":@settings
  19. "./PasswordResetHandler":@PasswordResetHandler
  20. "logger-sharelatex": log:->
  21. "../../infrastructure/RateLimiter":@RateLimiter
  22. "../Authentication/AuthenticationController": @AuthenticationController = {}
  23. "../User/UserGetter": @UserGetter = {}
  24. @email = "bob@bob.com "
  25. @token = "my security token that was emailed to me"
  26. @password = "my new password"
  27. @req =
  28. body:
  29. email:@email
  30. passwordResetToken:@token
  31. password:@password
  32. i18n:
  33. translate:->
  34. session: {}
  35. query: {}
  36. @res = {}
  37. describe "requestReset", ->
  38. it "should error if the rate limit is hit", (done)->
  39. @PasswordResetHandler.generateAndEmailResetToken.callsArgWith(1, null, true)
  40. @RateLimiter.addCount.callsArgWith(1, null, false)
  41. @res.send = (code)=>
  42. code.should.equal 500
  43. @PasswordResetHandler.generateAndEmailResetToken.calledWith(@email.trim()).should.equal false
  44. done()
  45. @PasswordResetController.requestReset @req, @res
  46. it "should tell the handler to process that email", (done)->
  47. @RateLimiter.addCount.callsArgWith(1, null, true)
  48. @PasswordResetHandler.generateAndEmailResetToken.callsArgWith(1, null, true)
  49. @res.sendStatus = (code)=>
  50. code.should.equal 200
  51. @PasswordResetHandler.generateAndEmailResetToken.calledWith(@email.trim()).should.equal true
  52. done()
  53. @PasswordResetController.requestReset @req, @res
  54. it "should send a 500 if there is an error", (done)->
  55. @RateLimiter.addCount.callsArgWith(1, null, true)
  56. @PasswordResetHandler.generateAndEmailResetToken.callsArgWith(1, "error")
  57. @res.send = (code)=>
  58. code.should.equal 500
  59. done()
  60. @PasswordResetController.requestReset @req, @res
  61. it "should send a 404 if the email doesn't exist", (done)->
  62. @RateLimiter.addCount.callsArgWith(1, null, true)
  63. @PasswordResetHandler.generateAndEmailResetToken.callsArgWith(1, null, false)
  64. @res.send = (code)=>
  65. code.should.equal 404
  66. done()
  67. @PasswordResetController.requestReset @req, @res
  68. it "should lowercase the email address", (done)->
  69. @email = "UPerCaseEMAIL@example.Com"
  70. @req.body.email = @email
  71. @RateLimiter.addCount.callsArgWith(1, null, true)
  72. @PasswordResetHandler.generateAndEmailResetToken.callsArgWith(1, null, true)
  73. @res.sendStatus = (code)=>
  74. code.should.equal 200
  75. @PasswordResetHandler.generateAndEmailResetToken.calledWith(@email.toLowerCase()).should.equal true
  76. done()
  77. @PasswordResetController.requestReset @req, @res
  78. describe "setNewUserPassword", ->
  79. beforeEach ->
  80. @req.session.resetToken = @token
  81. it "should tell the user handler to reset the password", (done)->
  82. @PasswordResetHandler.setNewUserPassword.callsArgWith(2, null, true)
  83. @res.sendStatus = (code)=>
  84. code.should.equal 200
  85. @PasswordResetHandler.setNewUserPassword.calledWith(@token, @password).should.equal true
  86. done()
  87. @PasswordResetController.setNewUserPassword @req, @res
  88. it "should send 404 if the token didn't work", (done)->
  89. @PasswordResetHandler.setNewUserPassword.callsArgWith(2, null, false)
  90. @res.sendStatus = (code)=>
  91. code.should.equal 404
  92. done()
  93. @PasswordResetController.setNewUserPassword @req, @res
  94. it "should return 400 (Bad Request) if there is no password", (done)->
  95. @req.body.password = ""
  96. @PasswordResetHandler.setNewUserPassword.callsArgWith(2)
  97. @res.sendStatus = (code)=>
  98. code.should.equal 400
  99. @PasswordResetHandler.setNewUserPassword.called.should.equal false
  100. done()
  101. @PasswordResetController.setNewUserPassword @req, @res
  102. it "should return 400 (Bad Request) if there is no passwordResetToken", (done)->
  103. @req.body.passwordResetToken = ""
  104. @PasswordResetHandler.setNewUserPassword.callsArgWith(2)
  105. @res.sendStatus = (code)=>
  106. code.should.equal 400
  107. @PasswordResetHandler.setNewUserPassword.called.should.equal false
  108. done()
  109. @PasswordResetController.setNewUserPassword @req, @res
  110. it "should clear the session.resetToken", (done) ->
  111. @PasswordResetHandler.setNewUserPassword.callsArgWith(2, null, true)
  112. @res.sendStatus = (code)=>
  113. code.should.equal 200
  114. @req.session.should.not.have.property 'resetToken'
  115. done()
  116. @PasswordResetController.setNewUserPassword @req, @res
  117. it "should login user if login_after is set", (done) ->
  118. @UserGetter.getUser = sinon.stub().callsArgWith(2, null, { email: "joe@example.com" })
  119. @PasswordResetHandler.setNewUserPassword.callsArgWith(2, null, true, @user_id = "user-id-123")
  120. @req.body.login_after = "true"
  121. @AuthenticationController.doLogin = (options, req, res, next)=>
  122. @UserGetter.getUser.calledWith(@user_id).should.equal true
  123. expect(options).to.deep.equal {
  124. email: "joe@example.com",
  125. password: @password
  126. }
  127. done()
  128. @PasswordResetController.setNewUserPassword @req, @res
  129. describe "renderSetPasswordForm", ->
  130. describe "with token in query-string", ->
  131. beforeEach ->
  132. @req.query.passwordResetToken = @token
  133. it "should set session.resetToken and redirect", (done) ->
  134. @req.session.should.not.have.property 'resetToken'
  135. @res.redirect = (path) =>
  136. path.should.equal '/user/password/set'
  137. @req.session.resetToken.should.equal @token
  138. done()
  139. @PasswordResetController.renderSetPasswordForm(@req, @res)
  140. describe "without a token in query-string", ->
  141. describe "with token in session", ->
  142. beforeEach ->
  143. @req.session.resetToken = @token
  144. it "should render the page, passing the reset token", (done) ->
  145. @res.render = (template_path, options) =>
  146. options.passwordResetToken.should.equal @req.session.resetToken
  147. done()
  148. @PasswordResetController.renderSetPasswordForm(@req, @res)
  149. describe "without a token in session", ->
  150. it "should redirect to the reset request page", (done) ->
  151. @res.redirect = (path) =>
  152. path.should.equal "/user/password/reset"
  153. @req.session.should.not.have.property 'resetToken'
  154. done()
  155. @PasswordResetController.renderSetPasswordForm(@req, @res)