const { User } = require('../../models/User') const UserCreator = require('./UserCreator') const UserGetter = require('./UserGetter') const AuthenticationManager = require('../Authentication/AuthenticationManager') const NewsletterManager = require('../Newsletter/NewsletterManager') const async = require('async') const logger = require('logger-sharelatex') const crypto = require('crypto') const EmailHandler = require('../Email/EmailHandler') const OneTimeTokenHandler = require('../Security/OneTimeTokenHandler') const Analytics = require('../Analytics/AnalyticsManager') const settings = require('settings-sharelatex') const EmailHelper = require('../Helpers/EmailHelper') const UserRegistrationHandler = { _registrationRequestIsValid(body) { const invalidEmail = AuthenticationManager.validateEmail(body.email || '') const invalidPassword = AuthenticationManager.validatePassword( body.password || '', body.email ) return !(invalidEmail || invalidPassword) }, _createNewUserIfRequired(user, userDetails, callback) { if (!user) { userDetails.holdingAccount = false UserCreator.createNewUser( { holdingAccount: false, email: userDetails.email, first_name: userDetails.first_name, last_name: userDetails.last_name, }, {}, callback ) } else { callback(null, user) } }, registerNewUser(userDetails, callback) { const self = this const requestIsValid = this._registrationRequestIsValid(userDetails) if (!requestIsValid) { return callback(new Error('request is not valid')) } userDetails.email = EmailHelper.parseEmail(userDetails.email) UserGetter.getUserByAnyEmail(userDetails.email, (error, user) => { if (error) { return callback(error) } if (user && user.holdingAccount === false) { return callback(new Error('EmailAlreadyRegistered'), user) } self._createNewUserIfRequired(user, userDetails, (error, user) => { if (error) { return callback(error) } async.series( [ callback => User.updateOne( { _id: user._id }, { $set: { holdingAccount: false } }, callback ), callback => AuthenticationManager.setUserPassword( user, userDetails.password, callback ), callback => { if (userDetails.subscribeToNewsletter === 'true') { NewsletterManager.subscribe(user, error => { if (error) { logger.warn( { err: error, user }, 'Failed to subscribe user to newsletter' ) } }) } callback() }, // this can be slow, just fire it off ], error => { Analytics.recordEvent(user._id, 'user-registered') callback(error, user) } ) }) }) }, registerNewUserAndSendActivationEmail(email, callback) { UserRegistrationHandler.registerNewUser( { email, password: crypto.randomBytes(32).toString('hex'), }, (error, user) => { if (error && error.message !== 'EmailAlreadyRegistered') { return callback(error) } if (error && error.message === 'EmailAlreadyRegistered') { logger.log({ email }, 'user already exists, resending welcome email') } const ONE_WEEK = 7 * 24 * 60 * 60 // seconds OneTimeTokenHandler.getNewToken( 'password', { user_id: user._id.toString(), email: user.email }, { expiresIn: ONE_WEEK }, (error, token) => { if (error) { return callback(error) } const setNewPasswordUrl = `${settings.siteUrl}/user/activate?token=${token}&user_id=${user._id}` EmailHandler.sendEmail( 'registered', { to: user.email, setNewPasswordUrl, }, error => { if (error) { logger.warn({ err: error }, 'failed to send activation email') } } ) callback(null, user, setNewPasswordUrl) } ) } ) }, } module.exports = UserRegistrationHandler