PasswordResetController.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. const PasswordResetHandler = require('./PasswordResetHandler')
  2. const RateLimiter = require('../../infrastructure/RateLimiter')
  3. const AuthenticationController = require('../Authentication/AuthenticationController')
  4. const AuthenticationManager = require('../Authentication/AuthenticationManager')
  5. const UserGetter = require('../User/UserGetter')
  6. const UserUpdater = require('../User/UserUpdater')
  7. const UserSessionsManager = require('../User/UserSessionsManager')
  8. const OError = require('@overleaf/o-error')
  9. const { expressify } = require('../../util/promises')
  10. async function setNewUserPassword(req, res, next) {
  11. let user
  12. let { passwordResetToken, password } = req.body
  13. if (!passwordResetToken || !password) {
  14. return res.sendStatus(400)
  15. }
  16. passwordResetToken = passwordResetToken.trim()
  17. if (AuthenticationManager.validatePassword(password) != null) {
  18. return res.sendStatus(400)
  19. }
  20. delete req.session.resetToken
  21. const initiatorId = AuthenticationController.getLoggedInUserId(req)
  22. // password reset via tokens can be done while logged in, or not
  23. const auditLog = {
  24. initiatorId,
  25. ip: req.ip
  26. }
  27. try {
  28. const result = await PasswordResetHandler.promises.setNewUserPassword(
  29. passwordResetToken,
  30. password,
  31. auditLog
  32. )
  33. let { found, reset, userId } = result
  34. if (!found) return res.sendStatus(404)
  35. if (!reset) return res.sendStatus(500)
  36. await UserSessionsManager.promises.revokeAllUserSessions(
  37. { _id: userId },
  38. []
  39. )
  40. await UserUpdater.promises.removeReconfirmFlag(userId)
  41. if (!req.session.doLoginAfterPasswordReset) {
  42. return res.sendStatus(200)
  43. }
  44. user = await UserGetter.promises.getUser(userId)
  45. } catch (error) {
  46. if (error.name === 'NotFoundError') {
  47. return res.sendStatus(404)
  48. } else if (error.name === 'InvalidPasswordError') {
  49. return res.sendStatus(400)
  50. } else {
  51. return res.sendStatus(500)
  52. }
  53. }
  54. AuthenticationController.finishLogin(user, req, res, next)
  55. }
  56. module.exports = {
  57. renderRequestResetForm(req, res) {
  58. res.render('user/passwordReset', { title: 'reset_password' })
  59. },
  60. requestReset(req, res, next) {
  61. const email = req.body.email.trim().toLowerCase()
  62. const opts = {
  63. endpointName: 'password_reset_rate_limit',
  64. timeInterval: 60,
  65. subjectName: req.ip,
  66. throttle: 6
  67. }
  68. RateLimiter.addCount(opts, (err, canContinue) => {
  69. if (err != null) {
  70. return next(
  71. new OError('rate-limit password reset failed').withCause(err)
  72. )
  73. }
  74. if (!canContinue) {
  75. return res.status(429).send({
  76. message: req.i18n.translate('rate_limit_hit_wait')
  77. })
  78. }
  79. PasswordResetHandler.generateAndEmailResetToken(email, (err, status) => {
  80. if (err != null) {
  81. OError.tag(err, 'failed to generate and email password reset token', {
  82. email
  83. })
  84. next(err)
  85. } else if (status === 'primary') {
  86. res.status(200).send({
  87. message: { text: req.i18n.translate('password_reset_email_sent') }
  88. })
  89. } else if (status === 'secondary') {
  90. res.status(404).send({
  91. message: req.i18n.translate('secondary_email_password_reset')
  92. })
  93. } else {
  94. res.status(404).send({
  95. message: req.i18n.translate('cant_find_email')
  96. })
  97. }
  98. })
  99. })
  100. },
  101. renderSetPasswordForm(req, res) {
  102. if (req.query.passwordResetToken != null) {
  103. req.session.resetToken = req.query.passwordResetToken
  104. return res.redirect('/user/password/set')
  105. }
  106. if (req.session.resetToken == null) {
  107. return res.redirect('/user/password/reset')
  108. }
  109. res.render('user/setPassword', {
  110. title: 'set_password',
  111. passwordResetToken: req.session.resetToken
  112. })
  113. },
  114. setNewUserPassword: expressify(setNewUserPassword)
  115. }