2020-05-20 12:07:58 +03:00
|
|
|
const _ = require('lodash');
|
2020-05-28 21:30:23 +03:00
|
|
|
const logging = require('../../../shared/logging');
|
2020-05-27 20:47:53 +03:00
|
|
|
const config = require('../../../shared/config');
|
2019-11-21 06:01:24 +03:00
|
|
|
const labsService = require('../labs');
|
|
|
|
const membersService = require('./index');
|
2020-05-28 13:57:02 +03:00
|
|
|
const urlUtils = require('../../../shared/url-utils');
|
2020-04-30 21:50:40 +03:00
|
|
|
const ghostVersion = require('../../lib/ghost-version');
|
|
|
|
const settingsCache = require('../settings/cache');
|
2020-05-20 12:07:58 +03:00
|
|
|
const {formattedMemberResponse} = require('./utils');
|
2019-11-21 06:01:24 +03:00
|
|
|
|
2020-04-30 21:33:09 +03:00
|
|
|
// @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) {
|
2020-04-30 22:26:12 +03:00
|
|
|
logging.warn(err.message);
|
2020-04-30 21:33:09 +03:00
|
|
|
Object.assign(req, {member: null});
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-11-26 18:44:25 +03:00
|
|
|
const getIdentityToken = async function (req, res) {
|
2019-11-21 06:01:24 +03:00
|
|
|
try {
|
|
|
|
const token = await membersService.ssr.getIdentityTokenForMemberFromSession(req, res);
|
|
|
|
res.writeHead(200);
|
|
|
|
res.end(token);
|
|
|
|
} catch (err) {
|
2020-04-30 22:26:12 +03:00
|
|
|
logging.warn(err.message);
|
2019-11-21 06:01:24 +03:00
|
|
|
res.writeHead(err.statusCode);
|
|
|
|
res.end(err.message);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-11-28 10:53:30 +03:00
|
|
|
const deleteSession = async function (req, res) {
|
2019-11-21 06:01:24 +03:00
|
|
|
try {
|
|
|
|
await membersService.ssr.deleteSession(req, res);
|
|
|
|
res.writeHead(204);
|
|
|
|
res.end();
|
|
|
|
} catch (err) {
|
2020-04-30 22:26:12 +03:00
|
|
|
logging.warn(err.message);
|
2019-11-21 06:01:24 +03:00
|
|
|
res.writeHead(err.statusCode);
|
|
|
|
res.end(err.message);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-04-20 09:03:15 +03:00
|
|
|
const getMemberData = async function (req, res) {
|
|
|
|
try {
|
|
|
|
const member = await membersService.ssr.getMemberDataFromSession(req, res);
|
|
|
|
if (member) {
|
2020-05-20 12:07:58 +03:00
|
|
|
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 {
|
2020-05-28 17:01:00 +03:00
|
|
|
const data = _.pick(req.body, 'name', 'subscribed');
|
2020-05-20 12:07:58 +03:00
|
|
|
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));
|
2020-04-20 09:03:15 +03:00
|
|
|
} else {
|
|
|
|
res.json(null);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
2020-04-30 22:26:12 +03:00
|
|
|
logging.warn(err.message);
|
2020-04-20 09:03:15 +03:00
|
|
|
res.writeHead(err.statusCode);
|
|
|
|
res.end(err.message);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-04-30 21:50:40 +03:00
|
|
|
const getMemberSiteData = async function (req, res) {
|
2020-06-29 17:22:42 +03:00
|
|
|
const isStripeConfigured = membersService.config.isStripeConnected();
|
2020-06-19 17:04:40 +03:00
|
|
|
|
2020-04-30 21:50:40 +03:00
|
|
|
const response = {
|
|
|
|
title: settingsCache.get('title'),
|
|
|
|
description: settingsCache.get('description'),
|
|
|
|
logo: settingsCache.get('logo'),
|
2020-07-23 14:34:04 +03:00
|
|
|
icon: settingsCache.get('icon'),
|
2020-06-23 15:33:57 +03:00
|
|
|
accent_color: settingsCache.get('accent_color'),
|
2020-04-30 21:50:40 +03:00
|
|
|
url: urlUtils.urlFor('home', true),
|
|
|
|
version: ghostVersion.safe,
|
|
|
|
plans: membersService.config.getPublicPlans(),
|
2020-06-19 17:04:40 +03:00
|
|
|
allow_self_signup: membersService.config.getAllowSelfSignup(),
|
|
|
|
is_stripe_configured: isStripeConfigured,
|
|
|
|
portal_button: settingsCache.get('portal_button'),
|
|
|
|
portal_name: settingsCache.get('portal_name'),
|
2020-07-07 11:11:16 +03:00
|
|
|
portal_plans: settingsCache.get('portal_plans'),
|
|
|
|
portal_button_icon: settingsCache.get('portal_button_icon'),
|
|
|
|
portal_button_signup_text: settingsCache.get('portal_button_signup_text'),
|
|
|
|
portal_button_style: settingsCache.get('portal_button_style')
|
2020-04-30 21:50:40 +03:00
|
|
|
};
|
|
|
|
|
2020-06-23 15:33:57 +03:00
|
|
|
// accent_color is currently an experimental feature
|
2020-04-30 21:50:40 +03:00
|
|
|
if (!config.get('enableDeveloperExperiments')) {
|
2020-06-23 15:33:57 +03:00
|
|
|
delete response.accent_color;
|
2020-04-30 21:50:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
res.json({site: response});
|
|
|
|
};
|
|
|
|
|
2020-04-29 20:23:55 +03:00
|
|
|
const createSessionFromMagicLink = async function (req, res, next) {
|
2019-11-21 06:01:24 +03:00
|
|
|
if (!req.url.includes('token=')) {
|
|
|
|
return next();
|
|
|
|
}
|
2020-04-29 20:23:55 +03:00
|
|
|
|
2020-05-07 23:55:50 +03:00
|
|
|
// 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]);
|
|
|
|
}
|
|
|
|
});
|
2020-04-29 20:23:55 +03:00
|
|
|
|
2020-05-07 23:55:50 +03:00
|
|
|
// We need to include the subdirectory,
|
|
|
|
// members is already removed from the path by express because it's a mount path
|
2020-05-08 15:03:44 +03:00
|
|
|
let redirectPath = `${urlUtils.getSubdir()}${req.path}`;
|
2020-05-07 23:55:50 +03:00
|
|
|
|
|
|
|
try {
|
|
|
|
await membersService.ssr.exchangeTokenForSession(req, res);
|
2020-04-29 20:23:55 +03:00
|
|
|
|
2020-05-08 15:03:44 +03:00
|
|
|
// Do a standard 302 redirect, with success=true
|
|
|
|
searchParams.set('success', true);
|
2019-11-21 06:01:24 +03:00
|
|
|
} catch (err) {
|
2020-04-30 22:26:12 +03:00
|
|
|
logging.warn(err.message);
|
2020-05-08 15:03:44 +03:00
|
|
|
searchParams.set('success', false);
|
|
|
|
} finally {
|
|
|
|
res.redirect(`${redirectPath}?${searchParams.toString()}`);
|
2019-11-21 06:01:24 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Set req.member & res.locals.member if a cookie is set
|
|
|
|
module.exports = {
|
2020-04-29 20:23:55 +03:00
|
|
|
loadMemberSession,
|
|
|
|
createSessionFromMagicLink,
|
2020-04-21 18:48:42 +03:00
|
|
|
getIdentityToken,
|
2020-04-20 09:03:15 +03:00
|
|
|
getMemberData,
|
2020-05-20 12:07:58 +03:00
|
|
|
updateMemberData,
|
2020-04-30 21:50:40 +03:00
|
|
|
getMemberSiteData,
|
2020-04-21 18:48:42 +03:00
|
|
|
deleteSession,
|
|
|
|
stripeWebhooks: (req, res, next) => membersService.api.middleware.handleStripeWebhook(req, res, next)
|
2019-11-21 06:01:24 +03:00
|
|
|
};
|