From bf859c38ee415eb55df57cf4bf9344f02ab95395 Mon Sep 17 00:00:00 2001 From: Simon Backx <simon@ghost.org> Date: Fri, 3 Nov 2023 16:02:46 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20showing=20recommendation?= =?UTF-8?q?s=20on=20custom=20welcome=20pages=20(#18864)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no issue When a custom welcome page is set for a tier, the recommendations modal didn't show. If recommendations were disabled, there was also no toast to confirm the sign up. To fix this, we'll need to set the success and action query parameters on the welcome page, but only if it is not an external site. --- .../server/services/members/middleware.js | 8 +++ .../core/test/e2e-api/members/signin.test.js | 49 ++++++++++++++----- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/ghost/core/core/server/services/members/middleware.js b/ghost/core/core/server/services/members/middleware.js index 23451c2ecd..a3ad49a4fb 100644 --- a/ghost/core/core/server/services/members/middleware.js +++ b/ghost/core/core/server/services/members/middleware.js @@ -265,8 +265,16 @@ const createSessionFromMagicLink = async function createSessionFromMagicLink(req const ensureEndsWith = (string, endsWith) => (string.endsWith(endsWith) ? string : string + endsWith); const removeLeadingSlash = string => string.replace(/^\//, ''); + // Add query parameters so the frontend can detect that the signup went fine + const redirectUrl = new URL(removeLeadingSlash(ensureEndsWith(customRedirect, '/')), ensureEndsWith(baseUrl, '/')); + if (urlUtils.isSiteUrl(redirectUrl)) { + // Add only for non-external URLs + redirectUrl.searchParams.set('success', 'true'); + redirectUrl.searchParams.set('action', 'signup'); + } + return res.redirect(redirectUrl.href); } } diff --git a/ghost/core/test/e2e-api/members/signin.test.js b/ghost/core/test/e2e-api/members/signin.test.js index 7ef02f0e30..aaa238bbec 100644 --- a/ghost/core/test/e2e-api/members/signin.test.js +++ b/ghost/core/test/e2e-api/members/signin.test.js @@ -3,6 +3,7 @@ const models = require('../../../core/server/models'); const assert = require('assert/strict'); require('should'); const sinon = require('sinon'); +const members = require('../../../core/server/services/members'); let membersAgent, membersService; @@ -64,7 +65,7 @@ describe('Members Signin', function () { await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); }); @@ -75,7 +76,7 @@ describe('Members Signin', function () { await membersAgent.get(`/?token=${token}&action=signup-paid`) .expectStatus(302) - .expectHeader('Location', /\/welcome-paid\/$/) + .expectHeader('Location', /\/welcome-paid\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); }); @@ -86,10 +87,36 @@ describe('Members Signin', function () { await membersAgent.get(`/?token=${token}&action=subscribe`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); }); + it('Will redirect to an external welcome page for subscribe', async function () { + // Alter the product welcome page to an external URL + const freeProduct = await members.api.productRepository.get({slug: 'free'}); + await members.api.productRepository.update({ + id: freeProduct.id, + welcome_page_url: 'https://externalsite.ghost/welcome/' + }); + + try { + const magicLink = await membersService.api.getMagicLink('member1@test.com', 'signup'); + const magicLinkUrl = new URL(magicLink); + const token = magicLinkUrl.searchParams.get('token'); + + await membersAgent.get(`/?token=${token}&action=subscribe`) + .expectStatus(302) + .expectHeader('Location', 'https://externalsite.ghost/welcome/') // no query params added + .expectHeader('Set-Cookie', /members-ssr.*/); + } finally { + // Change it back + await members.api.productRepository.update({ + id: freeProduct.id, + welcome_page_url: freeProduct.get('welcome_page_url') + }); + } + }); + it('Will create a new member on signup', async function () { const email = 'not-existent-member@test.com'; const magicLink = await membersService.api.getMagicLink(email, 'signup'); @@ -98,7 +125,7 @@ describe('Members Signin', function () { await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); const member = await getMemberByEmail(email); @@ -129,7 +156,7 @@ describe('Members Signin', function () { await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); }); @@ -173,7 +200,7 @@ describe('Members Signin', function () { // Use a first time await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); // Fetch token in the database @@ -189,7 +216,7 @@ describe('Members Signin', function () { await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); await model.refresh(); @@ -226,17 +253,17 @@ describe('Members Signin', function () { // Use a first time await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); // Fetch token in the database @@ -534,7 +561,7 @@ describe('Members Signin', function () { await membersAgent.get(`/?token=${token}&action=signup`) .expectStatus(302) - .expectHeader('Location', /\/welcome-free\/$/) + .expectHeader('Location', /\/welcome-free\/\?success=true&action=signup$/) .expectHeader('Set-Cookie', /members-ssr.*/); const member = await getMemberByEmail(email);