UserEmailsController.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. const logger = require('logger-sharelatex')
  2. const AuthenticationController = require('../Authentication/AuthenticationController')
  3. const UserGetter = require('./UserGetter')
  4. const UserUpdater = require('./UserUpdater')
  5. const UserSessionsManager = require('./UserSessionsManager')
  6. const EmailHandler = require('../Email/EmailHandler')
  7. const EmailHelper = require('../Helpers/EmailHelper')
  8. const UserEmailsConfirmationHandler = require('./UserEmailsConfirmationHandler')
  9. const { endorseAffiliation } = require('../Institutions/InstitutionsAPI')
  10. const Errors = require('../Errors/Errors')
  11. const HttpErrorHandler = require('../Errors/HttpErrorHandler')
  12. const { expressify } = require('../../util/promises')
  13. async function _sendSecurityAlertEmail(user, email) {
  14. const emailOptions = {
  15. to: user.email,
  16. actionDescribed: `a secondary email address has been added to your account ${user.email}`,
  17. message: [
  18. `<span style="display:inline-block;padding: 0 20px;width:100%;">Added: <br/><b>${email}</b></span>`,
  19. ],
  20. action: 'secondary email address added',
  21. }
  22. await EmailHandler.promises.sendEmail('securityAlert', emailOptions)
  23. }
  24. async function add(req, res, next) {
  25. const userId = AuthenticationController.getLoggedInUserId(req)
  26. const email = EmailHelper.parseEmail(req.body.email)
  27. if (!email) {
  28. return res.sendStatus(422)
  29. }
  30. const user = await UserGetter.promises.getUser(userId, { email: 1 })
  31. const affiliationOptions = {
  32. university: req.body.university,
  33. role: req.body.role,
  34. department: req.body.department,
  35. }
  36. try {
  37. await UserUpdater.promises.addEmailAddress(
  38. userId,
  39. email,
  40. affiliationOptions,
  41. {
  42. initiatorId: user._id,
  43. ipAddress: req.ip,
  44. }
  45. )
  46. } catch (error) {
  47. return UserEmailsController._handleEmailError(error, req, res, next)
  48. }
  49. await _sendSecurityAlertEmail(user, email)
  50. await UserEmailsConfirmationHandler.promises.sendConfirmationEmail(
  51. userId,
  52. email
  53. )
  54. res.sendStatus(204)
  55. }
  56. function resendConfirmation(req, res, next) {
  57. const userId = AuthenticationController.getLoggedInUserId(req)
  58. const email = EmailHelper.parseEmail(req.body.email)
  59. if (!email) {
  60. return res.sendStatus(422)
  61. }
  62. UserGetter.getUserByAnyEmail(email, { _id: 1 }, function (error, user) {
  63. if (error) {
  64. return next(error)
  65. }
  66. if (!user || user._id.toString() !== userId) {
  67. return res.sendStatus(422)
  68. }
  69. UserEmailsConfirmationHandler.sendConfirmationEmail(
  70. userId,
  71. email,
  72. function (error) {
  73. if (error) {
  74. return next(error)
  75. }
  76. res.sendStatus(200)
  77. }
  78. )
  79. })
  80. }
  81. function sendReconfirmation(req, res, next) {
  82. const userId = AuthenticationController.getLoggedInUserId(req)
  83. const email = EmailHelper.parseEmail(req.body.email)
  84. if (!email) {
  85. return res.sendStatus(400)
  86. }
  87. UserGetter.getUserByAnyEmail(email, { _id: 1 }, function (error, user) {
  88. if (error) {
  89. return next(error)
  90. }
  91. if (!user || user._id.toString() !== userId) {
  92. return res.sendStatus(422)
  93. }
  94. UserEmailsConfirmationHandler.sendReconfirmationEmail(
  95. userId,
  96. email,
  97. function (error) {
  98. if (error) {
  99. return next(error)
  100. }
  101. res.sendStatus(200)
  102. }
  103. )
  104. })
  105. }
  106. const UserEmailsController = {
  107. list(req, res, next) {
  108. const userId = AuthenticationController.getLoggedInUserId(req)
  109. UserGetter.getUserFullEmails(userId, function (error, fullEmails) {
  110. if (error) {
  111. return next(error)
  112. }
  113. res.json(fullEmails)
  114. })
  115. },
  116. add: expressify(add),
  117. remove(req, res, next) {
  118. const userId = AuthenticationController.getLoggedInUserId(req)
  119. const email = EmailHelper.parseEmail(req.body.email)
  120. if (!email) {
  121. return res.sendStatus(422)
  122. }
  123. UserUpdater.removeEmailAddress(userId, email, function (error) {
  124. if (error) {
  125. return next(error)
  126. }
  127. res.sendStatus(200)
  128. })
  129. },
  130. setDefault(req, res, next) {
  131. const userId = AuthenticationController.getLoggedInUserId(req)
  132. const email = EmailHelper.parseEmail(req.body.email)
  133. if (!email) {
  134. return res.sendStatus(422)
  135. }
  136. const auditLog = {
  137. initiatorId: userId,
  138. ipAddress: req.ip,
  139. }
  140. UserUpdater.setDefaultEmailAddress(
  141. userId,
  142. email,
  143. false,
  144. auditLog,
  145. true,
  146. err => {
  147. if (err) {
  148. return UserEmailsController._handleEmailError(err, req, res, next)
  149. }
  150. AuthenticationController.setInSessionUser(req, { email: email })
  151. const user = AuthenticationController.getSessionUser(req)
  152. UserSessionsManager.revokeAllUserSessions(
  153. user,
  154. [req.sessionID],
  155. err => {
  156. if (err)
  157. logger.warn(
  158. { err },
  159. 'failed revoking secondary sessions after changing default email'
  160. )
  161. }
  162. )
  163. res.sendStatus(200)
  164. }
  165. )
  166. },
  167. endorse(req, res, next) {
  168. const userId = AuthenticationController.getLoggedInUserId(req)
  169. const email = EmailHelper.parseEmail(req.body.email)
  170. if (!email) {
  171. return res.sendStatus(422)
  172. }
  173. endorseAffiliation(
  174. userId,
  175. email,
  176. req.body.role,
  177. req.body.department,
  178. function (error) {
  179. if (error) {
  180. return next(error)
  181. }
  182. res.sendStatus(204)
  183. }
  184. )
  185. },
  186. resendConfirmation,
  187. sendReconfirmation,
  188. showConfirm(req, res, next) {
  189. res.render('user/confirm_email', {
  190. token: req.query.token,
  191. title: 'confirm_email',
  192. })
  193. },
  194. confirm(req, res, next) {
  195. const { token } = req.body
  196. if (!token) {
  197. return res.status(422).json({
  198. message: req.i18n.translate('confirmation_link_broken'),
  199. })
  200. }
  201. UserEmailsConfirmationHandler.confirmEmailFromToken(
  202. token,
  203. function (error) {
  204. if (error) {
  205. if (error instanceof Errors.NotFoundError) {
  206. res.status(404).json({
  207. message: req.i18n.translate('confirmation_token_invalid'),
  208. })
  209. } else {
  210. next(error)
  211. }
  212. } else {
  213. res.sendStatus(200)
  214. }
  215. }
  216. )
  217. },
  218. _handleEmailError(error, req, res, next) {
  219. if (error instanceof Errors.UnconfirmedEmailError) {
  220. return HttpErrorHandler.conflict(req, res, 'email must be confirmed')
  221. } else if (error instanceof Errors.EmailExistsError) {
  222. const message = req.i18n.translate('email_already_registered')
  223. return HttpErrorHandler.conflict(req, res, message)
  224. } else if (error.message === '422: Email does not belong to university') {
  225. const message = req.i18n.translate('email_does_not_belong_to_university')
  226. return HttpErrorHandler.conflict(req, res, message)
  227. }
  228. next(error)
  229. },
  230. }
  231. module.exports = UserEmailsController