🐛 Fixed comped member creation via Admin API (#15714)

closes https://github.com/TryGhost/Team/issues/2184

- when using the old legacy method of `comped:true` to add complimentary subs to a member along with a label, the API call failed with `Internal Server error` and the member was added as free on the site.
- patches the options sent for fetching default product to only pick the relevant keys, as it was picking up the `withRelated` for `labels` that caused the API failure
This commit is contained in:
Rishabh Garg 2022-10-28 01:59:05 +05:30 committed by GitHub
parent d8fa21e43c
commit 007637973e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 5 deletions

View File

@ -1394,10 +1394,11 @@ module.exports = class MemberRepository {
const activeSubscriptions = subscriptions.models.filter((subscription) => { const activeSubscriptions = subscriptions.models.filter((subscription) => {
return this.isActiveSubscriptionStatus(subscription.get('status')); return this.isActiveSubscriptionStatus(subscription.get('status'));
}); });
const sharedOptions = _.pick(options, ['context', 'transacting']);
const ghostProductModel = await this._productRepository.getDefaultProduct({ const ghostProductModel = await this._productRepository.getDefaultProduct({
withRelated: ['stripePrices'], withRelated: ['stripePrices'],
...options ...sharedOptions
}); });
const defaultProduct = ghostProductModel?.toJSON(); const defaultProduct = ghostProductModel?.toJSON();
@ -1454,7 +1455,7 @@ module.exports = class MemberRepository {
await this.linkSubscription({ await this.linkSubscription({
id: member.id, id: member.id,
subscription: updatedSubscription subscription: updatedSubscription
}, options); }, sharedOptions);
} }
} else { } else {
const stripeCustomer = await this._stripeAPIService.createCustomer({ const stripeCustomer = await this._stripeAPIService.createCustomer({
@ -1466,7 +1467,7 @@ module.exports = class MemberRepository {
member_id: data.id, member_id: data.id,
email: stripeCustomer.email, email: stripeCustomer.email,
name: stripeCustomer.name name: stripeCustomer.name
}, options); }, sharedOptions);
let zeroValuePrice = zeroValuePrices[0]; let zeroValuePrice = zeroValuePrices[0];
@ -1482,7 +1483,7 @@ module.exports = class MemberRepository {
interval: 'year', interval: 'year',
amount: 0 amount: 0
}] }]
}, options)).toJSON(); }, sharedOptions)).toJSON();
zeroValuePrice = product.stripePrices.find((price) => { zeroValuePrice = product.stripePrices.find((price) => {
return price.currency.toLowerCase() === 'usd' && price.amount === 0; return price.currency.toLowerCase() === 'usd' && price.amount === 0;
}); });
@ -1497,7 +1498,7 @@ module.exports = class MemberRepository {
await this.linkSubscription({ await this.linkSubscription({
id: member.id, id: member.id,
subscription subscription
}, options); }, sharedOptions);
} }
} }

View File

@ -99,6 +99,38 @@ describe('MemberRepository', function () {
assert.equal(err.message, 'Could not find Product "default"'); assert.equal(err.message, 'Could not find Product "default"');
} }
}); });
it('uses the right options for fetching default product', async function () {
productRepository = {
getDefaultProduct: sinon.stub().resolves({
toJSON: () => {
return null;
}
})
};
const repo = new MemberRepository({
Member,
stripeAPIService: {
configured: true
},
productRepository
});
try {
await repo.setComplimentarySubscription({
id: 'member_id_123'
}, {
transacting: true,
withRelated: ['labels']
});
assert.fail('setComplimentarySubscription should have thrown');
} catch (err) {
productRepository.getDefaultProduct.calledWith({withRelated: ['stripePrices'], transacting: true}).should.be.true();
assert.equal(err.message, 'Could not find Product "default"');
}
});
}); });
describe('linkSubscription', function (){ describe('linkSubscription', function (){