PasswordResetTests.js 7.6 KB

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