From 26ee64839799f6d9a111d18ccbc36f791340c37c Mon Sep 17 00:00:00 2001 From: Rishabh Garg Date: Thu, 28 Jan 2021 22:55:38 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=97=20Flattened=20members=20subscripti?= =?UTF-8?q?ons=20data=20in=20API=20(#12581)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no refs - Updates member model serializer to directly set subscriptions on member object instead of `stripe.subscriptions` - Updates all references to members subscriptions from nested `stripe.subscriptions` to `subscriptions` - Updates v3 API serializer to still use `stripe.subscriptions` - Updates tests --- core/frontend/services/themes/middleware.js | 2 +- .../utils/serializers/output/members.js | 9 ++++---- .../v3/utils/serializers/output/members.js | 10 ++++++--- core/server/models/member.js | 4 +--- core/server/services/members/middleware.js | 2 +- core/server/services/members/utils.js | 2 +- test/api-acceptance/admin/members_spec.js | 22 +++++++++---------- .../api/canary/admin/members_spec.js | 20 ++++++++--------- test/unit/services/members/middleware_spec.js | 8 +++---- 9 files changed, 40 insertions(+), 39 deletions(-) diff --git a/core/frontend/services/themes/middleware.js b/core/frontend/services/themes/middleware.js index 7171cc4c3d..e93dc7f8b9 100644 --- a/core/frontend/services/themes/middleware.js +++ b/core/frontend/services/themes/middleware.js @@ -132,7 +132,7 @@ function updateLocalTemplateOptions(req, res, next) { name: req.member.name, firstname: req.member.name && req.member.name.split(' ')[0], avatar_image: req.member.avatar_image, - subscriptions: req.member.stripe.subscriptions, + subscriptions: req.member.subscriptions, paid: req.member.status === 'paid' } : null; diff --git a/core/server/api/canary/utils/serializers/output/members.js b/core/server/api/canary/utils/serializers/output/members.js index 4b1db072a2..741a77304c 100644 --- a/core/server/api/canary/utils/serializers/output/members.js +++ b/core/server/api/canary/utils/serializers/output/members.js @@ -73,8 +73,8 @@ function serializeMember(member, options) { const json = member.toJSON(options); let comped = false; - if (json.stripe && json.stripe.subscriptions) { - const hasCompedSubscription = !!json.stripe.subscriptions.find( + if (json.subscriptions) { + const hasCompedSubscription = !!json.subscriptions.find( /** * @param {SerializedMemberStripeSubscription} sub */ @@ -86,6 +86,7 @@ function serializeMember(member, options) { comped = true; } } + const subscriptions = json.subscriptions || []; return { id: json.id, @@ -98,7 +99,7 @@ function serializeMember(member, options) { created_at: json.created_at, updated_at: json.updated_at, labels: json.labels, - stripe: json.stripe, + subscriptions: subscriptions, avatar_image: json.avatar_image, comped: comped, email_count: json.email_count, @@ -146,7 +147,7 @@ function createSerializer(debugString, serialize) { * @prop {string} created_at * @prop {string} updated_at * @prop {string[]} labels - * @prop {null|SerializedMemberStripeData} stripe + * @prop {SerializedMemberStripeSubscription[]} subscriptions * @prop {string} avatar_image * @prop {boolean} comped * @prop {number} email_count diff --git a/core/server/api/v3/utils/serializers/output/members.js b/core/server/api/v3/utils/serializers/output/members.js index 8cebf2a5dd..4df5c2e9ac 100644 --- a/core/server/api/v3/utils/serializers/output/members.js +++ b/core/server/api/v3/utils/serializers/output/members.js @@ -73,8 +73,12 @@ function serializeMember(member, options) { const json = member.toJSON(options); let comped = false; - if (json.stripe && json.stripe.subscriptions) { - const hasCompedSubscription = !!json.stripe.subscriptions.find( + let stripe = null; + if (json.subscriptions) { + stripe = { + subscriptions: json.subscriptions + }; + const hasCompedSubscription = !!json.subscriptions.find( /** * @param {SerializedMemberStripeSubscription} sub */ @@ -98,7 +102,7 @@ function serializeMember(member, options) { created_at: json.created_at, updated_at: json.updated_at, labels: json.labels, - stripe: json.stripe, + stripe: stripe, avatar_image: json.avatar_image, comped: comped, email_count: json.email_count, diff --git a/core/server/models/member.js b/core/server/models/member.js index 475da7af8a..8250de407f 100644 --- a/core/server/models/member.js +++ b/core/server/models/member.js @@ -67,9 +67,7 @@ const Member = ghostBookshelf.Model.extend({ const defaultSerializedObject = ghostBookshelf.Model.prototype.serialize.call(this, options); if (defaultSerializedObject.stripeSubscriptions) { - defaultSerializedObject.stripe = { - subscriptions: defaultSerializedObject.stripeSubscriptions - }; + defaultSerializedObject.subscriptions = defaultSerializedObject.stripeSubscriptions; delete defaultSerializedObject.stripeSubscriptions; } diff --git a/core/server/services/members/middleware.js b/core/server/services/members/middleware.js index 41dafa517d..e7b404ffef 100644 --- a/core/server/services/members/middleware.js +++ b/core/server/services/members/middleware.js @@ -136,7 +136,7 @@ const createSessionFromMagicLink = async function (req, res, next) { try { const member = await membersService.ssr.exchangeTokenForSession(req, res); - const subscriptions = member && member.stripe && member.stripe.subscriptions || []; + const subscriptions = member && member.subscriptions || []; const action = req.query.action; diff --git a/core/server/services/members/utils.js b/core/server/services/members/utils.js index ffd2fddac0..bc9285c99e 100644 --- a/core/server/services/members/utils.js +++ b/core/server/services/members/utils.js @@ -9,7 +9,7 @@ module.exports.formattedMemberResponse = function formattedMemberResponse(member firstname: member.name && member.name.split(' ')[0], avatar_image: member.avatar_image, subscribed: !!member.subscribed, - subscriptions: member.stripe ? member.stripe.subscriptions : [], + subscriptions: member.subscriptions || [], paid: member.status === 'paid' }; }; diff --git a/test/api-acceptance/admin/members_spec.js b/test/api-acceptance/admin/members_spec.js index 4097220ea3..7d527777de 100644 --- a/test/api-acceptance/admin/members_spec.js +++ b/test/api-acceptance/admin/members_spec.js @@ -37,7 +37,7 @@ describe('Members API', function () { should.exist(jsonResponse); should.exist(jsonResponse.members); jsonResponse.members.should.have.length(4); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); testUtils.API.isISO8601(jsonResponse.members[0].created_at).should.be.true(); jsonResponse.members[0].created_at.should.be.an.instanceof(String); @@ -64,7 +64,7 @@ describe('Members API', function () { should.exist(jsonResponse.members); jsonResponse.members.should.have.length(1); localUtils.API.checkResponse(jsonResponse, 'members'); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); }); @@ -83,7 +83,7 @@ describe('Members API', function () { jsonResponse.members.should.have.length(1); jsonResponse.members[0].email.should.equal('member1@test.com'); localUtils.API.checkResponse(jsonResponse, 'members'); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); }); @@ -103,7 +103,7 @@ describe('Members API', function () { jsonResponse.members[0].email.should.equal('paid@test.com'); jsonResponse.members[1].email.should.equal('trialing@test.com'); localUtils.API.checkResponse(jsonResponse, 'members'); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); }); @@ -120,7 +120,7 @@ describe('Members API', function () { should.exist(jsonResponse); should.exist(jsonResponse.members); jsonResponse.members.should.have.length(1); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); }); it('Can read and include email_recipients', async function () { @@ -136,7 +136,7 @@ describe('Members API', function () { should.exist(jsonResponse); should.exist(jsonResponse.members); jsonResponse.members.should.have.length(1); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', ['stripe', 'email_recipients']); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', ['subscriptions', 'email_recipients']); jsonResponse.members[0].email_recipients.length.should.equal(1); localUtils.API.checkResponse(jsonResponse.members[0].email_recipients[0], 'email_recipient', ['email']); localUtils.API.checkResponse(jsonResponse.members[0].email_recipients[0].email, 'email'); @@ -235,7 +235,7 @@ describe('Members API', function () { should.exist(jsonResponse2); should.exist(jsonResponse2.members); jsonResponse2.members.should.have.length(1); - localUtils.API.checkResponse(jsonResponse2.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse2.members[0], 'member', 'subscriptions'); jsonResponse2.members[0].name.should.equal(memberChanged.name); jsonResponse2.members[0].email.should.equal(memberChanged.email); jsonResponse2.members[0].email.should.not.equal(memberToChange.email); @@ -360,8 +360,8 @@ describe('Members API', function () { importedMember1.labels.length.should.equal(1); testUtils.API.isISO8601(importedMember1.created_at).should.be.true(); importedMember1.comped.should.equal(false); - importedMember1.stripe.should.not.be.undefined(); - importedMember1.stripe.subscriptions.length.should.equal(0); + importedMember1.subscriptions.should.not.be.undefined(); + importedMember1.subscriptions.length.should.equal(0); const importedMember2 = jsonResponse2.members.find(m => m.email === 'test@example.com'); should.exist(importedMember2); @@ -372,8 +372,8 @@ describe('Members API', function () { testUtils.API.isISO8601(importedMember2.created_at).should.be.true(); importedMember2.created_at.should.equal('1991-10-02T20:30:31.000Z'); importedMember2.comped.should.equal(false); - importedMember2.stripe.should.not.be.undefined(); - importedMember2.stripe.subscriptions.length.should.equal(0); + importedMember2.subscriptions.should.not.be.undefined(); + importedMember2.subscriptions.length.should.equal(0); }); async function fetchStats() { diff --git a/test/regression/api/canary/admin/members_spec.js b/test/regression/api/canary/admin/members_spec.js index a4eb43579d..a9a1e152ff 100644 --- a/test/regression/api/canary/admin/members_spec.js +++ b/test/regression/api/canary/admin/members_spec.js @@ -91,7 +91,7 @@ describe('Members API', function () { jsonResponse.members.should.have.length(1); jsonResponse.members[0].email.should.equal('member1@test.com'); localUtils.API.checkResponse(jsonResponse, 'members'); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); }); }); @@ -111,7 +111,7 @@ describe('Members API', function () { jsonResponse.members.should.have.length(1); jsonResponse.members[0].email.should.equal('member2@test.com'); localUtils.API.checkResponse(jsonResponse, 'members'); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); }); }); @@ -131,7 +131,7 @@ describe('Members API', function () { jsonResponse.members.should.have.length(1); jsonResponse.members[0].email.should.equal('paid@test.com'); localUtils.API.checkResponse(jsonResponse, 'members'); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); }); }); @@ -234,7 +234,7 @@ describe('Members API', function () { should.exist(jsonResponse); should.exist(jsonResponse.members); jsonResponse.members.should.have.length(1); - localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); + localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'subscriptions'); jsonResponse.members[0].name.should.equal(memberToChange.name); jsonResponse.members[0].email.should.equal(memberToChange.email); jsonResponse.members[0].comped.should.equal(memberToChange.comped); @@ -397,8 +397,8 @@ describe('Members API', function () { should(importedMember1.note).equal(null); importedMember1.subscribed.should.equal(true); importedMember1.comped.should.equal(false); - importedMember1.stripe.should.not.be.undefined(); - importedMember1.stripe.subscriptions.length.should.equal(0); + importedMember1.subscriptions.should.not.be.undefined(); + importedMember1.subscriptions.length.should.equal(0); // check label order // 1 unique global + 1 record labels + 1 auto generated label @@ -464,8 +464,8 @@ describe('Members API', function () { should(importedMember1.note).equal('no need to map me'); importedMember1.subscribed.should.equal(true); importedMember1.comped.should.equal(false); - importedMember1.stripe.should.not.be.undefined(); - importedMember1.stripe.subscriptions.length.should.equal(0); + importedMember1.subscriptions.should.not.be.undefined(); + importedMember1.subscriptions.length.should.equal(0); importedMember1.labels.length.should.equal(1); // auto-generated import label }); }); @@ -509,8 +509,8 @@ describe('Members API', function () { should(defaultMember1.note).equal(null); defaultMember1.subscribed.should.equal(true); defaultMember1.comped.should.equal(false); - defaultMember1.stripe.should.not.be.undefined(); - defaultMember1.stripe.subscriptions.length.should.equal(0); + defaultMember1.subscriptions.should.not.be.undefined(); + defaultMember1.subscriptions.length.should.equal(0); defaultMember1.labels.length.should.equal(1); // auto-generated import label const defaultMember2 = jsonResponse.members.find(member => (member.email === 'member+defaults_2@example.com')); diff --git a/test/unit/services/members/middleware_spec.js b/test/unit/services/members/middleware_spec.js index 27a2c03e90..17eaba2505 100644 --- a/test/unit/services/members/middleware_spec.js +++ b/test/unit/services/members/middleware_spec.js @@ -104,11 +104,9 @@ describe('Members Service Middleware', function () { // Fake token handling failure membersService.ssr.exchangeTokenForSession.resolves({ - stripe: { - subscriptions: [{ - status: 'active' - }] - } + subscriptions: [{ + status: 'active' + }] }); // Call the middleware