PasswordResetTests.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. const auditLog = userHelper.getAuditLogWithoutNoise()
  60. expect(auditLog).to.exist
  61. expect(auditLog[0]).to.exist
  62. expect(typeof auditLog[0].initiatorId).to.equal('object')
  63. expect(auditLog[0].initiatorId).to.deep.equal(user._id)
  64. expect(auditLog[0].operation).to.equal('reset-password')
  65. expect(auditLog[0].ipAddress).to.equal('127.0.0.1')
  66. expect(auditLog[0].timestamp).to.exist
  67. })
  68. })
  69. describe('when logged in as another user', function() {
  70. let otherUser, otherUserEmail
  71. beforeEach(async function() {
  72. otherUserEmail = userHelper.getDefaultEmail()
  73. userHelper = await UserHelper.createUser({ email: otherUserEmail })
  74. otherUser = userHelper.user
  75. userHelper = await UserHelper.loginUser({
  76. email: otherUserEmail,
  77. password: userHelper.getDefaultPassword()
  78. })
  79. response = await userHelper.request.get(
  80. `/user/password/set?passwordResetToken=${token}&email=${email}`,
  81. { simple: false }
  82. )
  83. expect(response.statusCode).to.equal(302)
  84. expect(response.headers.location).to.equal('/user/password/set')
  85. // send reset request
  86. response = await userHelper.request.post('/user/password/set', {
  87. form: {
  88. passwordResetToken: token,
  89. password: 'a-password'
  90. }
  91. })
  92. userHelper = await UserHelper.getUser({ email })
  93. user = userHelper.user
  94. })
  95. it('update the password', async function() {
  96. expect(user.hashedPassword).to.exist
  97. expect(user.password).to.not.exist
  98. })
  99. it('log the change with the logged in user as the initiatorId', async function() {
  100. const auditLog = userHelper.getAuditLogWithoutNoise()
  101. expect(auditLog).to.exist
  102. expect(auditLog[0]).to.exist
  103. expect(typeof auditLog[0].initiatorId).to.equal('object')
  104. expect(auditLog[0].initiatorId).to.deep.equal(otherUser._id)
  105. expect(auditLog[0].operation).to.equal('reset-password')
  106. expect(auditLog[0].ipAddress).to.equal('127.0.0.1')
  107. expect(auditLog[0].timestamp).to.exist
  108. })
  109. })
  110. describe('when not logged in', function() {
  111. beforeEach(async function() {
  112. response = await userHelper.request.get(
  113. `/user/password/set?passwordResetToken=${token}&email=${email}`,
  114. { simple: false }
  115. )
  116. expect(response.statusCode).to.equal(302)
  117. expect(response.headers.location).to.equal('/user/password/set')
  118. // send reset request
  119. response = await userHelper.request.post('/user/password/set', {
  120. form: {
  121. passwordResetToken: token,
  122. password: 'a-password'
  123. }
  124. })
  125. userHelper = await UserHelper.getUser({ email })
  126. user = userHelper.user
  127. })
  128. it('updates the password', function() {
  129. expect(user.hashedPassword).to.exist
  130. expect(user.password).to.not.exist
  131. })
  132. it('log the change', async function() {
  133. const auditLog = userHelper.getAuditLogWithoutNoise()
  134. expect(auditLog).to.exist
  135. expect(auditLog[0]).to.exist
  136. expect(auditLog[0].initiatorId).to.equal(null)
  137. expect(auditLog[0].operation).to.equal('reset-password')
  138. expect(auditLog[0].ipAddress).to.equal('127.0.0.1')
  139. expect(auditLog[0].timestamp).to.exist
  140. })
  141. })
  142. describe('password checks', function() {
  143. beforeEach(async function() {
  144. response = await userHelper.request.get(
  145. `/user/password/set?passwordResetToken=${token}&email=${email}`,
  146. { simple: false }
  147. )
  148. expect(response.statusCode).to.equal(302)
  149. expect(response.headers.location).to.equal('/user/password/set')
  150. })
  151. it('without a password should return 400 and not log the change', async function() {
  152. // send reset request
  153. response = await userHelper.request.post('/user/password/set', {
  154. form: {
  155. passwordResetToken: token
  156. },
  157. simple: false
  158. })
  159. expect(response.statusCode).to.equal(400)
  160. userHelper = await UserHelper.getUser({ email })
  161. const auditLog = userHelper.getAuditLogWithoutNoise()
  162. expect(auditLog).to.deep.equal([])
  163. })
  164. it('without a valid password should return 400 and not log the change', async function() {
  165. // send reset request
  166. response = await userHelper.request.post('/user/password/set', {
  167. form: {
  168. passwordResetToken: token,
  169. password: 'short'
  170. },
  171. simple: false
  172. })
  173. expect(response.statusCode).to.equal(400)
  174. userHelper = await UserHelper.getUser({ email })
  175. const auditLog = userHelper.getAuditLogWithoutNoise()
  176. expect(auditLog).to.deep.equal([])
  177. })
  178. })
  179. })
  180. describe('without a valid token', function() {
  181. it('no token should redirect to page to re-request reset token', async function() {
  182. response = await userHelper.request.get(
  183. `/user/password/set?&email=${email}`,
  184. { simple: false }
  185. )
  186. expect(response.statusCode).to.equal(302)
  187. expect(response.headers.location).to.equal('/user/password/reset')
  188. })
  189. it('should return 404 for invalid tokens', async function() {
  190. const invalidToken = 'not-real-token'
  191. response = await userHelper.request.get(
  192. `/user/password/set?&passwordResetToken=${invalidToken}&email=${email}`,
  193. { simple: false }
  194. )
  195. expect(response.statusCode).to.equal(302)
  196. expect(response.headers.location).to.equal('/user/password/set')
  197. // send reset request
  198. response = await userHelper.request.post('/user/password/set', {
  199. form: {
  200. passwordResetToken: invalidToken,
  201. password: 'a-password'
  202. },
  203. simple: false
  204. })
  205. expect(response.statusCode).to.equal(404)
  206. })
  207. })
  208. describe('password reset', function() {
  209. it('should return 200 if email field is valid', async function() {
  210. response = await userHelper.request.post(`/user/password/reset`, {
  211. form: {
  212. email
  213. }
  214. })
  215. expect(response.statusCode).to.equal(200)
  216. })
  217. it('should return 400 if email field is missing', async function() {
  218. response = await userHelper.request.post(`/user/password/reset`, {
  219. form: {
  220. mail: email
  221. },
  222. simple: false
  223. })
  224. expect(response.statusCode).to.equal(400)
  225. })
  226. })
  227. describe('password set', function() {
  228. it('should return 200 if password and passwordResetToken fields are valid', async function() {
  229. response = await userHelper.request.post(`/user/password/set`, {
  230. form: {
  231. password: 'new-password',
  232. passwordResetToken: token
  233. }
  234. })
  235. expect(response.statusCode).to.equal(200)
  236. })
  237. it('should return 400 if password field is missing', async function() {
  238. response = await userHelper.request.post(`/user/password/set`, {
  239. form: {
  240. passwordResetToken: token
  241. },
  242. simple: false
  243. })
  244. expect(response.statusCode).to.equal(400)
  245. })
  246. it('should return 400 if passwordResetToken field is missing', async function() {
  247. response = await userHelper.request.post(`/user/password/set`, {
  248. form: {
  249. password: 'new-password'
  250. },
  251. simple: false
  252. })
  253. expect(response.statusCode).to.equal(400)
  254. })
  255. })
  256. })