0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-18 02:21:47 -05:00

Disabled one-click subscribe when Portal checkbox is required (#18252)

fixes https://github.com/TryGhost/Product/issues/3911

For now we decided that we don't want to enable one-click-subscribe in
case a site has a required checkbox (which isn't shown during the
one-click-subscribe flow)
This commit is contained in:
Simon Backx 2023-09-20 17:35:10 +02:00 committed by GitHub
parent 76bd5a4dc2
commit 715d658e11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 123 additions and 16 deletions

View file

@ -7,7 +7,7 @@ export type GhostSiteResponse = {
logo: URL | null,
icon: URL | null,
cover_image : URL | null,
allow_self_signup: boolean,
allow_external_signup: boolean,
url: URL,
}
}
@ -35,7 +35,20 @@ export const useExternalGhostSite = () => {
});
// We need to validate all data types here for extra safety
if (typeof result !== 'object' || !result.site || typeof result.site !== 'object' || typeof result.site.title !== 'string' || typeof result.site.allow_self_signup !== 'boolean' || typeof result.site.url !== 'string') {
if (typeof result !== 'object' || !result.site || typeof result.site !== 'object') {
// eslint-disable-next-line no-console
console.warn('Received invalid response from external Ghost site API', result);
return null;
}
// Temporary mapping (should get removed!)
// allow_self_signup was replaced by allow_external_signup
if (typeof result.site.allow_self_signup === 'boolean' && typeof result.site.allow_external_signup !== 'boolean') {
result.site.allow_external_signup = result.site.allow_self_signup;
}
// We need to validate all data types here for extra safety
if (typeof result.site.title !== 'string' || typeof result.site.allow_external_signup !== 'boolean' || typeof result.site.url !== 'string') {
// eslint-disable-next-line no-console
console.warn('Received invalid response from external Ghost site API', result);
return null;
@ -74,7 +87,7 @@ export const useExternalGhostSite = () => {
logo: result.site.logo ? new URL(result.site.logo) : null,
icon: result.site.icon ? new URL(result.site.icon) : null,
cover_image: result.site.cover_image ? new URL(result.site.cover_image) : null,
allow_self_signup: result.site.allow_self_signup,
allow_external_signup: result.site.allow_external_signup,
url: new URL(result.site.url)
}
};

View file

@ -58,7 +58,7 @@ const AddRecommendationModal: React.FC<RoutingModalProps & AddRecommendationModa
updatedRecommendation.excerpt = externalGhostSite.site.description ?? formState.excerpt ?? null;
updatedRecommendation.featured_image = externalGhostSite.site.cover_image?.toString() ?? formState.featured_image ?? null;
updatedRecommendation.favicon = externalGhostSite.site.icon?.toString() ?? externalGhostSite.site.logo?.toString() ?? formState.favicon ?? null;
updatedRecommendation.one_click_subscribe = externalGhostSite.site.allow_self_signup;
updatedRecommendation.one_click_subscribe = externalGhostSite.site.allow_external_signup;
} else {
// For non-Ghost sites, we use the Oemebd API to fetch metadata
const oembed = await queryOembed({

View file

@ -16,7 +16,7 @@ module.exports = {
'locale',
'url',
'version',
'allow_self_signup',
'allow_external_signup',
'sentry_dsn',
'sentry_env'
])

View file

@ -14,7 +14,7 @@ module.exports = function getSiteProperties() {
locale: settingsCache.get('locale'),
url: urlUtils.urlFor('home', true),
version: ghostVersion.safe,
allow_self_signup: settingsCache.get('allow_self_signup')
allow_external_signup: settingsCache.get('allow_self_signup') && !(settingsCache.get('portal_signup_checkbox_required') && settingsCache.get('portal_signup_terms_html'))
};
if (config.get('client_sentry') && !config.get('client_sentry').disabled) {

View file

@ -4,7 +4,7 @@ exports[`Site API can retrieve config and all expected properties 1: [body] 1`]
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_self_signup": true,
"allow_external_signup": true,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,

View file

@ -4,7 +4,7 @@ exports[`Site Public Settings Can retrieve site pubic config 1: [body] 1`] = `
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_self_signup": true,
"allow_external_signup": true,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,
@ -29,6 +29,64 @@ Object {
}
`;
exports[`Site Public Settings Sets allow_external_signup to false when members are invite only 1: [body] 1`] = `
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_external_signup": false,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,
"locale": "en",
"logo": null,
"title": "Ghost",
"url": "http://127.0.0.1:2369/",
"version": StringMatching /\\\\d\\+\\\\\\.\\\\d\\+/,
},
}
`;
exports[`Site Public Settings Sets allow_external_signup to false when members are invite only 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": StringMatching /\\\\d\\+/,
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Site Public Settings Sets allow_external_signup to false when portal requires checkbox 1: [body] 1`] = `
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_external_signup": false,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,
"locale": "en",
"logo": null,
"title": "Ghost",
"url": "http://127.0.0.1:2369/",
"version": StringMatching /\\\\d\\+\\\\\\.\\\\d\\+/,
},
}
`;
exports[`Site Public Settings Sets allow_external_signup to false when portal requires checkbox 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": StringMatching /\\\\d\\+/,
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Site Public Settings Sets allow_self_signup to false when members are invite only 1: [body] 1`] = `
Object {
"site": Object {

View file

@ -11,6 +11,13 @@ describe('Site Public Settings', function () {
await fixtureManager.init();
});
afterEach(async function () {
await await models.Settings.edit({
key: 'members_signup_access',
value: 'all'
}, {context: {internal: true}});
});
it('Can retrieve site pubic config', async function () {
const {body} = await membersAgent
.get('/api/site')
@ -23,10 +30,10 @@ describe('Site Public Settings', function () {
etag: anyEtag,
'content-length': anyContentLength
});
assert.equal(body.site.allow_self_signup, true);
assert.equal(body.site.allow_external_signup, true);
});
it('Sets allow_self_signup to false when members are invite only', async function () {
it('Sets allow_external_signup to false when members are invite only', async function () {
await await models.Settings.edit({
key: 'members_signup_access',
value: 'invite'
@ -43,6 +50,35 @@ describe('Site Public Settings', function () {
etag: anyEtag,
'content-length': anyContentLength
});
assert.equal(body.site.allow_self_signup, false);
assert.equal(body.site.allow_external_signup, false);
});
it('Sets allow_external_signup to false when portal requires checkbox', async function () {
const {body: initialBody} = await membersAgent
.get('/api/site');
assert.equal(initialBody.site.allow_external_signup, true, 'This test requires the initial state to allow external signups');
await await models.Settings.edit({
key: 'portal_signup_checkbox_required',
value: true
}, {context: {internal: true}});
await await models.Settings.edit({
key: 'portal_signup_terms_html',
value: 'I agree to the terms and conditions'
}, {context: {internal: true}});
const {body} = await membersAgent
.get('/api/site')
.matchBodySnapshot({
site: {
version: stringMatching(/\d+\.\d+/)
}
})
.matchHeaderSnapshot({
etag: anyEtag,
'content-length': anyContentLength
});
assert.equal(body.site.allow_external_signup, false);
});
});

View file

@ -4,7 +4,7 @@ exports[`API Versioning Admin API Does an internal rewrite for canary URLs with
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_self_signup": true,
"allow_external_signup": true,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,
@ -83,7 +83,7 @@ exports[`API Versioning Admin API allows invalid accept-version header 1: [body]
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_self_signup": true,
"allow_external_signup": true,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,
@ -231,7 +231,7 @@ exports[`API Versioning Admin API responds with content version header even when
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_self_signup": true,
"allow_external_signup": true,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,
@ -261,7 +261,7 @@ exports[`API Versioning Admin API responds with current content version header w
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_self_signup": true,
"allow_external_signup": true,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,
@ -291,7 +291,7 @@ exports[`API Versioning Admin API responds with current content version header w
Object {
"site": Object {
"accent_color": "#FF1A75",
"allow_self_signup": true,
"allow_external_signup": true,
"cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
"description": "Thoughts, stories and ideas",
"icon": null,