Просмотр исходного кода

[web] Send email to support when skipping deleting pro group subscription (#19971)

* Move group SSO enabled check up

So that we have this available when managed users is enabled. This will be useful in the following commit.

* Notify support when subscription deletion skipped

* Fix rebase conflicts

---------

Co-authored-by: mserranom <mserranom@gmail.com>
GitOrigin-RevId: 8a4abe0742ab6a1c6b15bb17b5cc4863a11010b2
Jessica Lawshe 1 год назад
Родитель
Сommit
4d8a6c5c9d

+ 64 - 16
services/web/app/src/Features/Subscription/SubscriptionUpdater.js

@@ -11,6 +11,8 @@ const logger = require('@overleaf/logger')
 const Features = require('../../infrastructure/Features')
 const UserAuditLogHandler = require('../User/UserAuditLogHandler')
 const { SSOConfig } = require('../../models/SSOConfig')
+const Modules = require('../../infrastructure/Modules')
+const Settings = require('@overleaf/settings')
 
 /**
  * Change the admin of the given subscription.
@@ -249,6 +251,29 @@ async function _deleteAndReplaceSubscriptionFromRecurly(
   )
 }
 
+async function _notifySupportSubscriptionDeletionSkipped(
+  subscription,
+  recurlySubscription,
+  hasGroupSSOEnabled
+) {
+  const adminUrl = `${Settings.adminUrl + '/admin/user/' + subscription.admin_id}`
+  const groupUrl = `${Settings.adminUrl + '/admin/group/' + subscription._id}`
+  let message = `\n**Recurly account:** <a href="${recurlySubscription?.account?.url}">${recurlySubscription?.account?.url}</a>`
+  message += `\n**Group admin:** <a href="${adminUrl}">${adminUrl}</a>`
+  message += `\n**Group:** <a href="${groupUrl}">${groupUrl}</a>`
+  message += `\n**Managed users enabled:** ${subscription?.managedUsersEnabled}`
+  message += `\n**SSO enabled:** ${hasGroupSSOEnabled}`
+
+  const data = {
+    subject: 'Skipped deleting pro group subscription',
+    inbox: 'support',
+    tags: 'Group subscription',
+    message,
+  }
+
+  await Modules.promises.hooks.fire('sendSupportRequest', data)
+}
+
 async function updateSubscriptionFromRecurly(
   recurlySubscription,
   subscription,
@@ -258,6 +283,18 @@ async function updateSubscriptionFromRecurly(
     const hasManagedUsersFeature =
       Features.hasFeature('saas') && subscription?.managedUsersEnabled
 
+    let hasGroupSSOEnabled = false
+    if (subscription?.ssoConfig) {
+      const ssoConfig = await SSOConfig.findOne({
+        _id: subscription.ssoConfig._id || subscription.ssoConfig,
+      })
+        .lean()
+        .exec()
+      if (ssoConfig.enabled) {
+        hasGroupSSOEnabled = true
+      }
+    }
+
     // If a payment lapses and if the group is managed or has group SSO, as a temporary measure we need to
     // make sure that the group continues as-is and no destructive actions are taken.
     if (hasManagedUsersFeature) {
@@ -265,28 +302,39 @@ async function updateSubscriptionFromRecurly(
         { subscriptionId: subscription._id },
         'expired subscription has managedUsers feature enabled, skipping deletion'
       )
-    } else {
-      let hasGroupSSOEnabled = false
-      if (subscription?.ssoConfig) {
-        const ssoConfig = await SSOConfig.findOne({
-          _id: subscription.ssoConfig._id || subscription.ssoConfig,
-        })
-          .lean()
-          .exec()
-        if (ssoConfig.enabled) {
-          hasGroupSSOEnabled = true
-        }
+      try {
+        await _notifySupportSubscriptionDeletionSkipped(
+          subscription,
+          recurlySubscription,
+          hasGroupSSOEnabled
+        )
+      } catch (e) {
+        logger.warn(
+          { subscriptionId: subscription._id },
+          'unable to send notification to support that subscription deletion was skipped'
+        )
       }
-
-      if (hasGroupSSOEnabled) {
+    } else if (hasGroupSSOEnabled) {
+      logger.warn(
+        { subscriptionId: subscription._id },
+        'expired subscription has groupSSO feature enabled, skipping deletion'
+      )
+      try {
+        await _notifySupportSubscriptionDeletionSkipped(
+          subscription,
+          recurlySubscription,
+          hasGroupSSOEnabled
+        )
+      } catch (e) {
         logger.warn(
           { subscriptionId: subscription._id },
-          'expired subscription has groupSSO feature enabled, skipping deletion'
+          'unable to send notification to support that subscription deletion was skipped'
         )
-      } else {
-        await deleteSubscription(subscription, requesterData)
       }
+    } else {
+      await deleteSubscription(subscription, requesterData)
     }
+
     return
   }
   const updatedPlanCode = recurlySubscription.plan.plan_code

+ 58 - 0
services/web/test/unit/src/Subscription/SubscriptionUpdaterTests.js

@@ -13,6 +13,9 @@ describe('SubscriptionUpdater', function () {
       plan: {
         plan_code: this.recurlyPlan.planCode,
       },
+      account: {
+        url: 'test_url',
+      },
     }
 
     this.adminUser = { _id: (this.adminuser_id = '5208dd34438843e2db000007') }
@@ -26,6 +29,7 @@ describe('SubscriptionUpdater', function () {
       save: sinon.stub().resolves(),
       planCode: 'student_or_something',
       recurlySubscription_id: 'abc123def456fab789',
+      managedUsersEnabled: false,
     }
     this.user_id = this.adminuser_id
 
@@ -120,6 +124,7 @@ describe('SubscriptionUpdater', function () {
           },
         },
       ],
+      adminUrl: 'test_admin_url',
     }
 
     this.UserFeaturesUpdater = {
@@ -177,6 +182,13 @@ describe('SubscriptionUpdater', function () {
         '../Analytics/AnalyticsManager': this.AnalyticsManager,
         '../../infrastructure/Features': this.Features,
         '../User/UserAuditLogHandler': this.UserAuditLogHandler,
+        '../../infrastructure/Modules': (this.Modules = {
+          promises: {
+            hooks: {
+              fire: sinon.stub().resolves(),
+            },
+          },
+        }),
       },
     })
   })
@@ -316,6 +328,52 @@ describe('SubscriptionUpdater', function () {
         {}
       )
       this.SubscriptionModel.deleteOne.should.not.have.been.called
+      const adminUrl = `${this.Settings.adminUrl + '/admin/user/' + this.subscription.admin_id}`
+      const groupUrl = `${this.Settings.adminUrl + '/admin/group/' + this.subscription._id}`
+      let message = `\n**Recurly account:** <a href="${this.recurlySubscription?.account?.url}">${this.recurlySubscription.account?.url}</a>`
+      message += `\n**Group admin:** <a href="${adminUrl}">${adminUrl}</a>`
+      message += `\n**Group:** <a href="${groupUrl}">${groupUrl}</a>`
+      message += `\n**Managed users enabled:** false`
+      message += `\n**SSO enabled:** true`
+      expect(this.Modules.promises.hooks.fire).to.have.been.calledOnce
+      expect(this.Modules.promises.hooks.fire).to.have.been.calledWith(
+        'sendSupportRequest',
+        {
+          subject: 'Skipped deleting pro group subscription',
+          inbox: 'support',
+          tags: 'Group subscription',
+          message,
+        }
+      )
+    })
+
+    it('should not remove the subscription when expired if it has managed users is enabled', async function () {
+      this.Features.hasFeature.withArgs('saas').returns(true)
+      this.subscription.managedUsersEnabled = true
+
+      this.recurlySubscription.state = 'expired'
+      await this.SubscriptionUpdater.promises.updateSubscriptionFromRecurly(
+        this.recurlySubscription,
+        this.subscription,
+        {}
+      )
+      this.SubscriptionModel.deleteOne.should.not.have.been.called
+      const adminUrl = `${this.Settings.adminUrl + '/admin/user/' + this.subscription.admin_id}`
+      const groupUrl = `${this.Settings.adminUrl + '/admin/group/' + this.subscription._id}`
+      let message = `\n**Recurly account:** <a href="${this.recurlySubscription?.account?.url}">${this.recurlySubscription.account?.url}</a>`
+      message += `\n**Group admin:** <a href="${adminUrl}">${adminUrl}</a>`
+      message += `\n**Group:** <a href="${groupUrl}">${groupUrl}</a>`
+      message += `\n**Managed users enabled:** true`
+      message += `\n**SSO enabled:** false`
+      expect(this.Modules.promises.hooks.fire).to.have.been.calledWith(
+        'sendSupportRequest',
+        {
+          subject: 'Skipped deleting pro group subscription',
+          inbox: 'support',
+          tags: 'Group subscription',
+          message,
+        }
+      )
     })
 
     it('should update all the users features', async function () {