mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-29 13:52:10 +03:00
Moved magiclink handling to /members/ + added redirect
- Magic link token handling doesn't need to be global, this couples the system to the frontend, which isn't necessary - Instead, we create a session from the token, and redirect to the frontend - Move res.locals.members setting into existing middleware function instead of having it separate
This commit is contained in:
parent
0e1ae7c2af
commit
d8d5d6b7d0
@ -2,6 +2,7 @@ const {URL} = require('url');
|
|||||||
const settingsCache = require('../settings/cache');
|
const settingsCache = require('../settings/cache');
|
||||||
const ghostVersion = require('../../lib/ghost-version');
|
const ghostVersion = require('../../lib/ghost-version');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
const path = require('path');
|
||||||
const common = require('../../lib/common');
|
const common = require('../../lib/common');
|
||||||
const urlUtils = require('../../lib/url-utils');
|
const urlUtils = require('../../lib/url-utils');
|
||||||
|
|
||||||
@ -155,6 +156,7 @@ function getTokenConfig() {
|
|||||||
|
|
||||||
function getSigninURL(token, type) {
|
function getSigninURL(token, type) {
|
||||||
const signinURL = new URL(siteUrl);
|
const signinURL = new URL(siteUrl);
|
||||||
|
signinURL.pathname = path.join(signinURL.pathname, '/members/');
|
||||||
signinURL.searchParams.set('token', token);
|
signinURL.searchParams.set('token', token);
|
||||||
signinURL.searchParams.set('action', type);
|
signinURL.searchParams.set('action', type);
|
||||||
return signinURL.href;
|
return signinURL.href;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const common = require('../../lib/common');
|
const common = require('../../lib/common');
|
||||||
const labsService = require('../labs');
|
const labsService = require('../labs');
|
||||||
const membersService = require('./index');
|
const membersService = require('./index');
|
||||||
|
const urlUtils = require('../../lib/url-utils');
|
||||||
|
|
||||||
const getIdentityToken = async function (req, res) {
|
const getIdentityToken = async function (req, res) {
|
||||||
try {
|
try {
|
||||||
@ -26,7 +27,7 @@ const deleteSession = async function (req, res) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMemberDataFromSession = async function (req, res, next) {
|
const loadMemberSession = async function (req, res, next) {
|
||||||
if (!labsService.isSet('members')) {
|
if (!labsService.isSet('members')) {
|
||||||
req.member = null;
|
req.member = null;
|
||||||
return next();
|
return next();
|
||||||
@ -34,6 +35,7 @@ const getMemberDataFromSession = async function (req, res, next) {
|
|||||||
try {
|
try {
|
||||||
const member = await membersService.ssr.getMemberDataFromSession(req, res);
|
const member = await membersService.ssr.getMemberDataFromSession(req, res);
|
||||||
Object.assign(req, {member});
|
Object.assign(req, {member});
|
||||||
|
res.locals.member = req.member;
|
||||||
next();
|
next();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.warn(err.message);
|
common.logging.warn(err.message);
|
||||||
@ -68,7 +70,7 @@ const getMemberData = async function (req, res) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const exchangeTokenForSession = async function (req, res, next) {
|
const createSessionFromMagicLink = async function (req, res, next) {
|
||||||
if (!labsService.isSet('members')) {
|
if (!labsService.isSet('members')) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
@ -76,8 +78,23 @@ const exchangeTokenForSession = async function (req, res, next) {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const member = await membersService.ssr.exchangeTokenForSession(req, res);
|
await membersService.ssr.exchangeTokenForSession(req, res);
|
||||||
Object.assign(req, {member});
|
|
||||||
|
// 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, but members is already removed from the path
|
||||||
|
let redirectPath = `${urlUtils.getSubdir()}${req.path}?${searchParams.toString()}`;
|
||||||
|
|
||||||
|
// Do a standard 302 redirect
|
||||||
|
res.redirect(redirectPath);
|
||||||
|
|
||||||
next();
|
next();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
common.logging.warn(err.message);
|
common.logging.warn(err.message);
|
||||||
@ -85,25 +102,11 @@ const exchangeTokenForSession = async function (req, res, next) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const decorateResponse = function (req, res, next) {
|
|
||||||
if (!labsService.isSet('members')) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
res.locals.member = req.member;
|
|
||||||
next();
|
|
||||||
};
|
|
||||||
|
|
||||||
// @TODO only load this stuff if members is enabled
|
// @TODO only load this stuff if members is enabled
|
||||||
// Set req.member & res.locals.member if a cookie is set
|
// Set req.member & res.locals.member if a cookie is set
|
||||||
module.exports = {
|
module.exports = {
|
||||||
memberSession: [
|
loadMemberSession,
|
||||||
getMemberDataFromSession,
|
createSessionFromMagicLink,
|
||||||
decorateResponse
|
|
||||||
],
|
|
||||||
createSessionFromMagicLink: [
|
|
||||||
exchangeTokenForSession,
|
|
||||||
decorateResponse
|
|
||||||
],
|
|
||||||
getIdentityToken,
|
getIdentityToken,
|
||||||
getMemberData,
|
getMemberData,
|
||||||
deleteSession,
|
deleteSession,
|
||||||
|
@ -138,10 +138,10 @@ module.exports = function setupSiteApp(options = {}) {
|
|||||||
siteApp.post('/members/webhooks/stripe', shared.middlewares.labs.members, membersMiddleware.stripeWebhooks);
|
siteApp.post('/members/webhooks/stripe', shared.middlewares.labs.members, membersMiddleware.stripeWebhooks);
|
||||||
|
|
||||||
// Currently global handling for signing in with ?token= magiclinks
|
// Currently global handling for signing in with ?token= magiclinks
|
||||||
siteApp.use(membersMiddleware.createSessionFromMagicLink);
|
siteApp.use('/members/', membersMiddleware.createSessionFromMagicLink);
|
||||||
|
|
||||||
// Global handling for member session, ensures a member is logged in to the frontend
|
// Global handling for member session, ensures a member is logged in to the frontend
|
||||||
siteApp.use(membersMiddleware.memberSession);
|
siteApp.use(membersMiddleware.loadMemberSession);
|
||||||
|
|
||||||
// Theme middleware
|
// Theme middleware
|
||||||
// This should happen AFTER any shared assets are served, as it only changes things to do with templates
|
// This should happen AFTER any shared assets are served, as it only changes things to do with templates
|
||||||
|
Loading…
Reference in New Issue
Block a user