Fixed HTTP 500 when adding unknown products to member

fix https://linear.app/tryghost/issue/SLO-89/cannot-read-properties-of-null-reading-get-an-unexpected-error

- if we pass an invalid ID when updating the products on a member, we
  throw a HTTP 500 error because `product` is `null`
- we can check for this and return a BadRequestError, because the user
  supplied an incorrect ID
This commit is contained in:
Daniel Lockyer 2024-05-01 16:38:51 +02:00 committed by Daniel Lockyer
parent 6b32548e5c
commit 3f7a7fff44
3 changed files with 49 additions and 0 deletions

View File

@ -5701,6 +5701,24 @@ Object {
}
`;
exports[`Members API Cannot add unknown tiers to a member 1: [body] 1`] = `
Object {
"errors": Array [
Object {
"code": null,
"context": "Could not find Product blahblahid",
"details": null,
"ghostErrorCode": null,
"help": null,
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"message": "Request not understood error, cannot edit member.",
"property": null,
"type": "BadRequestError",
},
],
}
`;
exports[`Members API Cannot delete a non-existent member 1: [body] 1`] = `
Object {
"errors": Array [

View File

@ -1740,6 +1740,29 @@ describe('Members API', function () {
should.deepEqual(memberWithPaidSubscription, readMember, 'Editing a member returns a different format than reading a member');
});
it('Cannot add unknown tiers to a member', async function () {
const memberId = testUtils.DataGenerator.Content.members[0].id;
const unknownProductId = 'blahblahid';
sinon.stub(logging, 'error');
await agent
.put(`/members/${memberId}/`)
.body({
members: [{
tiers: [{
id: unknownProductId
}]
}]
})
.expectStatus(400)
.matchBodySnapshot({
errors: [{
id: anyErrorId
}]
});
});
it('Cannot add complimentary subscriptions to a member with an active subscription', async function () {
if (!memberWithPaidSubscription) {
// Previous test failed

View File

@ -548,6 +548,14 @@ module.exports = class MemberRepository {
for (const productId of productsToAdd) {
const product = await this._productRepository.get({id: productId}, sharedOptions);
if (!product) {
throw new errors.BadRequestError({
message: tpl(messages.productNotFound, {
id: productId
})
});
}
if (product.get('active') !== true) {
throw new errors.BadRequestError({message: tpl(messages.tierArchived)});
}