UserCreator.mjs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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.recordEventForMongoUserInBackground(
  44. user,
  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. if (!attributes.analyticsId) {
  54. throw new Error('bug: attributes.analyticsId is missing')
  55. }
  56. let user = new User()
  57. if (attributes.first_name == null || attributes.first_name === '') {
  58. attributes.first_name = attributes.email.split('@')[0]
  59. }
  60. Object.assign(user, attributes)
  61. user.ace.syntaxValidation = true
  62. const reversedHostname = user.email.split('@')[1].split('').reverse().join('')
  63. const emailData = {
  64. email: user.email,
  65. createdAt: new Date(),
  66. reversedHostname,
  67. }
  68. if (Features.hasFeature('affiliations') && !options.requireAffiliation) {
  69. emailData.affiliationUnchecked = true
  70. }
  71. if (
  72. attributes.samlIdentifiers &&
  73. attributes.samlIdentifiers[0] &&
  74. attributes.samlIdentifiers[0].providerId
  75. ) {
  76. emailData.samlProviderId = attributes.samlIdentifiers[0].providerId
  77. }
  78. const affiliationOptions = options.affiliationOptions || {}
  79. if (options.confirmedAt) {
  80. emailData.confirmedAt = options.confirmedAt
  81. affiliationOptions.confirmedAt = options.confirmedAt
  82. }
  83. user.emails = [emailData]
  84. user = await user.save()
  85. if (Features.hasFeature('affiliations')) {
  86. try {
  87. user = await _addAffiliation(user, affiliationOptions)
  88. } catch (error) {
  89. if (options.requireAffiliation) {
  90. await UserDeleter.promises.deleteMongoUser(user._id)
  91. throw OError.tag(error)
  92. } else {
  93. const err = OError.tag(error, 'adding affiliations failed')
  94. logger.error({ err, userId: user._id }, err.message)
  95. }
  96. }
  97. }
  98. await recordRegistrationEvent(user)
  99. await Analytics.setUserPropertyForMongoUser(user, 'created-at', new Date())
  100. await Analytics.setUserPropertyForMongoUser(user, 'user-id', user._id)
  101. if (attributes.analyticsId) {
  102. await Analytics.setUserPropertyForMongoUser(
  103. user,
  104. 'analytics-id',
  105. attributes.analyticsId
  106. )
  107. }
  108. if (Features.hasFeature('saas')) {
  109. try {
  110. await UserOnboardingEmailManager.scheduleOnboardingEmail(user)
  111. await UserPostRegistrationAnalyticsManager.schedulePostRegistrationAnalytics(
  112. user
  113. )
  114. } catch (error) {
  115. logger.error(
  116. OError.tag(error, 'Failed to schedule sending of onboarding email', {
  117. userId: user._id,
  118. })
  119. )
  120. }
  121. }
  122. return user
  123. }
  124. const UserCreator = {
  125. createNewUser: util.callbackify(createNewUser),
  126. promises: {
  127. createNewUser,
  128. },
  129. }
  130. export default UserCreator