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

Merge pull request #21794 from overleaf/em-validate-plan-add-on

Add-on validation improvements

GitOrigin-RevId: 6812172fb431495ce34c2741c7c2c7c0d33685a6
Eric Mc Sween 1 год назад
Родитель
Сommit
6c6ed06677

+ 2 - 3
services/web/app/src/Features/Subscription/FeaturesUpdater.js

@@ -14,8 +14,7 @@ const UserGetter = require('../User/UserGetter')
 const AnalyticsManager = require('../Analytics/AnalyticsManager')
 const Queues = require('../../infrastructure/Queues')
 const Modules = require('../../infrastructure/Modules')
-
-const AI_ADDON_CODE = 'assistant'
+const { AI_ADD_ON_CODE } = require('./RecurlyEntities')
 
 /**
  * Enqueue a job for refreshing features for the given user
@@ -174,7 +173,7 @@ function _subscriptionAddonsToFeatures(addOns) {
   if (!addOns) {
     return {}
   }
-  const hasAiAddon = addOns.some(addOn => addOn.addOnCode === AI_ADDON_CODE)
+  const hasAiAddon = addOns.some(addOn => addOn.addOnCode === AI_ADD_ON_CODE)
   if (hasAiAddon) {
     return { aiErrorAssistant: true }
   } else {

+ 3 - 0
services/web/app/src/Features/Subscription/RecurlyEntities.js

@@ -5,6 +5,8 @@ const { DuplicateAddOnError, AddOnNotPresentError } = require('./Errors')
 const PlansLocator = require('./PlansLocator')
 const SubscriptionHelper = require('./SubscriptionHelper')
 
+const AI_ADD_ON_CODE = 'assistant'
+
 class RecurlySubscription {
   /**
    * @param {object} props
@@ -261,6 +263,7 @@ class RecurlyAddOn {
 }
 
 module.exports = {
+  AI_ADD_ON_CODE,
   RecurlySubscription,
   RecurlySubscriptionAddOn,
   RecurlySubscriptionChange,

+ 4 - 5
services/web/app/src/Features/Subscription/SubscriptionController.js

@@ -28,13 +28,12 @@ const SubscriptionFormatters = require('./SubscriptionFormatters')
 const HttpErrorHandler = require('../Errors/HttpErrorHandler')
 const { URLSearchParams } = require('url')
 const RecurlyClient = require('./RecurlyClient')
+const { AI_ADD_ON_CODE } = require('./RecurlyEntities')
 
 /**
  * @import { SubscriptionChangePreview } from '../../../../types/subscription/subscription-change-preview'
  */
 
-const AI_ADDON_CODES = ['assistant', 'assistant-annual']
-
 const groupPlanModalOptions = Settings.groupPlanModalOptions
 const validGroupPlanModalOptions = {
   plan_code: groupPlanModalOptions.plan_codes.map(item => item.code),
@@ -489,7 +488,7 @@ async function previewAddonPurchase(req, res) {
   const userId = SessionManager.getLoggedInUserId(req.session)
   const addOnCode = req.params.addOnCode
 
-  if (!AI_ADDON_CODES.includes(addOnCode)) {
+  if (addOnCode !== AI_ADD_ON_CODE) {
     return HttpErrorHandler.notFound(req, res, `Unknown add-on: ${addOnCode}`)
   }
 
@@ -559,7 +558,7 @@ async function purchaseAddon(req, res, next) {
   // currently we only support having a quantity of 1
   const quantity = 1
   // currently we only support one add-on, the Ai add-on
-  if (!AI_ADDON_CODES.includes(addOnCode)) {
+  if (addOnCode !== AI_ADD_ON_CODE) {
     return res.sendStatus(404)
   }
 
@@ -591,7 +590,7 @@ async function removeAddon(req, res, next) {
   const user = SessionManager.getSessionUser(req.session)
   const addOnCode = req.params.addOnCode
 
-  if (!AI_ADDON_CODES.includes(addOnCode)) {
+  if (addOnCode !== AI_ADD_ON_CODE) {
     return res.sendStatus(404)
   }
 

+ 24 - 1
services/web/app/src/Features/Subscription/SubscriptionHandler.js

@@ -1,5 +1,6 @@
 // @ts-check
 
+const recurly = require('recurly')
 const RecurlyWrapper = require('./RecurlyWrapper')
 const RecurlyClient = require('./RecurlyClient')
 const { User } = require('../../models/User')
@@ -11,9 +12,9 @@ const EmailHandler = require('../Email/EmailHandler')
 const { callbackify } = require('@overleaf/promise-utils')
 const UserUpdater = require('../User/UserUpdater')
 const { NoRecurlySubscriptionError } = require('./Errors')
+const { NotFoundError } = require('../Errors/Errors')
 
 /**
- * @import recurly from 'recurly'
  * @import { RecurlySubscription, RecurlySubscriptionChange } from './RecurlyEntities'
  */
 
@@ -297,6 +298,17 @@ async function previewAddonPurchase(userId, addOnCode) {
   }
 
   const subscription = await RecurlyClient.promises.getSubscription(recurlyId)
+  try {
+    await RecurlyClient.promises.getAddOn(subscription.planCode, addOnCode)
+  } catch (err) {
+    if (err instanceof recurly.errors.NotFoundError) {
+      throw new NotFoundError({
+        message: 'Add-on not found',
+        info: { addOnCode },
+      })
+    }
+    throw err
+  }
   const changeRequest = subscription.getRequestForAddOnPurchase(addOnCode)
   const change =
     await RecurlyClient.promises.previewSubscriptionChange(changeRequest)
@@ -305,6 +317,17 @@ async function previewAddonPurchase(userId, addOnCode) {
 
 async function purchaseAddon(user, addOnCode, quantity) {
   const subscription = await _getSubscription(user)
+  try {
+    await RecurlyClient.promises.getAddOn(subscription.planCode, addOnCode)
+  } catch (err) {
+    if (err instanceof recurly.errors.NotFoundError) {
+      throw new NotFoundError({
+        message: 'Add-on not found',
+        info: { addOnCode },
+      })
+    }
+    throw err
+  }
   const changeRequest = subscription.getRequestForAddOnPurchase(
     addOnCode,
     quantity