From 7d8e18c802958b5618601d915b54958a77afe465 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 3 Jun 2021 15:44:43 +0530 Subject: [PATCH] Added migration to revert portal_plans setting to named values closes https://github.com/TryGhost/Team/issues/753 Currently, the portal_plans setting is storing price ids for active monthly/yearly prices for the default product, which was done to allow multiple prices in Portal. Since we only want to limit the prices for a Product to monthly/yearly, we are reverting the earlier migration and only store the available prices as monthly / yearly in portal setting instead of ids. Its also in sync with the approach in theme/API where we use named prices for monthly/yearly instead of price id list. --- ghost/members-api/index.js | 2 + ghost/members-api/lib/migrations/index.js | 70 +++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/ghost/members-api/index.js b/ghost/members-api/index.js index 55badd04cb..b23b02f764 100644 --- a/ghost/members-api/index.js +++ b/ghost/members-api/index.js @@ -167,6 +167,8 @@ module.exports = function MembersApi({ return stripeMigrations.populateDefaultProductMonthlyPriceId(); }).then(() => { return stripeMigrations.populateDefaultProductYearlyPriceId(); + }).then(() => { + return stripeMigrations.revertPortalPlansSetting(); }), stripeWebhookService.configure({ webhookSecret: process.env.WEBHOOK_SECRET, diff --git a/ghost/members-api/lib/migrations/index.js b/ghost/members-api/lib/migrations/index.js index e415280129..22ec970945 100644 --- a/ghost/members-api/lib/migrations/index.js +++ b/ghost/members-api/lib/migrations/index.js @@ -113,6 +113,20 @@ module.exports = class StripeMigrations { return price; } + async getPlanFromPrice(priceId) { + const price = await this._StripePrice.findOne({ + id: priceId + }); + + if (price && price.get('interval') === 'month') { + return 'monthly'; + } + if (price && price.get('interval') === 'year') { + return 'yearly'; + } + return null; + } + async populateStripePricesFromStripePlansSetting(plans) { if (!plans) { this._logging.info('Skipping stripe_plans -> stripe_prices migration'); @@ -410,4 +424,60 @@ module.exports = class StripeMigrations { await this._Product.edit({yearly_price_id: yearlyPriceId}, {id: defaultProduct.id}); } + + async revertPortalPlansSetting() { + this._logging.info('Migrating portal_plans setting from ids to names'); + const portalPlansSetting = await this._Settings.findOne({key: 'portal_plans'}); + + let portalPlans; + try { + portalPlans = JSON.parse(portalPlansSetting.get('value')); + } catch (err) { + this._logging.error({ + message: 'Could not parse portal_plans setting, skipping migration', + err + }); + return; + } + + const containsNamedValues = !!portalPlans.find((plan) => { + return ['monthly', 'yearly'].includes(plan); + }); + + if (containsNamedValues) { + this._logging.info('The portal_plans setting already contains names, skipping migration'); + return; + } + const portalPlanIds = portalPlans.filter((plan) => { + return plan !== 'free'; + }); + + if (portalPlanIds.length === 0) { + this._logging.info('No price ids found in portal_plans setting, skipping migration'); + return; + } + const defaultPortalPlans = portalPlans.filter((plan) => { + return plan === 'free'; + }); + + const newPortalPlans = await portalPlanIds.reduce(async (newPortalPlansPromise, priceId) => { + const plan = await this.getPlanFromPrice(priceId); + + if (!plan) { + return newPortalPlansPromise; + } + + const newPortalPlans = await newPortalPlansPromise; + const updatedPortalPlans = newPortalPlans.filter(d => d !== plan).concat(plan); + + return updatedPortalPlans; + }, defaultPortalPlans); + this._logging.info(`Updating portal_plans setting to ${JSON.stringify(newPortalPlans)}`); + await this._Settings.edit({ + key: 'portal_plans', + value: JSON.stringify(newPortalPlans) + }, { + id: portalPlansSetting.id + }); + } };