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

180 lines
5.3 KiB
JavaScript
Raw Normal View History

/* eslint-disable
camelcase,
handle-callback-err,
max-len,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let PasswordResetHandler
const settings = require('settings-sharelatex')
const async = require('async')
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')
module.exports = PasswordResetHandler = {
generateAndEmailResetToken(email, callback) {
if (callback == null) {
callback = function(error, status) {}
}
return PasswordResetHandler._getPasswordResetData(email, function(
error,
exists,
data
) {
if (error != null) {
return callback(error, null)
} else if (exists) {
return 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
)}`
}
return EmailHandler.sendEmail(
'passwordResetRequested',
emailOptions,
function(error) {
if (error != null) {
return callback(error)
}
return callback(null, 'primary')
}
)
})
} else {
return UserGetter.getUserByAnyEmail(email, function(err, user) {
if (!user) {
return callback(error, null)
} else if (
(user.overleaf != null ? user.overleaf.id : undefined) == null
) {
return callback(error, 'sharelatex')
} else {
return callback(error, 'secondary')
}
})
}
})
},
setNewUserPassword(token, password, callback) {
if (callback == null) {
callback = function(error, found, user_id) {}
}
return OneTimeTokenHandler.getValueFromTokenAndExpire(
'password',
token,
function(err, data) {
if (err) {
return callback(err)
}
if (data == null) {
return callback(null, false, null)
}
if (typeof data === 'string') {
// Backwards compatible with old format.
// Tokens expire after 1h, so this can be removed soon after deploy.
// Possibly we should keep this until we do an onsite release too.
data = { user_id: data }
}
if (data.user_id != null) {
return AuthenticationManager.setUserPassword(
data.user_id,
password,
function(err, reset) {
if (err) {
return callback(err)
}
return callback(null, reset, data.user_id)
}
)
} else if (data.v1_user_id != null) {
return AuthenticationManager.setUserPasswordInV1(
data.v1_user_id,
password,
function(error, reset) {
if (error != null) {
return callback(error)
}
return UserGetter.getUser(
{ 'overleaf.id': data.v1_user_id },
{ _id: 1 },
function(error, user) {
if (error != null) {
return callback(error)
}
return callback(
null,
reset,
user != null ? user._id : undefined
)
}
)
}
)
}
}
)
},
_getPasswordResetData(email, callback) {
if (callback == null) {
callback = function(error, exists, data) {}
}
if (settings.overleaf != null) {
// Overleaf v2
return 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) {
return callback(null, false)
} else {
return callback(null, true, { v1_user_id: body.user_id })
}
}
)
} else {
// ShareLaTeX
return 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)
}
return callback(null, true, { user_id: user._id })
})
}
}
}