mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-20 17:32:15 +03:00
69df4b7c05
refs https://github.com/TryGhost/Team/issues/1257 This gets us closer to not having to reload the MembersAPI when config is changed which will help stop bugs arising from multiple instances of the MembersAPI being created.
167 lines
5.9 KiB
JavaScript
167 lines
5.9 KiB
JavaScript
const errors = require('@tryghost/errors');
|
|
|
|
module.exports = class MemberController {
|
|
/**
|
|
* @param {object} deps
|
|
* @param {any} deps.memberRepository
|
|
* @param {any} deps.StripePrice
|
|
* @param {any} deps.tokenService
|
|
* @param {any} deps.sendEmailWithMagicLink
|
|
*/
|
|
constructor({
|
|
memberRepository,
|
|
StripePrice,
|
|
tokenService,
|
|
sendEmailWithMagicLink
|
|
}) {
|
|
this._memberRepository = memberRepository;
|
|
this._StripePrice = StripePrice;
|
|
this._tokenService = tokenService;
|
|
this._sendEmailWithMagicLink = sendEmailWithMagicLink;
|
|
}
|
|
|
|
async updateEmailAddress(req, res) {
|
|
const identity = req.body.identity;
|
|
const email = req.body.email;
|
|
const options = {
|
|
forceEmailType: true
|
|
};
|
|
|
|
if (!identity) {
|
|
res.writeHead(403);
|
|
return res.end('No Permission.');
|
|
}
|
|
|
|
let tokenData = {};
|
|
try {
|
|
const member = await this._memberRepository.getByToken(identity);
|
|
tokenData.oldEmail = member.get('email');
|
|
} catch (err) {
|
|
res.writeHead(401);
|
|
return res.end('Unauthorized.');
|
|
}
|
|
|
|
try {
|
|
await this._sendEmailWithMagicLink({email, tokenData, requestedType: 'updateEmail', options});
|
|
res.writeHead(201);
|
|
return res.end('Created.');
|
|
} catch (err) {
|
|
res.writeHead(500);
|
|
return res.end('Internal Server Error.');
|
|
}
|
|
}
|
|
|
|
async updateSubscription(req, res) {
|
|
try {
|
|
const identity = req.body.identity;
|
|
const subscriptionId = req.params.id;
|
|
const cancelAtPeriodEnd = req.body.cancel_at_period_end;
|
|
const smartCancel = req.body.smart_cancel;
|
|
const cancellationReason = req.body.cancellation_reason;
|
|
const ghostPriceId = req.body.priceId;
|
|
if (cancelAtPeriodEnd === undefined && ghostPriceId === undefined && smartCancel === undefined) {
|
|
throw new errors.BadRequestError({
|
|
message: 'Updating subscription failed!',
|
|
help: 'Request should contain "cancel_at_period_end" or "priceId" or "smart_cancel" field.'
|
|
});
|
|
}
|
|
|
|
if ((cancelAtPeriodEnd === undefined || cancelAtPeriodEnd === false) && !smartCancel && cancellationReason !== undefined) {
|
|
throw new errors.BadRequestError({
|
|
message: 'Updating subscription failed!',
|
|
help: '"cancellation_reason" field requires the "cancel_at_period_end" or "smart_cancel" 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 (ghostPriceId !== undefined) {
|
|
const price = await this._StripePrice.findOne({
|
|
id: ghostPriceId
|
|
});
|
|
|
|
if (!price) {
|
|
res.writeHead(404);
|
|
return res.end('Not Found.');
|
|
}
|
|
|
|
const priceId = price.get('stripe_price_id');
|
|
await this._memberRepository.updateSubscription({
|
|
email,
|
|
subscription: {
|
|
subscription_id: subscriptionId,
|
|
price: priceId
|
|
}
|
|
});
|
|
} else if (cancelAtPeriodEnd !== undefined) {
|
|
await this._memberRepository.updateSubscription({
|
|
email,
|
|
subscription: {
|
|
subscription_id: subscriptionId,
|
|
cancel_at_period_end: cancelAtPeriodEnd,
|
|
cancellationReason
|
|
}
|
|
});
|
|
} else if (smartCancel) {
|
|
const currentSubscription = await this._memberRepository.getSubscription({
|
|
email,
|
|
subscription: {
|
|
subscription_id: subscriptionId
|
|
}
|
|
});
|
|
|
|
if (['past_due', 'unpaid'].includes(currentSubscription.status)) {
|
|
await this._memberRepository.cancelSubscription({
|
|
email,
|
|
subscription: {
|
|
subscription_id: subscriptionId,
|
|
cancellationReason
|
|
}
|
|
});
|
|
} else {
|
|
await this._memberRepository.updateSubscription({
|
|
email,
|
|
subscription: {
|
|
subscription_id: subscriptionId,
|
|
cancel_at_period_end: true,
|
|
cancellationReason
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
res.writeHead(204);
|
|
res.end();
|
|
} catch (err) {
|
|
res.writeHead(err.statusCode || 500);
|
|
res.end(err.message);
|
|
}
|
|
}
|
|
};
|