Ghost/core/server/services/members/middleware.js

160 lines
5.5 KiB
JavaScript
Raw Normal View History

const _ = require('lodash');
const logging = require('../../../shared/logging');
const config = require('../../../shared/config');
const labsService = require('../labs');
const membersService = require('./index');
const urlUtils = require('../../../shared/url-utils');
const ghostVersion = require('../../lib/ghost-version');
const settingsCache = require('../settings/cache');
const {formattedMemberResponse} = require('./utils');
// @TODO: This piece of middleware actually belongs to the frontend, not to the member app
// Need to figure a way to separate these things (e.g. frontend actually talks to members API)
const loadMemberSession = async function (req, res, next) {
if (!labsService.isSet('members')) {
req.member = null;
return next();
}
try {
const member = await membersService.ssr.getMemberDataFromSession(req, res);
Object.assign(req, {member});
res.locals.member = req.member;
next();
} catch (err) {
logging.warn(err.message);
Object.assign(req, {member: null});
next();
}
};
const getIdentityToken = async function (req, res) {
try {
const token = await membersService.ssr.getIdentityTokenForMemberFromSession(req, res);
res.writeHead(200);
res.end(token);
} catch (err) {
logging.warn(err.message);
res.writeHead(err.statusCode);
res.end(err.message);
}
};
const deleteSession = async function (req, res) {
try {
await membersService.ssr.deleteSession(req, res);
res.writeHead(204);
res.end();
} catch (err) {
logging.warn(err.message);
res.writeHead(err.statusCode);
res.end(err.message);
}
};
const getMemberData = async function (req, res) {
try {
const member = await membersService.ssr.getMemberDataFromSession(req, res);
if (member) {
res.json(formattedMemberResponse(member));
} else {
res.json(null);
}
} catch (err) {
logging.warn(err.message);
res.writeHead(err.statusCode);
res.end(err.message);
}
};
const updateMemberData = async function (req, res) {
try {
const data = _.pick(req.body, 'name', 'subscribed');
const member = await membersService.ssr.getMemberDataFromSession(req, res);
if (member) {
const updatedMember = await membersService.api.members.update(data, {id: member.id});
res.json(formattedMemberResponse(updatedMember));
} else {
res.json(null);
}
} catch (err) {
logging.warn(err.message);
res.writeHead(err.statusCode);
res.end(err.message);
}
};
const getMemberSiteData = async function (req, res) {
const stripePaymentProcessor = settingsCache.get('members_subscription_settings').paymentProcessors.find(
paymentProcessor => paymentProcessor.adapter === 'stripe'
);
const stripeSecretToken = stripePaymentProcessor && stripePaymentProcessor.config.secret_token;
const stripePublicToken = stripePaymentProcessor && stripePaymentProcessor.config.public_token;
const stripeConnectIntegration = settingsCache.get('stripe_connect_integration');
const isStripeConfigured = (!!stripeSecretToken && !!stripePublicToken) || !!(stripeConnectIntegration && stripeConnectIntegration.account_id);
const response = {
title: settingsCache.get('title'),
description: settingsCache.get('description'),
logo: settingsCache.get('logo'),
brand: settingsCache.get('brand'),
url: urlUtils.urlFor('home', true),
version: ghostVersion.safe,
plans: membersService.config.getPublicPlans(),
allowSelfSignup: membersService.config.getAllowSelfSignup(),
isStripeConfigured,
show_beacon: settingsCache.get('membersjs_show_beacon'),
show_signup_name: settingsCache.get('membersjs_show_signup_name'),
allowed_plans: settingsCache.get('membersjs_allowed_plans')
};
// Brand is currently an experimental feature
if (!config.get('enableDeveloperExperiments')) {
delete response.brand;
}
res.json({site: response});
};
const createSessionFromMagicLink = async function (req, res, next) {
if (!req.url.includes('token=')) {
return next();
}
// req.query is a plain object, copy it to a URLSearchParams object so we can call toString()
const searchParams = new URLSearchParams('');
Object.keys(req.query).forEach((param) => {
// don't copy the token param
if (param !== 'token') {
searchParams.set(param, req.query[param]);
}
});
// We need to include the subdirectory,
// members is already removed from the path by express because it's a mount path
let redirectPath = `${urlUtils.getSubdir()}${req.path}`;
try {
await membersService.ssr.exchangeTokenForSession(req, res);
// Do a standard 302 redirect, with success=true
searchParams.set('success', true);
} catch (err) {
logging.warn(err.message);
searchParams.set('success', false);
} finally {
res.redirect(`${redirectPath}?${searchParams.toString()}`);
}
};
// Set req.member & res.locals.member if a cookie is set
module.exports = {
loadMemberSession,
createSessionFromMagicLink,
getIdentityToken,
getMemberData,
updateMemberData,
getMemberSiteData,
deleteSession,
stripeWebhooks: (req, res, next) => membersService.api.middleware.handleStripeWebhook(req, res, next)
};