diff --git a/ghost/members-api/index.js b/ghost/members-api/index.js index c2016baabc..d93f9651e5 100644 --- a/ghost/members-api/index.js +++ b/ghost/members-api/index.js @@ -260,6 +260,11 @@ module.exports = function MembersApi({ res.writeHead(400); return res.end(); } + + if (!req.body || !req.headers['stripe-signature']) { + res.writeHead(400); + return res.end(); + } let event; try { event = stripeWebhookService.parseWebhook(req.body, req.headers['stripe-signature']); diff --git a/ghost/members-api/lib/controllers/router/index.js b/ghost/members-api/lib/controllers/router/index.js index 42b036c195..d6e09da2c6 100644 --- a/ghost/members-api/lib/controllers/router/index.js +++ b/ghost/members-api/lib/controllers/router/index.js @@ -47,99 +47,109 @@ module.exports = class RouterController { } async updateSubscription(req, res) { - const identity = req.body.identity; - const subscriptionId = req.params.id; - const cancelAtPeriodEnd = req.body.cancel_at_period_end; - const cancellationReason = req.body.cancellation_reason; - const planName = req.body.planName; - - if (cancelAtPeriodEnd === undefined && planName === undefined) { - throw new errors.BadRequestError({ - message: 'Updating subscription failed!', - help: 'Request should contain "cancel_at_period_end" or "planName" field.' - }); - } - - if ((cancelAtPeriodEnd === undefined || cancelAtPeriodEnd === false) && cancellationReason !== undefined) { - throw new errors.BadRequestError({ - message: 'Updating subscription failed!', - help: '"cancellation_reason" field requires the "cancel_at_period_end" field to be true.' - }); - } - - if (cancellationReason && cancellationReason.length > 500) { - throw new errors.BadRequestError({ - message: 'Updating subscription failed!', - help: '"cancellation_reason" field can be a maximum of 500 characters.' - }); - } - - let email; try { - if (!identity) { + const identity = req.body.identity; + const subscriptionId = req.params.id; + const cancelAtPeriodEnd = req.body.cancel_at_period_end; + const cancellationReason = req.body.cancellation_reason; + const planName = req.body.planName; + + if (cancelAtPeriodEnd === undefined && planName === undefined) { + throw new errors.BadRequestError({ + message: 'Updating subscription failed!', + help: 'Request should contain "cancel_at_period_end" or "planName" field.' + }); + } + + if ((cancelAtPeriodEnd === undefined || cancelAtPeriodEnd === false) && cancellationReason !== undefined) { + throw new errors.BadRequestError({ + message: 'Updating subscription failed!', + help: '"cancellation_reason" field requires the "cancel_at_period_end" field to be true.' + }); + } + + if (cancellationReason && cancellationReason.length > 500) { + throw new errors.BadRequestError({ + message: 'Updating subscription failed!', + help: '"cancellation_reason" field can be a maximum of 500 characters.' + }); + } + + let email; + try { + if (!identity) { + throw new errors.BadRequestError({ + message: 'Updating subscription failed! Could not find member' + }); + } + + const claims = await this._tokenService.decodeToken(identity); + email = claims && claims.sub; + } catch (err) { + res.writeHead(401); + return res.end('Unauthorized'); + } + + const member = email ? await this._memberRepository.get({email}, {withRelated: ['stripeSubscriptions']}) : null; + + if (!member) { throw new errors.BadRequestError({ message: 'Updating subscription failed! Could not find member' }); } - const claims = await this._tokenService.decodeToken(identity); - email = claims && claims.sub; - } catch (err) { - res.writeHead(401); - return res.end('Unauthorized'); - } + // Don't allow removing subscriptions that don't belong to the member + const subscription = member.related('stripeSubscriptions').models.find( + subscription => subscription.get('subscription_id') === subscriptionId + ); + if (!subscription) { + res.writeHead(403); + return res.end('No permission'); + } - const member = email ? await this._memberRepository.get({email}, {withRelated: ['stripeSubscriptions']}) : null; - - if (!member) { - throw new errors.BadRequestError({ - message: 'Updating subscription failed! Could not find member' - }); - } - - // Don't allow removing subscriptions that don't belong to the member - const subscription = member.related('stripeSubscriptions').models.find( - subscription => subscription.get('subscription_id') === subscriptionId - ); - if (!subscription) { - res.writeHead(403); - return res.end('No permission'); - } - - let updatedSubscription; - if (planName !== undefined) { - const plan = this._stripePlansService.getPlans().find(plan => plan.nickname === planName); - if (!plan) { - throw new errors.BadRequestError({ - message: 'Updating subscription failed! Could not find plan' + let updatedSubscription; + if (planName !== undefined) { + const plan = this._stripePlansService.getPlans().find(plan => plan.nickname === planName); + if (!plan) { + throw new errors.BadRequestError({ + message: 'Updating subscription failed! Could not find plan' + }); + } + updatedSubscription = await this._stripeAPIService.changeSubscriptionPlan(subscriptionId, plan.id); + } else if (cancelAtPeriodEnd !== undefined) { + if (cancelAtPeriodEnd) { + updatedSubscription = await this._stripeAPIService.cancelSubscriptionAtPeriodEnd( + subscriptionId, cancellationReason + ); + } else { + updatedSubscription = await this._stripeAPIService.continueSubscriptionAtPeriodEnd( + subscriptionId + ); + } + } + if (updatedSubscription) { + await this._memberRepository.linkSubscription({ + id: member.id, + subscription: updatedSubscription }); } - updatedSubscription = await this._stripeAPIService.changeSubscriptionPlan(subscriptionId, plan.id); - } else if (cancelAtPeriodEnd !== undefined) { - if (cancelAtPeriodEnd) { - updatedSubscription = await this._stripeAPIService.cancelSubscriptionAtPeriodEnd( - subscriptionId, cancellationReason - ); - } else { - updatedSubscription = await this._stripeAPIService.continueSubscriptionAtPeriodEnd( - subscriptionId - ); - } - } - if (updatedSubscription) { - await this._memberRepository.linkSubscription({ - id: member.id, - subscription: updatedSubscription - }); - } - res.writeHead(204); - res.end(); + res.writeHead(204); + res.end(); + } catch (err) { + res.writeHead(err.statusCode || 500); + res.end(err.message); + } } async createCheckoutSetupSession(req, res) { const identity = req.body.identity; + if (!identity) { + res.writeHead(400); + return res.end(); + } + let email; try { if (!identity) {