PasswordResetHandler.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. const settings = require('@overleaf/settings')
  2. const UserAuditLogHandler = require('../User/UserAuditLogHandler')
  3. const UserGetter = require('../User/UserGetter')
  4. const OneTimeTokenHandler = require('../Security/OneTimeTokenHandler')
  5. const EmailHandler = require('../Email/EmailHandler')
  6. const AuthenticationManager = require('../Authentication/AuthenticationManager')
  7. const { callbackify, promisify } = require('util')
  8. function generateAndEmailResetToken(email, callback) {
  9. UserGetter.getUserByAnyEmail(email, (err, user) => {
  10. if (err || !user) {
  11. return callback(err, null)
  12. }
  13. if (user.email !== email) {
  14. return callback(null, 'secondary')
  15. }
  16. const data = { user_id: user._id.toString(), email: email }
  17. OneTimeTokenHandler.getNewToken('password', data, (err, token) => {
  18. if (err) {
  19. return callback(err)
  20. }
  21. const emailOptions = {
  22. to: email,
  23. setNewPasswordUrl: `${
  24. settings.siteUrl
  25. }/user/password/set?passwordResetToken=${token}&email=${encodeURIComponent(
  26. email
  27. )}`,
  28. }
  29. EmailHandler.sendEmail('passwordResetRequested', emailOptions, err => {
  30. if (err) {
  31. return callback(err)
  32. }
  33. callback(null, 'primary')
  34. })
  35. })
  36. })
  37. }
  38. function getUserForPasswordResetToken(token, callback) {
  39. OneTimeTokenHandler.getValueFromTokenAndExpire(
  40. 'password',
  41. token,
  42. (err, data) => {
  43. if (err != null) {
  44. if (err.name === 'NotFoundError') {
  45. return callback(null, null)
  46. } else {
  47. return callback(err)
  48. }
  49. }
  50. if (data == null || data.email == null) {
  51. return callback(null, null)
  52. }
  53. UserGetter.getUserByMainEmail(
  54. data.email,
  55. { _id: 1, 'overleaf.id': 1, email: 1 },
  56. (err, user) => {
  57. if (err != null) {
  58. callback(err)
  59. } else if (user == null) {
  60. callback(null, null)
  61. } else if (
  62. data.user_id != null &&
  63. data.user_id === user._id.toString()
  64. ) {
  65. callback(null, user)
  66. } else if (
  67. data.v1_user_id != null &&
  68. user.overleaf != null &&
  69. data.v1_user_id === user.overleaf.id
  70. ) {
  71. callback(null, user)
  72. } else {
  73. callback(null, null)
  74. }
  75. }
  76. )
  77. }
  78. )
  79. }
  80. async function setNewUserPassword(token, password, auditLog) {
  81. const user = await PasswordResetHandler.promises.getUserForPasswordResetToken(
  82. token
  83. )
  84. if (!user) {
  85. return {
  86. found: false,
  87. reset: false,
  88. userId: null,
  89. }
  90. }
  91. const reset = await AuthenticationManager.promises.setUserPassword(
  92. user,
  93. password
  94. )
  95. await UserAuditLogHandler.promises.addEntry(
  96. user._id,
  97. 'reset-password',
  98. auditLog.initiatorId,
  99. auditLog.ip
  100. )
  101. return { found: true, reset, userId: user._id }
  102. }
  103. const PasswordResetHandler = {
  104. generateAndEmailResetToken,
  105. setNewUserPassword: callbackify(setNewUserPassword),
  106. getUserForPasswordResetToken,
  107. }
  108. PasswordResetHandler.promises = {
  109. getUserForPasswordResetToken: promisify(
  110. PasswordResetHandler.getUserForPasswordResetToken
  111. ),
  112. setNewUserPassword,
  113. }
  114. module.exports = PasswordResetHandler