فهرست منبع

Merge pull request #14187 from overleaf/mf-update-email-group-invite-general

Add new email template when sending managed users group invitation for existing users

GitOrigin-RevId: e4b4ded9b28400e73f85948f8f10f6fc5a7c01b4
Alexandre Bourdin 3 سال پیش
والد
کامیت
c634267142

+ 71 - 0
services/web/app/src/Features/Email/EmailBuilder.js

@@ -360,6 +360,77 @@ templates.verifyEmailToJoinTeam = ctaTemplate({
   },
 })
 
+templates.verifyEmailToJoinManagedUsers = ctaTemplate({
+  subject(opts) {
+    return `You’ve been invited by ${_.escape(
+      _formatUserNameAndEmail(opts.inviter, 'a collaborator')
+    )} to join an ${settings.appName} group subscription.`
+  },
+  title(opts) {
+    return `You’ve been invited by ${_.escape(
+      _formatUserNameAndEmail(opts.inviter, 'a collaborator')
+    )} to join an ${settings.appName} group subscription.`
+  },
+  message(opts) {
+    return [
+      `By joining this group, you'll have access to ${settings.appName} premium features such as additional collaborators, greater maximum compile time, and real-time track changes.`,
+    ]
+  },
+  secondaryMessage(opts) {
+    return [
+      `<b>User accounts in this group are managed by ${_.escape(
+        _formatUserNameAndEmail(opts.admin, 'an admin')
+      )}</b>`,
+      `If you accept, you’ll transfer the management of your ${settings.appName} account to the owner of the group subscription, who will then have admin rights over your account and control over your stuff.`,
+      `If you have personal projects in your ${settings.appName} account that you want to keep separate, that’s not a problem. You can set up another account under a personal email address and change the ownership of your personal projects to the new account. Find out how to change project owner.`,
+    ]
+  },
+  ctaURL(opts) {
+    return opts.acceptInviteUrl
+  },
+  ctaText(opts) {
+    return 'Accept invitation'
+  },
+  greeting() {
+    return ''
+  },
+})
+
+templates.inviteNewUserToJoinManagedUsers = ctaTemplate({
+  subject(opts) {
+    return `You’ve been invited by ${_.escape(
+      _formatUserNameAndEmail(opts.inviter, 'a collaborator')
+    )} to join an ${settings.appName} group subscription.`
+  },
+  title(opts) {
+    return `You’ve been invited by ${_.escape(
+      _formatUserNameAndEmail(opts.inviter, 'a collaborator')
+    )} to join an ${settings.appName} group subscription.`
+  },
+  message(opts) {
+    return ['']
+  },
+  secondaryMessage(opts) {
+    return [
+      `User accounts in this group are managed by ${_.escape(
+        _formatUserNameAndEmail(opts.admin, 'an admin')
+      )}`,
+      `If you accept the owner of the group subscription will have admin rights over your account and control over your stuff.`,
+      `<b>What is ${settings.appName}?</b>`,
+      `${settings.appName} is the collaborative online LaTeX editor loved by researchers and technical writers. With thousands of ready-to-use templates and an array of LaTeX learning resources you’ll be up and running in no time.`,
+    ]
+  },
+  ctaURL(opts) {
+    return opts.acceptInviteUrl
+  },
+  ctaText(opts) {
+    return 'Accept invitation'
+  },
+  greeting() {
+    return ''
+  },
+})
+
 templates.testEmail = ctaTemplate({
   subject() {
     return `A Test Email from ${settings.appName}`

+ 12 - 0
services/web/app/src/Features/Subscription/SubscriptionLocator.js

@@ -40,6 +40,17 @@ const SubscriptionLocator = {
       .exec(callback)
   },
 
+  getAdminEmailAndName(subscriptionId, callback) {
+    Subscription.findById(subscriptionId)
+      .populate('admin_id', ['email', 'first_name', 'last_name'])
+      .exec((err, subscription) => {
+        if (err) {
+          return callback(err)
+        }
+        callback(err, subscription?.admin_id)
+      })
+  },
+
   hasRecurlyGroupSubscription(userOrId, callback) {
     const userId = SubscriptionLocator._getUserId(userOrId)
     Subscription.exists(
@@ -111,6 +122,7 @@ SubscriptionLocator.promises = {
     SubscriptionLocator.getManagedGroupSubscriptions
   ),
   getMemberSubscriptions: promisify(SubscriptionLocator.getMemberSubscriptions),
+  getAdminEmailAndName: promisify(SubscriptionLocator.getAdminEmailAndName),
   getSubscription: promisify(SubscriptionLocator.getSubscription),
   getSubscriptionByMemberIdAndId: promisify(
     SubscriptionLocator.getSubscriptionByMemberIdAndId

+ 44 - 6
services/web/app/src/Features/Subscription/TeamInvitesHandler.js

@@ -1,4 +1,5 @@
 const logger = require('@overleaf/logger')
+const OError = require('@overleaf/o-error')
 const crypto = require('crypto')
 
 const settings = require('@overleaf/settings')
@@ -147,13 +148,50 @@ async function _createInvite(subscription, email, inviter) {
 
   await subscription.save()
 
-  const opts = {
-    to: email,
-    inviter,
-    acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${invite.token}/`,
-    appName: settings.appName,
+  if (subscription.groupPolicy) {
+    let admin = {}
+    try {
+      admin = await SubscriptionLocator.promises.getAdminEmailAndName(
+        subscription._id
+      )
+    } catch (error) {
+      logger.error(
+        OError.tag(error, 'error getting subscription admin email and name')
+      )
+    }
+
+    const user = await UserGetter.promises.getUserByAnyEmail(email)
+
+    const opts = {
+      to: email,
+      admin,
+      inviter,
+      acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${invite.token}/`,
+      appName: settings.appName,
+    }
+
+    if (user) {
+      await EmailHandler.promises.sendEmail(
+        'verifyEmailToJoinManagedUsers',
+        opts
+      )
+    } else {
+      await EmailHandler.promises.sendEmail(
+        'inviteNewUserToJoinManagedUsers',
+        opts
+      )
+    }
+  } else {
+    const opts = {
+      to: email,
+      inviter,
+      acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${invite.token}/`,
+      appName: settings.appName,
+    }
+
+    await EmailHandler.promises.sendEmail('verifyEmailToJoinTeam', opts)
   }
-  await EmailHandler.promises.sendEmail('verifyEmailToJoinTeam', opts)
+
   Object.assign(invite, { invite: true })
   return invite
 }