mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-06 22:40:14 -05:00
Supported redirecting externally after signup (#12391)
refs #12391 Adds support for redirecting to external URL's after successful signup for members.
This commit is contained in:
parent
5c4e884070
commit
f8b617af64
2 changed files with 63 additions and 22 deletions
|
@ -136,37 +136,36 @@ const createSessionFromMagicLink = async function (req, res, next) {
|
|||
const member = await membersService.ssr.exchangeTokenForSession(req, res);
|
||||
const subscriptions = member && member.stripe && member.stripe.subscriptions || [];
|
||||
|
||||
let redirectPath = '/';
|
||||
const action = req.query.action || req.query['portal-action'];
|
||||
|
||||
if (action === 'signup') {
|
||||
let customRedirect = '';
|
||||
if (subscriptions.find(sub => ['active', 'trialing'].includes(sub.status))) {
|
||||
redirectPath = settingsCache.get('members_paid_signup_redirect') || '/';
|
||||
customRedirect = settingsCache.get('members_paid_signup_redirect') || '';
|
||||
} else {
|
||||
redirectPath = settingsCache.get('members_free_signup_redirect') || '/';
|
||||
customRedirect = settingsCache.get('members_free_signup_redirect') || '';
|
||||
}
|
||||
|
||||
if (!redirectPath.startsWith('/')) {
|
||||
redirectPath = '/' + redirectPath;
|
||||
}
|
||||
if (customRedirect && customRedirect !== '/') {
|
||||
const baseUrl = urlUtils.getSiteUrl();
|
||||
const ensureEndsWith = (string, endsWith) => (string.endsWith(endsWith) ? string : string + endsWith);
|
||||
const removeLeadingSlash = string => string.replace(/^\//, '');
|
||||
|
||||
if (!redirectPath.endsWith('/')) {
|
||||
redirectPath = redirectPath + '/';
|
||||
const redirectUrl = new URL(removeLeadingSlash(ensureEndsWith(customRedirect, '/')), ensureEndsWith(baseUrl, '/'));
|
||||
|
||||
return res.redirect(redirectUrl.href);
|
||||
}
|
||||
}
|
||||
|
||||
if (redirectPath === '/') {
|
||||
searchParams.set('success', true);
|
||||
redirectPath = redirectPath + '?' + searchParams.toString();
|
||||
}
|
||||
|
||||
res.redirect(`${urlUtils.getSubdir()}${redirectPath}`);
|
||||
// Do a standard 302 redirect to the homepage, with success=true
|
||||
searchParams.set('success', true);
|
||||
res.redirect(`${urlUtils.getSubdir()}/?${searchParams.toString()}`);
|
||||
} catch (err) {
|
||||
logging.warn(err.message);
|
||||
|
||||
const redirectPath = '/';
|
||||
// Do a standard 302 redirect to the homepage, with success=false
|
||||
searchParams.set('success', false);
|
||||
res.redirect(`${urlUtils.getSubdir()}${redirectPath}?${searchParams.toString()}`);
|
||||
res.redirect(`${urlUtils.getSubdir()}/?${searchParams.toString()}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ const sinon = require('sinon');
|
|||
const urlUtils = require('../../../../core/shared/url-utils');
|
||||
const membersService = require('../../../../core/server/services/members');
|
||||
const membersMiddleware = require('../../../../core/server/services/members/middleware');
|
||||
const settingsCache = require('../../../../core/server/services/settings/cache');
|
||||
|
||||
describe('Members Service Middleware', function () {
|
||||
describe('createSessionFromMagicLink', function () {
|
||||
|
@ -22,6 +23,7 @@ describe('Members Service Middleware', function () {
|
|||
membersService.ssr.exchangeTokenForSession = sinon.stub();
|
||||
|
||||
sinon.stub(urlUtils, 'getSubdir').returns('/blah');
|
||||
sinon.stub(urlUtils, 'getSiteUrl').returns('https://site.com/blah');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
@ -29,9 +31,7 @@ describe('Members Service Middleware', function () {
|
|||
});
|
||||
|
||||
it('calls next if url does not include a token', async function () {
|
||||
// This recreates what express does, note: members is mounted so path will be /
|
||||
req.url = '/members';
|
||||
req.path = '/';
|
||||
req.query = {};
|
||||
|
||||
// Call the middleware
|
||||
|
@ -43,9 +43,7 @@ describe('Members Service Middleware', function () {
|
|||
});
|
||||
|
||||
it('redirects correctly on success', async function () {
|
||||
// This recreates what express does, note: members is mounted so path will be /
|
||||
req.url = '/members?token=test&action=signup';
|
||||
req.path = '/';
|
||||
req.query = {token: 'test', action: 'signup'};
|
||||
|
||||
// Fake token handling success
|
||||
|
@ -61,9 +59,7 @@ describe('Members Service Middleware', function () {
|
|||
});
|
||||
|
||||
it('redirects correctly on failure', async function () {
|
||||
// This recreates what express does, note: members is mounted so path will be /
|
||||
req.url = '/members?token=test&action=signup';
|
||||
req.path = '/';
|
||||
req.query = {token: 'test', action: 'signup'};
|
||||
|
||||
// Fake token handling failure
|
||||
|
@ -77,5 +73,51 @@ describe('Members Service Middleware', function () {
|
|||
res.redirect.calledOnce.should.be.true();
|
||||
res.redirect.firstCall.args[0].should.eql('/blah/?action=signup&success=false');
|
||||
});
|
||||
|
||||
it('redirects to custom redirect on signup', async function () {
|
||||
req.url = '/members?token=test&action=signup';
|
||||
req.query = {token: 'test', action: 'signup'};
|
||||
|
||||
sinon.stub(settingsCache, 'get')
|
||||
.withArgs('members_free_signup_redirect')
|
||||
.returns('https://custom.com/redirect');
|
||||
|
||||
// Fake token handling failure
|
||||
membersService.ssr.exchangeTokenForSession.resolves();
|
||||
|
||||
// Call the middleware
|
||||
await membersMiddleware.createSessionFromMagicLink(req, res, next);
|
||||
|
||||
// Check behaviour
|
||||
next.calledOnce.should.be.false();
|
||||
res.redirect.calledOnce.should.be.true();
|
||||
res.redirect.firstCall.args[0].should.eql('https://custom.com/redirect/');
|
||||
});
|
||||
|
||||
it('redirects to custom redirect on signup', async function () {
|
||||
req.url = '/members?token=test&action=signup';
|
||||
req.query = {token: 'test', action: 'signup'};
|
||||
|
||||
sinon.stub(settingsCache, 'get')
|
||||
.withArgs('members_paid_signup_redirect')
|
||||
.returns('https://custom.com/paid');
|
||||
|
||||
// Fake token handling failure
|
||||
membersService.ssr.exchangeTokenForSession.resolves({
|
||||
stripe: {
|
||||
subscriptions: [{
|
||||
status: 'active'
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
// Call the middleware
|
||||
await membersMiddleware.createSessionFromMagicLink(req, res, next);
|
||||
|
||||
// Check behaviour
|
||||
next.calledOnce.should.be.false();
|
||||
res.redirect.calledOnce.should.be.true();
|
||||
res.redirect.firstCall.args[0].should.eql('https://custom.com/paid/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue