PasswordResetTests.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. const { expect } = require('chai')
  2. const RateLimiter = require('../../../app/src/infrastructure/RateLimiter')
  3. const UserHelper = require('./helpers/UserHelper')
  4. const { db } = require('../../../app/src/infrastructure/mongodb')
  5. describe('PasswordReset', function() {
  6. let email, response, user, userHelper, token
  7. afterEach(async function() {
  8. await RateLimiter.promises.clearRateLimit(
  9. 'password_reset_rate_limit',
  10. '127.0.0.1'
  11. )
  12. })
  13. beforeEach(async function() {
  14. userHelper = new UserHelper()
  15. email = userHelper.getDefaultEmail()
  16. userHelper = await UserHelper.createUser({ email })
  17. user = userHelper.user
  18. // generate the token
  19. await userHelper.getCsrfToken()
  20. response = await userHelper.request.post('/user/password/reset', {
  21. form: {
  22. email
  23. }
  24. })
  25. token = (
  26. await db.tokens.findOne({
  27. 'data.user_id': user._id.toString()
  28. })
  29. ).token
  30. })
  31. describe('with a valid token', function() {
  32. describe('when logged in', function() {
  33. beforeEach(async function() {
  34. userHelper = await UserHelper.loginUser({
  35. email,
  36. password: userHelper.getDefaultPassword()
  37. })
  38. response = await userHelper.request.get(
  39. `/user/password/set?passwordResetToken=${token}&email=${email}`,
  40. { simple: false }
  41. )
  42. expect(response.statusCode).to.equal(302)
  43. expect(response.headers.location).to.equal('/user/password/set')
  44. // send reset request
  45. response = await userHelper.request.post('/user/password/set', {
  46. form: {
  47. passwordResetToken: token,
  48. password: 'a-password'
  49. }
  50. })
  51. userHelper = await UserHelper.getUser({ email })
  52. user = userHelper.user
  53. })
  54. it('update the password', async function() {
  55. expect(user.hashedPassword).to.exist
  56. expect(user.password).to.not.exist
  57. })
  58. it('log the change with initiatorId', async function() {
  59. expect(user.auditLog).to.exist
  60. expect(user.auditLog[0]).to.exist
  61. expect(typeof user.auditLog[0].initiatorId).to.equal('object')
  62. expect(user.auditLog[0].initiatorId).to.deep.equal(user._id)
  63. expect(user.auditLog[0].operation).to.equal('reset-password')
  64. expect(user.auditLog[0].ipAddress).to.equal('127.0.0.1')
  65. expect(user.auditLog[0].timestamp).to.exist
  66. })
  67. })
  68. describe('when logged in as another user', function() {
  69. let otherUser, otherUserEmail
  70. beforeEach(async function() {
  71. otherUserEmail = userHelper.getDefaultEmail()
  72. userHelper = await UserHelper.createUser({ email: otherUserEmail })
  73. otherUser = userHelper.user
  74. userHelper = await UserHelper.loginUser({
  75. email: otherUserEmail,
  76. password: userHelper.getDefaultPassword()
  77. })
  78. response = await userHelper.request.get(
  79. `/user/password/set?passwordResetToken=${token}&email=${email}`,
  80. { simple: false }
  81. )
  82. expect(response.statusCode).to.equal(302)
  83. expect(response.headers.location).to.equal('/user/password/set')
  84. // send reset request
  85. response = await userHelper.request.post('/user/password/set', {
  86. form: {
  87. passwordResetToken: token,
  88. password: 'a-password'
  89. }
  90. })
  91. userHelper = await UserHelper.getUser({ email })
  92. user = userHelper.user
  93. })
  94. it('update the password', async function() {
  95. expect(user.hashedPassword).to.exist
  96. expect(user.password).to.not.exist
  97. })
  98. it('log the change with the logged in user as the initiatorId', async function() {
  99. expect(user.auditLog).to.exist
  100. expect(user.auditLog[0]).to.exist
  101. expect(typeof user.auditLog[0].initiatorId).to.equal('object')
  102. expect(user.auditLog[0].initiatorId).to.deep.equal(otherUser._id)
  103. expect(user.auditLog[0].operation).to.equal('reset-password')
  104. expect(user.auditLog[0].ipAddress).to.equal('127.0.0.1')
  105. expect(user.auditLog[0].timestamp).to.exist
  106. })
  107. })
  108. describe('when not logged in', function() {
  109. beforeEach(async function() {
  110. response = await userHelper.request.get(
  111. `/user/password/set?passwordResetToken=${token}&email=${email}`,
  112. { simple: false }
  113. )
  114. expect(response.statusCode).to.equal(302)
  115. expect(response.headers.location).to.equal('/user/password/set')
  116. // send reset request
  117. response = await userHelper.request.post('/user/password/set', {
  118. form: {
  119. passwordResetToken: token,
  120. password: 'a-password'
  121. }
  122. })
  123. userHelper = await UserHelper.getUser({ email })
  124. user = userHelper.user
  125. })
  126. it('updates the password', function() {
  127. expect(user.hashedPassword).to.exist
  128. expect(user.password).to.not.exist
  129. })
  130. it('log the change', async function() {
  131. expect(user.auditLog).to.exist
  132. expect(user.auditLog[0]).to.exist
  133. expect(user.auditLog[0].initiatorId).to.equal(null)
  134. expect(user.auditLog[0].operation).to.equal('reset-password')
  135. expect(user.auditLog[0].ipAddress).to.equal('127.0.0.1')
  136. expect(user.auditLog[0].timestamp).to.exist
  137. })
  138. })
  139. describe('password checks', function() {
  140. beforeEach(async function() {
  141. response = await userHelper.request.get(
  142. `/user/password/set?passwordResetToken=${token}&email=${email}`,
  143. { simple: false }
  144. )
  145. expect(response.statusCode).to.equal(302)
  146. expect(response.headers.location).to.equal('/user/password/set')
  147. })
  148. it('without a password should return 400 and not log the change', async function() {
  149. // send reset request
  150. response = await userHelper.request.post('/user/password/set', {
  151. form: {
  152. passwordResetToken: token
  153. },
  154. simple: false
  155. })
  156. expect(response.statusCode).to.equal(400)
  157. userHelper = await UserHelper.getUser({ email })
  158. user = userHelper.user
  159. expect(user.auditLog).to.deep.equal([])
  160. })
  161. it('without a valid password should return 400 and not log the change', async function() {
  162. // send reset request
  163. response = await userHelper.request.post('/user/password/set', {
  164. form: {
  165. passwordResetToken: token,
  166. password: 'short'
  167. },
  168. simple: false
  169. })
  170. expect(response.statusCode).to.equal(400)
  171. userHelper = await UserHelper.getUser({ email })
  172. user = userHelper.user
  173. expect(user.auditLog).to.deep.equal([])
  174. })
  175. })
  176. })
  177. describe('without a valid token', function() {
  178. it('no token should redirect to page to re-request reset token', async function() {
  179. response = await userHelper.request.get(
  180. `/user/password/set?&email=${email}`,
  181. { simple: false }
  182. )
  183. expect(response.statusCode).to.equal(302)
  184. expect(response.headers.location).to.equal('/user/password/reset')
  185. })
  186. it('should return 404 for invalid tokens', async function() {
  187. const invalidToken = 'not-real-token'
  188. response = await userHelper.request.get(
  189. `/user/password/set?&passwordResetToken=${invalidToken}&email=${email}`,
  190. { simple: false }
  191. )
  192. expect(response.statusCode).to.equal(302)
  193. expect(response.headers.location).to.equal('/user/password/set')
  194. // send reset request
  195. response = await userHelper.request.post('/user/password/set', {
  196. form: {
  197. passwordResetToken: invalidToken,
  198. password: 'a-password'
  199. },
  200. simple: false
  201. })
  202. expect(response.statusCode).to.equal(404)
  203. })
  204. })
  205. })