overleaf/services/web/app/src/Features/PasswordReset/PasswordResetHandler.js

165 lines
4.5 KiB
JavaScript
Raw Normal View History

const settings = require('settings-sharelatex')
const UserGetter = require('../User/UserGetter')
const OneTimeTokenHandler = require('../Security/OneTimeTokenHandler')
const EmailHandler = require('../Email/EmailHandler')
const AuthenticationManager = require('../Authentication/AuthenticationManager')
const logger = require('logger-sharelatex')
const V1Api = require('../V1/V1Api')
const PasswordResetHandler = {
generateAndEmailResetToken(email, callback) {
PasswordResetHandler._getPasswordResetData(email, function(
error,
exists,
data
) {
if (error != null) {
callback(error)
} else if (exists) {
OneTimeTokenHandler.getNewToken('password', data, function(err, token) {
if (err) {
return callback(err)
}
const emailOptions = {
to: email,
setNewPasswordUrl: `${
settings.siteUrl
}/user/password/set?passwordResetToken=${token}&email=${encodeURIComponent(
email
)}`
}
EmailHandler.sendEmail(
'passwordResetRequested',
emailOptions,
function(error) {
if (error != null) {
return callback(error)
}
callback(null, 'primary')
}
)
})
} else {
UserGetter.getUserByAnyEmail(email, function(err, user) {
if (err != null) {
return callback(err)
}
if (!user) {
callback(null, null)
} else if (user.overleaf == null || user.overleaf.id == null) {
callback(null, 'sharelatex')
} else {
callback(null, 'secondary')
}
})
}
})
},
setNewUserPassword(token, password, callback) {
PasswordResetHandler.getUserForPasswordResetToken(
token,
(err, user, version) => {
if (err != null) {
return callback(err)
}
if (user == null) {
return callback(null, false, null)
}
AuthenticationManager.setUserPassword(
user._id,
password,
(err, reset) => {
if (err) {
return callback(err)
}
callback(null, reset, user._id)
}
)
}
)
},
getUserForPasswordResetToken(token, callback) {
OneTimeTokenHandler.getValueFromTokenAndExpire(
'password',
token,
(err, data) => {
if (err != null) {
if (err.name === 'NotFoundError') {
return callback(null, null)
} else {
return callback(err)
}
}
if (data == null || data.email == null) {
return callback(null, null)
}
UserGetter.getUserByMainEmail(
data.email,
{ _id: 1, 'overleaf.id': 1 },
(err, user) => {
if (err != null) {
callback(err)
} else if (user == null) {
callback(null, null)
} else if (
data.user_id != null &&
data.user_id === user._id.toString()
) {
callback(null, user, 'v2')
} else if (
data.v1_user_id != null &&
user.overleaf != null &&
data.v1_user_id === user.overleaf.id
) {
callback(null, user, 'v1')
} else {
callback(null, null)
}
}
)
}
)
},
_getPasswordResetData(email, callback) {
if (settings.overleaf != null) {
// Overleaf v2
V1Api.request(
{
url: '/api/v1/sharelatex/user_emails',
qs: {
email
},
expectedStatusCodes: [404]
},
function(error, response, body) {
if (error != null) {
return callback(error)
}
if (response.statusCode === 404) {
callback(null, false)
} else {
callback(null, true, { v1_user_id: body.user_id, email: email })
}
}
)
} else {
// ShareLaTeX
UserGetter.getUserByMainEmail(email, function(err, user) {
if (err) {
return callback(err)
}
if (user == null || user.holdingAccount || user.overleaf != null) {
logger.err({ email }, 'user could not be found for password reset')
return callback(null, false)
}
callback(null, true, { user_id: user._id, email: email })
})
}
}
}
module.exports = PasswordResetHandler