PasswordResetTests.js 7.8 KB

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