PasswordResetController.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. const PasswordResetHandler = require('./PasswordResetHandler')
  2. const AuthenticationController = require('../Authentication/AuthenticationController')
  3. const AuthenticationManager = require('../Authentication/AuthenticationManager')
  4. const SessionManager = require('../Authentication/SessionManager')
  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 EmailsHelper = require('../Helpers/EmailHelper')
  10. const { expressify } = require('../../util/promises')
  11. async function setNewUserPassword(req, res, next) {
  12. let user
  13. let { passwordResetToken, password, email } = req.body
  14. if (!passwordResetToken || !password) {
  15. return res.status(400).json({
  16. message: {
  17. key: 'invalid-password',
  18. },
  19. })
  20. }
  21. const err = AuthenticationManager.validatePassword(password, email)
  22. if (err) {
  23. return res.status(400).json({
  24. message: { text: err.message },
  25. })
  26. }
  27. passwordResetToken = passwordResetToken.trim()
  28. delete req.session.resetToken
  29. const initiatorId = SessionManager.getLoggedInUserId(req.session)
  30. // password reset via tokens can be done while logged in, or not
  31. const auditLog = {
  32. initiatorId,
  33. ip: req.ip,
  34. }
  35. try {
  36. const result = await PasswordResetHandler.promises.setNewUserPassword(
  37. passwordResetToken,
  38. password,
  39. auditLog
  40. )
  41. const { found, reset, userId } = result
  42. if (!found) {
  43. return res.status(404).json({
  44. message: {
  45. key: 'token-expired',
  46. },
  47. })
  48. }
  49. if (!reset) {
  50. return res.status(500).json({
  51. message: req.i18n.translate('error_performing_request'),
  52. })
  53. }
  54. await UserSessionsManager.promises.revokeAllUserSessions(
  55. { _id: userId },
  56. []
  57. )
  58. await UserUpdater.promises.removeReconfirmFlag(userId)
  59. if (!req.session.doLoginAfterPasswordReset) {
  60. return res.sendStatus(200)
  61. }
  62. user = await UserGetter.promises.getUser(userId)
  63. } catch (error) {
  64. if (error.name === 'NotFoundError') {
  65. return res.status(404).json({
  66. message: {
  67. key: 'token-expired',
  68. },
  69. })
  70. } else if (error.name === 'InvalidPasswordError') {
  71. return res.status(400).json({
  72. message: {
  73. key: 'invalid-password',
  74. },
  75. })
  76. } else if (error.name === 'PasswordMustBeDifferentError') {
  77. return res.status(400).json({
  78. message: {
  79. key: 'password-must-be-different',
  80. },
  81. })
  82. } else if (error.name === 'PasswordReusedError') {
  83. return res.status(400).json({
  84. message: {
  85. key: 'password-must-be-strong',
  86. },
  87. })
  88. } else {
  89. return res.status(500).json({
  90. message: req.i18n.translate('error_performing_request'),
  91. })
  92. }
  93. }
  94. AuthenticationController.setAuditInfo(req, {
  95. method: 'Password reset, set new password',
  96. })
  97. AuthenticationController.finishLogin(user, req, res, next)
  98. }
  99. module.exports = {
  100. renderRequestResetForm(req, res) {
  101. const errorQuery = req.query.error
  102. let error = null
  103. if (errorQuery === 'token_expired') {
  104. error = 'password_reset_token_expired'
  105. }
  106. res.render('user/passwordReset', {
  107. title: 'reset_password',
  108. error,
  109. })
  110. },
  111. requestReset(req, res, next) {
  112. const email = EmailsHelper.parseEmail(req.body.email)
  113. if (!email) {
  114. return res.status(400).json({
  115. message: req.i18n.translate('must_be_email_address'),
  116. })
  117. }
  118. PasswordResetHandler.generateAndEmailResetToken(email, (err, status) => {
  119. if (err != null) {
  120. OError.tag(err, 'failed to generate and email password reset token', {
  121. email,
  122. })
  123. next(err)
  124. } else if (status === 'primary') {
  125. res.status(200).json({
  126. message: req.i18n.translate('password_reset_email_sent'),
  127. })
  128. } else if (status === 'secondary') {
  129. res.status(404).json({
  130. message: req.i18n.translate('secondary_email_password_reset'),
  131. })
  132. } else {
  133. res.status(404).json({
  134. message: req.i18n.translate('cant_find_email'),
  135. })
  136. }
  137. })
  138. },
  139. renderSetPasswordForm(req, res) {
  140. if (req.query.passwordResetToken != null) {
  141. return PasswordResetHandler.getUserForPasswordResetToken(
  142. req.query.passwordResetToken,
  143. (err, user, remainingUses) => {
  144. if (err || !user || remainingUses <= 0) {
  145. return res.redirect('/user/password/reset?error=token_expired')
  146. }
  147. req.session.resetToken = req.query.passwordResetToken
  148. let emailQuery = ''
  149. if (typeof req.query.email === 'string') {
  150. const email = EmailsHelper.parseEmail(req.query.email)
  151. if (email) {
  152. emailQuery = `?email=${encodeURIComponent(email)}`
  153. }
  154. }
  155. return res.redirect('/user/password/set' + emailQuery)
  156. }
  157. )
  158. }
  159. if (req.session.resetToken == null) {
  160. return res.redirect('/user/password/reset')
  161. }
  162. const email = EmailsHelper.parseEmail(req.query.email)
  163. res.render('user/setPassword', {
  164. title: 'set_password',
  165. email,
  166. passwordResetToken: req.session.resetToken,
  167. })
  168. },
  169. setNewUserPassword: expressify(setNewUserPassword),
  170. }