mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Added content gating based on visibility flag (#11173)
no issue - Checks content gating based on members current plan and visibility option set on the requested post/page
This commit is contained in:
parent
044919356e
commit
36379b2806
4 changed files with 316 additions and 50 deletions
|
@ -1,45 +1,42 @@
|
||||||
|
const _ = require('lodash');
|
||||||
const labs = require('../../../../../../services/labs');
|
const labs = require('../../../../../../services/labs');
|
||||||
const membersService = require('../../../../../../services/members');
|
|
||||||
const MEMBER_TAG = '#members';
|
|
||||||
const PERMIT_CONTENT = false;
|
|
||||||
const BLOCK_CONTENT = true;
|
|
||||||
|
|
||||||
// Checks if request should hide memnbers only content
|
// Checks if request should hide members only content
|
||||||
function hideMembersOnlyContent(attrs, frame) {
|
function hideMembersOnlyContent({visibility}, frame) {
|
||||||
const membersEnabled = labs.isSet('members');
|
const PERMIT_CONTENT = false;
|
||||||
if (!membersEnabled) {
|
const BLOCK_CONTENT = true;
|
||||||
|
|
||||||
|
if (visibility === 'public') {
|
||||||
return PERMIT_CONTENT;
|
return PERMIT_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const postHasMemberTag = attrs.tags && attrs.tags.find((tag) => {
|
|
||||||
return (tag.name === MEMBER_TAG);
|
|
||||||
});
|
|
||||||
const requestFromMember = frame.original.context.member;
|
const requestFromMember = frame.original.context.member;
|
||||||
if (!postHasMemberTag) {
|
|
||||||
return PERMIT_CONTENT;
|
|
||||||
}
|
|
||||||
if (!requestFromMember) {
|
if (!requestFromMember) {
|
||||||
return BLOCK_CONTENT;
|
return BLOCK_CONTENT;
|
||||||
|
} else if (visibility === 'members') {
|
||||||
|
return PERMIT_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const memberHasPlan = !!(frame.original.context.member.stripe.subscriptions || []).length;
|
const memberHasPlan = !!(_.get(frame, 'original.context.member.stripe.subscriptions', [])).length;
|
||||||
if (!membersService.isPaymentConfigured()) {
|
|
||||||
return PERMIT_CONTENT;
|
if (visibility === 'paid' && memberHasPlan) {
|
||||||
}
|
|
||||||
if (memberHasPlan) {
|
|
||||||
return PERMIT_CONTENT;
|
return PERMIT_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BLOCK_CONTENT;
|
return BLOCK_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const forPost = (attrs, frame) => {
|
const forPost = (attrs, frame) => {
|
||||||
const hideFormatsData = hideMembersOnlyContent(attrs, frame);
|
|
||||||
if (hideFormatsData) {
|
|
||||||
['plaintext', 'html'].forEach((field) => {
|
|
||||||
attrs[field] = '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (labs.isSet('members')) {
|
if (labs.isSet('members')) {
|
||||||
|
const hideFormatsData = hideMembersOnlyContent(attrs, frame);
|
||||||
|
|
||||||
|
if (hideFormatsData) {
|
||||||
|
['plaintext', 'html'].forEach((field) => {
|
||||||
|
attrs[field] = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// CASE: Members always adds tags, remove if the user didn't originally ask for them
|
// CASE: Members always adds tags, remove if the user didn't originally ask for them
|
||||||
const origQueryOrOptions = frame.original.query || frame.original.options || {};
|
const origQueryOrOptions = frame.original.query || frame.original.options || {};
|
||||||
const origInclude = origQueryOrOptions.include;
|
const origInclude = origQueryOrOptions.include;
|
||||||
|
|
|
@ -1,45 +1,42 @@
|
||||||
|
const _ = require('lodash');
|
||||||
const labs = require('../../../../../../services/labs');
|
const labs = require('../../../../../../services/labs');
|
||||||
const membersService = require('../../../../../../services/members');
|
|
||||||
const MEMBER_TAG = '#members';
|
|
||||||
const PERMIT_CONTENT = false;
|
|
||||||
const BLOCK_CONTENT = true;
|
|
||||||
|
|
||||||
// Checks if request should hide memnbers only content
|
// Checks if request should hide members only content
|
||||||
function hideMembersOnlyContent(attrs, frame) {
|
function hideMembersOnlyContent({visibility}, frame) {
|
||||||
const membersEnabled = labs.isSet('members');
|
const PERMIT_CONTENT = false;
|
||||||
if (!membersEnabled) {
|
const BLOCK_CONTENT = true;
|
||||||
|
|
||||||
|
if (visibility === 'public') {
|
||||||
return PERMIT_CONTENT;
|
return PERMIT_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const postHasMemberTag = attrs.tags && attrs.tags.find((tag) => {
|
|
||||||
return (tag.name === MEMBER_TAG);
|
|
||||||
});
|
|
||||||
const requestFromMember = frame.original.context.member;
|
const requestFromMember = frame.original.context.member;
|
||||||
if (!postHasMemberTag) {
|
|
||||||
return PERMIT_CONTENT;
|
|
||||||
}
|
|
||||||
if (!requestFromMember) {
|
if (!requestFromMember) {
|
||||||
return BLOCK_CONTENT;
|
return BLOCK_CONTENT;
|
||||||
|
} else if (visibility === 'members') {
|
||||||
|
return PERMIT_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const memberHasPlan = !!(frame.original.context.member.stripe.subscriptions).length;
|
const memberHasPlan = !!(_.get(frame, 'original.context.member.stripe.subscriptions', [])).length;
|
||||||
if (!membersService.isPaymentConfigured()) {
|
|
||||||
return PERMIT_CONTENT;
|
if (visibility === 'paid' && memberHasPlan) {
|
||||||
}
|
|
||||||
if (memberHasPlan) {
|
|
||||||
return PERMIT_CONTENT;
|
return PERMIT_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BLOCK_CONTENT;
|
return BLOCK_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const forPost = (attrs, frame) => {
|
const forPost = (attrs, frame) => {
|
||||||
const hideFormatsData = hideMembersOnlyContent(attrs, frame);
|
|
||||||
if (hideFormatsData) {
|
|
||||||
['plaintext', 'html'].forEach((field) => {
|
|
||||||
attrs[field] = '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (labs.isSet('members')) {
|
if (labs.isSet('members')) {
|
||||||
|
const hideFormatsData = hideMembersOnlyContent(attrs, frame);
|
||||||
|
|
||||||
|
if (hideFormatsData) {
|
||||||
|
['plaintext', 'html'].forEach((field) => {
|
||||||
|
attrs[field] = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// CASE: Members always adds tags, remove if the user didn't originally ask for them
|
// CASE: Members always adds tags, remove if the user didn't originally ask for them
|
||||||
const origQueryOrOptions = frame.original.query || frame.original.options || {};
|
const origQueryOrOptions = frame.original.query || frame.original.options || {};
|
||||||
const origInclude = origQueryOrOptions.include;
|
const origInclude = origQueryOrOptions.include;
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
const should = require('should');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
const labs = require('../../../../../../../../server/services/labs');
|
||||||
|
const members = require('../../../../../../../../server/api/canary/utils/serializers/output/utils/members');
|
||||||
|
|
||||||
|
describe('Unit: canary/utils/serializers/output/utils/members', function () {
|
||||||
|
describe('for post', function () {
|
||||||
|
it('does not modify attributes when members is disabled', function () {
|
||||||
|
const attrs = {
|
||||||
|
plaintext: 'no touching',
|
||||||
|
html: '<p>I am here to stay</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
options: {}
|
||||||
|
};
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('no touching');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('labs.members enabled', function () {
|
||||||
|
before(function () {
|
||||||
|
sinon.stub(labs, 'isSet').returns(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT hide content attributes when visibility is public', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'public',
|
||||||
|
plaintext: 'no touching',
|
||||||
|
html: '<p>I am here to stay</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('no touching');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide content attributes when visibility is "members"', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'members',
|
||||||
|
plaintext: 'no touching. secret stuff',
|
||||||
|
html: '<p>I am here to stay</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('');
|
||||||
|
attrs.html.should.eql('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT hide content attributes when visibility is "members" and member is present', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'members',
|
||||||
|
plaintext: 'I see dead people',
|
||||||
|
html: '<p>What\'s the matter?</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {
|
||||||
|
member: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('I see dead people');
|
||||||
|
attrs.html.should.eql('<p>What\'s the matter?</p>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide content attributes when visibility is "paid" and member has no subscription', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'paid',
|
||||||
|
plaintext: 'I see dead people',
|
||||||
|
html: '<p>What\'s the matter?</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {
|
||||||
|
member: {
|
||||||
|
stripe: {
|
||||||
|
subscriptions: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('');
|
||||||
|
attrs.html.should.eql('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT hide content attributes when visibility is "paid" and member has a subscription', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'paid',
|
||||||
|
plaintext: 'Secret paid content',
|
||||||
|
html: '<p>Can read this</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {
|
||||||
|
member: {
|
||||||
|
stripe: {
|
||||||
|
subscriptions: ['I pay money dollaz']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('Secret paid content');
|
||||||
|
attrs.html.should.eql('<p>Can read this</p>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,136 @@
|
||||||
|
const should = require('should');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
const labs = require('../../../../../../../../server/services/labs');
|
||||||
|
const members = require('../../../../../../../../server/api/v2/utils/serializers/output/utils/members');
|
||||||
|
|
||||||
|
describe('Unit: v2/utils/serializers/output/utils/members', function () {
|
||||||
|
describe('for post', function () {
|
||||||
|
it('does not modify attributes when members is disabled', function () {
|
||||||
|
const attrs = {
|
||||||
|
plaintext: 'no touching',
|
||||||
|
html: '<p>I am here to stay</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
options: {}
|
||||||
|
};
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('no touching');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('labs.members enabled', function () {
|
||||||
|
before(function () {
|
||||||
|
sinon.stub(labs, 'isSet').returns(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT hide content attributes when visibility is public', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'public',
|
||||||
|
plaintext: 'no touching',
|
||||||
|
html: '<p>I am here to stay</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('no touching');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide content attributes when visibility is "members"', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'members',
|
||||||
|
plaintext: 'no touching. secret stuff',
|
||||||
|
html: '<p>I am here to stay</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('');
|
||||||
|
attrs.html.should.eql('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT hide content attributes when visibility is "members" and member is present', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'members',
|
||||||
|
plaintext: 'I see dead people',
|
||||||
|
html: '<p>What\'s the matter?</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {
|
||||||
|
member: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('I see dead people');
|
||||||
|
attrs.html.should.eql('<p>What\'s the matter?</p>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide content attributes when visibility is "paid" and member has no subscription', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'paid',
|
||||||
|
plaintext: 'I see dead people',
|
||||||
|
html: '<p>What\'s the matter?</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {
|
||||||
|
member: {
|
||||||
|
stripe: {
|
||||||
|
subscriptions: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('');
|
||||||
|
attrs.html.should.eql('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT hide content attributes when visibility is "paid" and member has a subscription', function () {
|
||||||
|
const attrs = {
|
||||||
|
visibility: 'paid',
|
||||||
|
plaintext: 'Secret paid content',
|
||||||
|
html: '<p>Can read this</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
const frame = {
|
||||||
|
original: {
|
||||||
|
context: {
|
||||||
|
member: {
|
||||||
|
stripe: {
|
||||||
|
subscriptions: ['I pay money dollaz']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
members.forPost(attrs, frame);
|
||||||
|
|
||||||
|
attrs.plaintext.should.eql('Secret paid content');
|
||||||
|
attrs.html.should.eql('<p>Can read this</p>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue