UserCreator.mjs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import logger from '@overleaf/logger'
  2. import util from 'node:util'
  3. import { AffiliationError } from '../Errors/Errors.js'
  4. import Features from '../../infrastructure/Features.mjs'
  5. import { User } from '../../models/User.mjs'
  6. import UserDeleter from './UserDeleter.mjs'
  7. import UserGetter from './UserGetter.mjs'
  8. import UserUpdater from './UserUpdater.mjs'
  9. import Analytics from '../Analytics/AnalyticsManager.mjs'
  10. import UserOnboardingEmailManager from './UserOnboardingEmailManager.mjs'
  11. import UserPostRegistrationAnalyticsManager from './UserPostRegistrationAnalyticsManager.mjs'
  12. import OError from '@overleaf/o-error'
  13. async function _addAffiliation(user, affiliationOptions) {
  14. try {
  15. await UserUpdater.promises.addAffiliationForNewUser(
  16. user._id,
  17. user.email,
  18. affiliationOptions
  19. )
  20. } catch (error) {
  21. throw new AffiliationError('add affiliation failed').withCause(error)
  22. }
  23. try {
  24. user = await UserGetter.promises.getUser(user._id)
  25. } catch (error) {
  26. logger.error(
  27. OError.tag(error, 'could not get fresh user data', {
  28. userId: user._id,
  29. email: user.email,
  30. })
  31. )
  32. }
  33. return user
  34. }
  35. async function recordRegistrationEvent(user) {
  36. try {
  37. const segmentation = {
  38. 'home-registration': 'default',
  39. }
  40. if (user.thirdPartyIdentifiers && user.thirdPartyIdentifiers.length > 0) {
  41. segmentation.provider = user.thirdPartyIdentifiers[0].providerId
  42. }
  43. Analytics.recordEventForUserInBackground(
  44. user._id,
  45. 'user-registered',
  46. segmentation
  47. )
  48. } catch (err) {
  49. logger.warn({ err }, 'there was an error recording `user-registered` event')
  50. }
  51. }
  52. async function createNewUser(attributes, options = {}) {
  53. let user = new User()
  54. if (attributes.first_name == null || attributes.first_name === '') {
  55. attributes.first_name = attributes.email.split('@')[0]
  56. }
  57. Object.assign(user, attributes)
  58. user.ace.syntaxValidation = true
  59. const reversedHostname = user.email.split('@')[1].split('').reverse().join('')
  60. const emailData = {
  61. email: user.email,
  62. createdAt: new Date(),
  63. reversedHostname,
  64. }
  65. if (Features.hasFeature('affiliations') && !options.requireAffiliation) {
  66. emailData.affiliationUnchecked = true
  67. }
  68. if (
  69. attributes.samlIdentifiers &&
  70. attributes.samlIdentifiers[0] &&
  71. attributes.samlIdentifiers[0].providerId
  72. ) {
  73. emailData.samlProviderId = attributes.samlIdentifiers[0].providerId
  74. }
  75. const affiliationOptions = options.affiliationOptions || {}
  76. if (options.confirmedAt) {
  77. emailData.confirmedAt = options.confirmedAt
  78. affiliationOptions.confirmedAt = options.confirmedAt
  79. }
  80. user.emails = [emailData]
  81. user = await user.save()
  82. if (Features.hasFeature('affiliations')) {
  83. try {
  84. user = await _addAffiliation(user, affiliationOptions)
  85. } catch (error) {
  86. if (options.requireAffiliation) {
  87. await UserDeleter.promises.deleteMongoUser(user._id)
  88. throw OError.tag(error)
  89. } else {
  90. const err = OError.tag(error, 'adding affiliations failed')
  91. logger.error({ err, userId: user._id }, err.message)
  92. }
  93. }
  94. }
  95. await recordRegistrationEvent(user)
  96. await Analytics.setUserPropertyForUser(user._id, 'created-at', new Date())
  97. await Analytics.setUserPropertyForUser(user._id, 'user-id', user._id)
  98. if (attributes.analyticsId) {
  99. await Analytics.setUserPropertyForUser(
  100. user._id,
  101. 'analytics-id',
  102. attributes.analyticsId
  103. )
  104. }
  105. if (Features.hasFeature('saas')) {
  106. try {
  107. await UserOnboardingEmailManager.scheduleOnboardingEmail(user)
  108. await UserPostRegistrationAnalyticsManager.schedulePostRegistrationAnalytics(
  109. user
  110. )
  111. } catch (error) {
  112. logger.error(
  113. OError.tag(error, 'Failed to schedule sending of onboarding email', {
  114. userId: user._id,
  115. })
  116. )
  117. }
  118. }
  119. return user
  120. }
  121. const UserCreator = {
  122. createNewUser: util.callbackify(createNewUser),
  123. promises: {
  124. createNewUser,
  125. },
  126. }
  127. export default UserCreator