Ghost/ghost/members-api/lib/controllers/member/index.js
Fabien 'egg' O'Carroll 3ed10ecdf6 Added tests for updateSubscription
refs https://github.com/TryGhost/Team/issues/530

The RouterController was a grab bag of all controller methods, making it
difficult to mock & test. This adds a MemberController with a smaller
API - making it easier to test.
2021-03-25 12:19:01 +00:00

105 lines
3.6 KiB
JavaScript

const errors = require('ghost-ignition').errors;
/**
* MemberController
*
* @param {object} deps
* @param {any} deps.memberRepository
* @param {any} deps.stripePlansService
* @param {any} deps.tokenService
*/
module.exports = class MemberController {
constructor({
memberRepository,
stripePlansService,
tokenService
}) {
this._memberRepository = memberRepository;
this._stripePlansService = stripePlansService;
this._tokenService = tokenService;
}
async updateSubscription(req, res) {
try {
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');
}
if (!email) {
throw new errors.BadRequestError({
message: 'Invalid token'
});
}
if (planName !== undefined) {
const plan = this._stripePlansService.getPlan(planName);
if (!plan) {
throw new errors.BadRequestError({
message: 'Updating subscription failed! Could not find plan'
});
}
await this._memberRepository.updateSubscription({
email,
subscription: {
subscription_id: subscriptionId,
plan: plan.id
}
});
} else if (cancelAtPeriodEnd !== undefined) {
await this._memberRepository.updateSubscription({
email,
subscription: {
subscription_id: subscriptionId,
cancel_at_period_end: cancelAtPeriodEnd,
cancellationReason
}
});
}
res.writeHead(204);
res.end();
} catch (err) {
res.writeHead(err.statusCode || 500);
res.end(err.message);
}
}
};