| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- const logger = require('@overleaf/logger')
- const SessionManager = require('../Authentication/SessionManager')
- const UserGetter = require('./UserGetter')
- const UserUpdater = require('./UserUpdater')
- const UserSessionsManager = require('./UserSessionsManager')
- const EmailHandler = require('../Email/EmailHandler')
- const EmailHelper = require('../Helpers/EmailHelper')
- const UserEmailsConfirmationHandler = require('./UserEmailsConfirmationHandler')
- const { endorseAffiliation } = require('../Institutions/InstitutionsAPI')
- const Errors = require('../Errors/Errors')
- const HttpErrorHandler = require('../Errors/HttpErrorHandler')
- const { expressify } = require('../../util/promises')
- const AsyncFormHelper = require('../Helpers/AsyncFormHelper')
- const AnalyticsManager = require('../Analytics/AnalyticsManager')
- const UserPrimaryEmailCheckHandler = require('../User/UserPrimaryEmailCheckHandler')
- async function _sendSecurityAlertEmail(user, email) {
- const emailOptions = {
- to: user.email,
- actionDescribed: `a secondary email address has been added to your account ${user.email}`,
- message: [
- `<span style="display:inline-block;padding: 0 20px;width:100%;">Added: <br/><b>${email}</b></span>`,
- ],
- action: 'secondary email address added',
- }
- await EmailHandler.promises.sendEmail('securityAlert', emailOptions)
- }
- async function add(req, res, next) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- const email = EmailHelper.parseEmail(req.body.email)
- if (!email) {
- return res.sendStatus(422)
- }
- const user = await UserGetter.promises.getUser(userId, { email: 1 })
- const affiliationOptions = {
- university: req.body.university,
- role: req.body.role,
- department: req.body.department,
- }
- try {
- await UserUpdater.promises.addEmailAddress(
- userId,
- email,
- affiliationOptions,
- {
- initiatorId: user._id,
- ipAddress: req.ip,
- }
- )
- } catch (error) {
- return UserEmailsController._handleEmailError(error, req, res, next)
- }
- await _sendSecurityAlertEmail(user, email)
- await UserEmailsConfirmationHandler.promises.sendConfirmationEmail(
- userId,
- email
- )
- res.sendStatus(204)
- }
- function resendConfirmation(req, res, next) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- const email = EmailHelper.parseEmail(req.body.email)
- if (!email) {
- return res.sendStatus(422)
- }
- UserGetter.getUserByAnyEmail(email, { _id: 1 }, function (error, user) {
- if (error) {
- return next(error)
- }
- if (!user || user._id.toString() !== userId) {
- return res.sendStatus(422)
- }
- UserEmailsConfirmationHandler.sendConfirmationEmail(
- userId,
- email,
- function (error) {
- if (error) {
- return next(error)
- }
- res.sendStatus(200)
- }
- )
- })
- }
- function sendReconfirmation(req, res, next) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- const email = EmailHelper.parseEmail(req.body.email)
- if (!email) {
- return res.sendStatus(400)
- }
- UserGetter.getUserByAnyEmail(email, { _id: 1 }, function (error, user) {
- if (error) {
- return next(error)
- }
- if (!user || user._id.toString() !== userId) {
- return res.sendStatus(422)
- }
- UserEmailsConfirmationHandler.sendReconfirmationEmail(
- userId,
- email,
- function (error) {
- if (error) {
- return next(error)
- }
- res.sendStatus(204)
- }
- )
- })
- }
- async function primaryEmailCheckPage(req, res) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- const user = await UserGetter.promises.getUser(userId, {
- lastPrimaryEmailCheck: 1,
- signUpDate: 1,
- email: 1,
- emails: 1,
- })
- if (!UserPrimaryEmailCheckHandler.requiresPrimaryEmailCheck(user)) {
- return res.redirect('/project')
- }
- AnalyticsManager.recordEventForUser(
- userId,
- 'primary-email-check-page-displayed'
- )
- res.render('user/primaryEmailCheck')
- }
- async function primaryEmailCheck(req, res) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- await UserUpdater.promises.updateUser(userId, {
- $set: { lastPrimaryEmailCheck: new Date() },
- })
- AnalyticsManager.recordEventForUser(userId, 'primary-email-check-done')
- AsyncFormHelper.redirect(req, res, '/project')
- }
- const UserEmailsController = {
- list(req, res, next) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- UserGetter.getUserFullEmails(userId, function (error, fullEmails) {
- if (error) {
- return next(error)
- }
- res.json(fullEmails)
- })
- },
- add: expressify(add),
- remove(req, res, next) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- const email = EmailHelper.parseEmail(req.body.email)
- if (!email) {
- return res.sendStatus(422)
- }
- const auditLog = {
- initiatorId: userId,
- ipAddress: req.ip,
- }
- UserUpdater.removeEmailAddress(userId, email, auditLog, function (error) {
- if (error) {
- return next(error)
- }
- res.sendStatus(200)
- })
- },
- setDefault(req, res, next) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- const email = EmailHelper.parseEmail(req.body.email)
- if (!email) {
- return res.sendStatus(422)
- }
- const auditLog = {
- initiatorId: userId,
- ipAddress: req.ip,
- }
- UserUpdater.setDefaultEmailAddress(
- userId,
- email,
- false,
- auditLog,
- true,
- err => {
- if (err) {
- return UserEmailsController._handleEmailError(err, req, res, next)
- }
- SessionManager.setInSessionUser(req.session, { email })
- const user = SessionManager.getSessionUser(req.session)
- UserSessionsManager.revokeAllUserSessions(
- user,
- [req.sessionID],
- err => {
- if (err)
- logger.warn(
- { err },
- 'failed revoking secondary sessions after changing default email'
- )
- }
- )
- res.sendStatus(200)
- }
- )
- },
- endorse(req, res, next) {
- const userId = SessionManager.getLoggedInUserId(req.session)
- const email = EmailHelper.parseEmail(req.body.email)
- if (!email) {
- return res.sendStatus(422)
- }
- endorseAffiliation(
- userId,
- email,
- req.body.role,
- req.body.department,
- function (error) {
- if (error) {
- return next(error)
- }
- res.sendStatus(204)
- }
- )
- },
- resendConfirmation,
- sendReconfirmation,
- primaryEmailCheckPage: expressify(primaryEmailCheckPage),
- primaryEmailCheck: expressify(primaryEmailCheck),
- showConfirm(req, res, next) {
- res.render('user/confirm_email', {
- token: req.query.token,
- title: 'confirm_email',
- })
- },
- confirm(req, res, next) {
- const { token } = req.body
- if (!token) {
- return res.status(422).json({
- message: req.i18n.translate('confirmation_link_broken'),
- })
- }
- UserEmailsConfirmationHandler.confirmEmailFromToken(
- token,
- function (error) {
- if (error) {
- if (error instanceof Errors.NotFoundError) {
- res.status(404).json({
- message: req.i18n.translate('confirmation_token_invalid'),
- })
- } else {
- next(error)
- }
- } else {
- res.sendStatus(200)
- }
- }
- )
- },
- _handleEmailError(error, req, res, next) {
- if (error instanceof Errors.UnconfirmedEmailError) {
- return HttpErrorHandler.conflict(req, res, 'email must be confirmed')
- } else if (error instanceof Errors.EmailExistsError) {
- const message = req.i18n.translate('email_already_registered')
- return HttpErrorHandler.conflict(req, res, message)
- } else if (error.message === '422: Email does not belong to university') {
- const message = req.i18n.translate('email_does_not_belong_to_university')
- return HttpErrorHandler.conflict(req, res, message)
- }
- next(error)
- },
- }
- module.exports = UserEmailsController
|