Create UserRegistrationHandler.js
This commit is contained in:
parent
9cb0492612
commit
3edabe2809
1 changed files with 136 additions and 0 deletions
136
overleafserver/UserRegistrationHandler.js
Normal file
136
overleafserver/UserRegistrationHandler.js
Normal file
|
@ -0,0 +1,136 @@
|
|||
const { User } = require('../../models/User')
|
||||
const UserCreator = require('./UserCreator')
|
||||
const UserGetter = require('./UserGetter')
|
||||
const AuthenticationManager = require('../Authentication/AuthenticationManager')
|
||||
const NewsletterManager = require('../Newsletter/NewsletterManager')
|
||||
const logger = require('@overleaf/logger')
|
||||
const crypto = require('crypto')
|
||||
const EmailHandler = require('../Email/EmailHandler')
|
||||
const OneTimeTokenHandler = require('../Security/OneTimeTokenHandler')
|
||||
const settings = require('@overleaf/settings')
|
||||
const EmailHelper = require('../Helpers/EmailHelper')
|
||||
const {
|
||||
callbackify,
|
||||
callbackifyMultiResult,
|
||||
} = require('@overleaf/promise-utils')
|
||||
const OError = require('@overleaf/o-error')
|
||||
|
||||
const UserRegistrationHandler = {
|
||||
_registrationRequestIsValid(body) {
|
||||
const invalidEmail = AuthenticationManager.validateEmail(body.email || '')
|
||||
const invalidPassword = AuthenticationManager.validatePassword(
|
||||
body.password || '',
|
||||
body.email
|
||||
)
|
||||
return !(invalidEmail || invalidPassword)
|
||||
},
|
||||
|
||||
async _createNewUserIfRequired(user, userDetails) {
|
||||
if (!user) {
|
||||
userDetails.holdingAccount = false
|
||||
return await UserCreator.promises.createNewUser(
|
||||
{
|
||||
holdingAccount: false,
|
||||
email: userDetails.email,
|
||||
first_name: userDetails.first_name,
|
||||
last_name: userDetails.last_name,
|
||||
analyticsId: userDetails.analyticsId,
|
||||
},
|
||||
{}
|
||||
)
|
||||
}
|
||||
return user
|
||||
},
|
||||
|
||||
async registerNewUser(userDetails) {
|
||||
const requestIsValid =
|
||||
UserRegistrationHandler._registrationRequestIsValid(userDetails)
|
||||
|
||||
if (!requestIsValid) {
|
||||
throw new Error('request is not valid')
|
||||
}
|
||||
userDetails.email = EmailHelper.parseEmail(userDetails.email)
|
||||
|
||||
let user = await UserGetter.promises.getUserByAnyEmail(userDetails.email)
|
||||
if (user && user.holdingAccount === false) {
|
||||
// We add userId to the error object so that the calling function can access
|
||||
// the id of the already existing user account.
|
||||
throw new OError('EmailAlreadyRegistered', { userId: user._id })
|
||||
}
|
||||
|
||||
user = await UserRegistrationHandler._createNewUserIfRequired(
|
||||
user,
|
||||
userDetails
|
||||
)
|
||||
|
||||
await User.updateOne(
|
||||
{ _id: user._id },
|
||||
{ $set: { holdingAccount: false } }
|
||||
).exec()
|
||||
|
||||
await AuthenticationManager.promises.setUserPassword(
|
||||
user,
|
||||
userDetails.password
|
||||
)
|
||||
|
||||
if (userDetails.subscribeToNewsletter === 'true') {
|
||||
try {
|
||||
NewsletterManager.subscribe(user)
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
{ err: error, user },
|
||||
'Failed to subscribe user to newsletter'
|
||||
)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
return user
|
||||
},
|
||||
|
||||
async registerNewUserAndSendActivationEmail(email) {
|
||||
let user
|
||||
try {
|
||||
user = await UserRegistrationHandler.registerNewUser({
|
||||
email,
|
||||
password: crypto.randomBytes(32).toString('hex'),
|
||||
})
|
||||
} catch (error) {
|
||||
if (error.message === 'EmailAlreadyRegistered') {
|
||||
logger.debug({ email }, 'user already exists, resending welcome email')
|
||||
user = await UserGetter.promises.getUserByAnyEmail(email)
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const ONE_WEEK = 7 * 24 * 60 * 60 // seconds
|
||||
const token = await OneTimeTokenHandler.promises.getNewToken(
|
||||
'password',
|
||||
{ user_id: user._id.toString(), email: user.email },
|
||||
{ expiresIn: ONE_WEEK }
|
||||
)
|
||||
|
||||
const setNewPasswordUrl = `${settings.siteUrl}/user/activate?token=${token}&user_id=${user._id}`
|
||||
|
||||
try {
|
||||
await EmailHandler.promises.sendEmail('registered', {
|
||||
to: user.email,
|
||||
setNewPasswordUrl,
|
||||
})
|
||||
} catch (error) {
|
||||
logger.warn({ err: error }, 'failed to send activation email')
|
||||
}
|
||||
|
||||
return { user, setNewPasswordUrl }
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
registerNewUser: callbackify(UserRegistrationHandler.registerNewUser),
|
||||
registerNewUserAndSendActivationEmail: callbackifyMultiResult(
|
||||
UserRegistrationHandler.registerNewUserAndSendActivationEmail,
|
||||
['user', 'setNewPasswordUrl']
|
||||
),
|
||||
promises: UserRegistrationHandler,
|
||||
}
|
Loading…
Reference in a new issue