From 27fb9aadf3cb4b10ad20fbd05972e93908e5438f Mon Sep 17 00:00:00 2001 From: Jimmy Domagala-Tang Date: Thu, 10 Oct 2024 10:44:38 -0400 Subject: [PATCH] Merge pull request #20937 from overleaf/jdt-ai-addon-grants-feat Grant feature access to users purchasing the ai add-on GitOrigin-RevId: a4183beab957e4d0c362c8f0978be395b86ce398 --- .../Features/Subscription/FeaturesUpdater.js | 22 ++++++++++++++++++- .../Features/Subscription/RecurlyClient.js | 6 +++++ .../Subscription/SubscriptionUpdater.js | 9 ++++++++ services/web/app/src/models/Subscription.js | 1 + 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/services/web/app/src/Features/Subscription/FeaturesUpdater.js b/services/web/app/src/Features/Subscription/FeaturesUpdater.js index 06653086ed..c76934ed84 100644 --- a/services/web/app/src/Features/Subscription/FeaturesUpdater.js +++ b/services/web/app/src/Features/Subscription/FeaturesUpdater.js @@ -15,6 +15,8 @@ const AnalyticsManager = require('../Analytics/AnalyticsManager') const Queues = require('../../infrastructure/Queues') const Modules = require('../../infrastructure/Modules') +const AI_ADDON_CODE = 'assistant' + /** * Enqueue a job for refreshing features for the given user */ @@ -147,7 +149,13 @@ async function _getV1Features(user) { } function _subscriptionToFeatures(subscription) { - return _planCodeToFeatures(subscription && subscription.planCode) + const addonFeatures = _subscriptionAddonsToFeatures( + subscription && subscription.addOns + ) + const planFeatures = _planCodeToFeatures( + subscription && subscription.planCode + ) + return FeaturesHelper.mergeFeatures(addonFeatures, planFeatures) } function _planCodeToFeatures(planCode) { @@ -162,6 +170,18 @@ function _planCodeToFeatures(planCode) { } } +function _subscriptionAddonsToFeatures(addOns) { + if (!addOns) { + return {} + } + const hasAiAddon = addOns.some(addOn => addOn.addOnCode === AI_ADDON_CODE) + if (hasAiAddon) { + return { aiErrorAssistant: true } + } else { + return {} + } +} + async function doSyncFromV1(v1UserId) { logger.debug({ v1UserId }, '[AccountSync] starting account sync') const user = await UserGetter.promises.getUser( diff --git a/services/web/app/src/Features/Subscription/RecurlyClient.js b/services/web/app/src/Features/Subscription/RecurlyClient.js index 3c4002209e..a667366e5a 100644 --- a/services/web/app/src/Features/Subscription/RecurlyClient.js +++ b/services/web/app/src/Features/Subscription/RecurlyClient.js @@ -44,6 +44,10 @@ async function getSubscription(subscriptionId) { return await client.getSubscription(subscriptionId) } +async function getSubscriptionByUuid(subscriptionUuid) { + return await client.getSubscription('uuid-' + subscriptionUuid) +} + async function changeSubscription(subscriptionId, body) { const change = await client.createSubscriptionChange(subscriptionId, body) logger.debug( @@ -101,6 +105,7 @@ module.exports = { getAccountForUserId: callbackify(getAccountForUserId), createAccountForUserId: callbackify(createAccountForUserId), getSubscription: callbackify(getSubscription), + getSubscriptionByUuid: callbackify(getSubscriptionByUuid), changeSubscription: callbackify(changeSubscription), changeSubscriptionByUuid: callbackify(changeSubscriptionByUuid), removeSubscriptionChange: callbackify(removeSubscriptionChange), @@ -111,6 +116,7 @@ module.exports = { promises: { getSubscription, + getSubscriptionByUuid, getAccountForUserId, createAccountForUserId, changeSubscription, diff --git a/services/web/app/src/Features/Subscription/SubscriptionUpdater.js b/services/web/app/src/Features/Subscription/SubscriptionUpdater.js index 29bc36062e..704335955e 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionUpdater.js +++ b/services/web/app/src/Features/Subscription/SubscriptionUpdater.js @@ -305,8 +305,17 @@ async function updateSubscriptionFromRecurly( return } + const addOns = recurlySubscription?.subscription_add_ons?.map(addOn => { + return { + addOnCode: addOn.add_on_code, + quantity: addOn.quantity, + unitAmountInCents: addOn.unit_amount_in_cents, + } + }) + subscription.recurlySubscription_id = recurlySubscription.uuid subscription.planCode = updatedPlanCode + subscription.addOns = addOns || [] subscription.recurlyStatus = { state: recurlySubscription.state, trialStartedAt: recurlySubscription.trial_started_at, diff --git a/services/web/app/src/models/Subscription.js b/services/web/app/src/models/Subscription.js index 9f1a4aeab8..f0afd0bb9a 100644 --- a/services/web/app/src/models/Subscription.js +++ b/services/web/app/src/models/Subscription.js @@ -36,6 +36,7 @@ const SubscriptionSchema = new Schema( managedUsers: { type: Boolean, default: null }, groupSSO: { type: Boolean, default: null }, }, + addOns: Schema.Types.Mixed, overleaf: { id: { type: Number,