mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Moved gated content block processing behind labs flag (#22101)
ref https://app.incident.io/ghost/incidents/137 - some sites make use of the Content API to fetch all posts in a single request with high traffic volumes which results in a lot of data processing to check for gated content that may cause higher CPU usage and slowdown - under an abundance of caution we're moving the related code behind a labs flag whilst further performance testing is performed - it should be noted that whilst this flag-conditional is in place, any content that has already used gated blocks as part of alpha testing will become visible if the flag is subsequently disabled
This commit is contained in:
parent
1a8d8061cd
commit
dafe5ac09b
2 changed files with 70 additions and 38 deletions
|
@ -1,4 +1,5 @@
|
|||
const membersService = require('../../../../../../services/members');
|
||||
const labs = require('../../../../../../../shared/labs');
|
||||
const htmlToPlaintext = require('@tryghost/html-to-plaintext');
|
||||
|
||||
const {PERMIT_ACCESS} = membersService.contentGating;
|
||||
|
@ -106,11 +107,13 @@ const forPost = (attrs, frame) => {
|
|||
}
|
||||
}
|
||||
|
||||
const hasGatedBlocks = HAS_GATED_BLOCKS_REGEX.test(attrs.html);
|
||||
if (hasGatedBlocks) {
|
||||
attrs.html = module.exports.stripGatedBlocks(attrs.html, frame.original.context.member);
|
||||
_updatePlaintext(attrs);
|
||||
_updateExcerpt(attrs);
|
||||
if (labs.isSet('contentVisibility')) {
|
||||
const hasGatedBlocks = HAS_GATED_BLOCKS_REGEX.test(attrs.html);
|
||||
if (hasGatedBlocks) {
|
||||
attrs.html = module.exports.stripGatedBlocks(attrs.html, frame.original.context.member);
|
||||
_updatePlaintext(attrs);
|
||||
_updateExcerpt(attrs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(frame.options, 'columns') || (frame.options.columns.includes('access'))) {
|
||||
|
|
|
@ -2,6 +2,7 @@ const assert = require('assert/strict');
|
|||
const sinon = require('sinon');
|
||||
const gating = require('../../../../../../../../core/server/api/endpoints/utils/serializers/output/utils/post-gating');
|
||||
const membersContentGating = require('../../../../../../../../core/server/services/members/content-gating');
|
||||
const labs = require('../../../../../../../../core/shared/labs');
|
||||
|
||||
describe('Unit: endpoints/utils/serializers/output/utils/post-gating', function () {
|
||||
afterEach(function () {
|
||||
|
@ -90,45 +91,73 @@ describe('Unit: endpoints/utils/serializers/output/utils/post-gating', function
|
|||
assert.equal(attrs.html, '<p>Can read this</p>');
|
||||
});
|
||||
|
||||
it('does not call stripGatedBlocks when a post has no gated blocks', function () {
|
||||
const attrs = {
|
||||
visibility: 'public',
|
||||
html: '<p>no gated blocks</p>'
|
||||
};
|
||||
describe('contentVisibility', function () {
|
||||
let contentVisibilityStub;
|
||||
|
||||
const stripGatedBlocksStub = sinon.stub(gating, 'stripGatedBlocks');
|
||||
gating.forPost(attrs, frame);
|
||||
sinon.assert.notCalled(stripGatedBlocksStub);
|
||||
});
|
||||
beforeEach(function () {
|
||||
contentVisibilityStub = sinon.stub(labs, 'isSet').withArgs('contentVisibility').returns(true);
|
||||
});
|
||||
|
||||
it('calls stripGatedBlocks when a post has gated blocks', function () {
|
||||
const attrs = {
|
||||
visibility: 'public',
|
||||
html: '<!--kg-gated-block:begin nonMember:true--><p>gated block</p><!--kg-gated-block:end-->'
|
||||
};
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
const stripGatedBlocksStub = sinon.stub(gating, 'stripGatedBlocks');
|
||||
gating.forPost(attrs, frame);
|
||||
sinon.assert.calledOnce(stripGatedBlocksStub);
|
||||
});
|
||||
it('does not call stripGatedBlocks when a post has no gated blocks', function () {
|
||||
const attrs = {
|
||||
visibility: 'public',
|
||||
html: '<p>no gated blocks</p>'
|
||||
};
|
||||
|
||||
it('updates html, plaintext, and excerpt when a post has gated blocks', function () {
|
||||
const attrs = {
|
||||
visibility: 'public',
|
||||
html: `
|
||||
<!--kg-gated-block:begin nonMember:false memberSegment:"status:free,status:-free"--><p>Members only.</p><!--kg-gated-block:end-->
|
||||
<p>Everyone can see this.</p>
|
||||
<!--kg-gated-block:begin nonMember:true--><p>Anonymous only.</p><!--kg-gated-block:end-->
|
||||
`,
|
||||
plaintext: 'Members only. Everyone can see this. Anonymous only.',
|
||||
excerpt: 'Members only. Everyone can see this. Anonymous only.'
|
||||
};
|
||||
const stripGatedBlocksStub = sinon.stub(gating, 'stripGatedBlocks');
|
||||
gating.forPost(attrs, frame);
|
||||
sinon.assert.notCalled(stripGatedBlocksStub);
|
||||
});
|
||||
|
||||
gating.forPost(attrs, frame);
|
||||
it('calls stripGatedBlocks when a post has gated blocks', function () {
|
||||
const attrs = {
|
||||
visibility: 'public',
|
||||
html: '<!--kg-gated-block:begin nonMember:true--><p>gated block</p><!--kg-gated-block:end-->'
|
||||
};
|
||||
|
||||
assert.match(attrs.html, /<p>Everyone can see this\.<\/p>\n\s+<p>Anonymous only.<\/p>/);
|
||||
assert.match(attrs.plaintext, /^\n+Everyone can see this.\n+Anonymous only.\n$/);
|
||||
assert.match(attrs.excerpt, /^\n+Everyone can see this.\n+Anonymous only.\n$/);
|
||||
const stripGatedBlocksStub = sinon.stub(gating, 'stripGatedBlocks');
|
||||
gating.forPost(attrs, frame);
|
||||
sinon.assert.calledOnce(stripGatedBlocksStub);
|
||||
});
|
||||
|
||||
it('updates html, plaintext, and excerpt when a post has gated blocks', function () {
|
||||
const attrs = {
|
||||
visibility: 'public',
|
||||
html: `
|
||||
<!--kg-gated-block:begin nonMember:false memberSegment:"status:free,status:-free"--><p>Members only.</p><!--kg-gated-block:end-->
|
||||
<p>Everyone can see this.</p>
|
||||
<!--kg-gated-block:begin nonMember:true--><p>Anonymous only.</p><!--kg-gated-block:end-->
|
||||
`,
|
||||
plaintext: 'Members only. Everyone can see this. Anonymous only.',
|
||||
excerpt: 'Members only. Everyone can see this. Anonymous only.'
|
||||
};
|
||||
|
||||
gating.forPost(attrs, frame);
|
||||
|
||||
assert.match(attrs.html, /<p>Everyone can see this\.<\/p>\n\s+<p>Anonymous only.<\/p>/);
|
||||
assert.match(attrs.plaintext, /^\n+Everyone can see this.\n+Anonymous only.\n$/);
|
||||
assert.match(attrs.excerpt, /^\n+Everyone can see this.\n+Anonymous only.\n$/);
|
||||
});
|
||||
|
||||
it('does not process gated blocks with contentVisibility flag disabled', function () {
|
||||
contentVisibilityStub.returns(false);
|
||||
|
||||
const regexSpy = sinon.spy(RegExp.prototype, 'test');
|
||||
const stripGatedBlocksStub = sinon.stub(gating, 'stripGatedBlocks');
|
||||
|
||||
const attrs = {
|
||||
visibility: 'public',
|
||||
html: '<!--kg-gated-block:begin nonMember:true--><p>gated block</p><!--kg-gated-block:end-->'
|
||||
};
|
||||
gating.forPost(attrs, frame);
|
||||
|
||||
sinon.assert.notCalled(regexSpy);
|
||||
sinon.assert.notCalled(stripGatedBlocksStub);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue