0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-25 02:31:59 -05:00

Merged 3.22.2 into master

* tag '3.22.2':
  v3.22.2
  Updated Ghost-Admin to v3.22.2
  Emitted all settings events on reinit of cache (#12012)
  🐛 Updated access to be true by default in v3 API
  Hardened members subscription migration against missing data (#12009)
This commit is contained in:
Daniel Lockyer 2020-07-06 16:19:55 +01:00
commit 8956a9df35
10 changed files with 40 additions and 28 deletions

@ -1 +1 @@
Subproject commit 08cfd215fd2d609e57ec3f634e546b3ca9f9aa2e Subproject commit 52fe1b452ad2a2713dd5d0c1a3b3776bd3bee9f1

View file

@ -3,6 +3,12 @@ const labs = require('../../../../../../services/labs');
// @TODO: reconsider the location of this - it's part of members and adds a property to the API // @TODO: reconsider the location of this - it's part of members and adds a property to the API
const forPost = (attrs, frame) => { const forPost = (attrs, frame) => {
// CASE: Access always defaults to true, unless members is enabled and the member does not have access
if (!Object.prototype.hasOwnProperty.call(frame.options, 'columns') || (frame.options.columns.includes('access'))) {
attrs.access = true;
}
// Handle members being enabled
if (labs.isSet('members')) { if (labs.isSet('members')) {
const memberHasAccess = membersService.contentGating.checkPostAccess(attrs, frame.original.context.member); const memberHasAccess = membersService.contentGating.checkPostAccess(attrs, frame.original.context.member);
@ -18,6 +24,7 @@ const forPost = (attrs, frame) => {
attrs.access = memberHasAccess; attrs.access = memberHasAccess;
} }
} }
return attrs; return attrs;
}; };

View file

@ -42,23 +42,25 @@ module.exports = {
.where('key', 'members_subscription_settings') .where('key', 'members_subscription_settings')
.first(); .first();
if (!membersSubscriptionSettingsJSON) { if (!membersSubscriptionSettingsJSON || !membersSubscriptionSettingsJSON.value) {
logging.warn(`Could not find members_subscription_settings - using default values`); logging.warn(`Could not find members_subscription_settings - using default values`);
return; return;
} }
const membersSubscriptionSettings = JSON.parse(membersSubscriptionSettingsJSON.value); const membersSubscriptionSettings = JSON.parse(membersSubscriptionSettingsJSON.value);
const membersFromAddress = membersSubscriptionSettings.fromAddress; const membersFromAddress = typeof membersSubscriptionSettings.fromAddress === 'string' ? membersSubscriptionSettings.fromAddress : 'noreply';
const membersAllowSelfSignup = membersSubscriptionSettings.allowSelfSignup; const membersAllowSelfSignup = typeof membersSubscriptionSettings.allowSelfSignup === 'boolean' ? membersSubscriptionSettings.allowSelfSignup : true;
const stripe = membersSubscriptionSettings.paymentProcessors[0]; const stripe = membersSubscriptionSettings && membersSubscriptionSettings.paymentProcessors && membersSubscriptionSettings.paymentProcessors[0];
const stripeDirectSecretKey = stripe.config.secret_token; const stripeConfig = stripe && stripe.config || {};
const stripeDirectPublishableKey = stripe.config.public_token;
const stripeProductName = stripe.config.product.name;
const stripePlans = stripe.config.plans.map((plan) => { const stripeDirectSecretKey = stripeConfig.secret_token || '';
const stripeDirectPublishableKey = stripeConfig.public_token || '';
const stripeProductName = stripeConfig.product && stripeConfig.product.name || 'Ghost Members';
const stripePlans = (stripeConfig.plans || []).map((plan) => {
return Object.assign(plan, { return Object.assign(plan, {
amount: plan.amount || 0 amount: plan.amount || 0
}); });

View file

@ -6,18 +6,17 @@ const models = require('../../models');
const SettingsCache = require('./cache'); const SettingsCache = require('./cache');
module.exports = { module.exports = {
init: function init() { async init() {
// Update the defaults const settingsCollection = await models.Settings.populateDefaults();
return models.Settings.populateDefaults() SettingsCache.init(settingsCollection);
.then((settingsCollection) => {
// Initialise the cache with the result
// This will bind to events for further updates
SettingsCache.init(settingsCollection);
});
}, },
reinit: function reinit() { async reinit() {
SettingsCache.shutdown(); SettingsCache.shutdown();
return this.init(); const settingsCollection = await models.Settings.populateDefaults();
SettingsCache.init(settingsCollection);
for (const model of settingsCollection.models) {
model.emitChange(model.attributes.key + '.' + 'edited', {});
}
} }
}; };

View file

@ -1,6 +1,6 @@
{ {
"name": "ghost", "name": "ghost",
"version": "3.22.1", "version": "3.22.2",
"description": "The professional publishing platform", "description": "The professional publishing platform",
"author": "Ghost Foundation", "author": "Ghost Foundation",
"homepage": "https://ghost.org", "homepage": "https://ghost.org",

View file

@ -29,6 +29,8 @@ const expectedProperties = {
// .without('page') // .without('page')
// v2 returns a calculated excerpt field // v2 returns a calculated excerpt field
.concat('excerpt') .concat('excerpt')
// Access is a calculated property in >= v3
.concat('access')
// returns meta fields from `posts_meta` schema // returns meta fields from `posts_meta` schema
.concat( .concat(
..._(schema.posts_meta).keys().without('post_id', 'id') ..._(schema.posts_meta).keys().without('post_id', 'id')

View file

@ -227,7 +227,6 @@ describe('api/canary/content/posts', function () {
let publicPost; let publicPost;
let membersPost; let membersPost;
let paidPost; let paidPost;
let contentGatingFields = ['access'];
before(function () { before(function () {
// NOTE: ideally this would be set through Admin API request not a stub // NOTE: ideally this would be set through Admin API request not a stub
@ -291,7 +290,7 @@ describe('api/canary/content/posts', function () {
should.exist(jsonResponse.posts); should.exist(jsonResponse.posts);
const post = jsonResponse.posts[0]; const post = jsonResponse.posts[0];
localUtils.API.checkResponse(post, 'post', contentGatingFields, null); localUtils.API.checkResponse(post, 'post', null, null);
post.slug.should.eql('thou-shalt-not-be-seen'); post.slug.should.eql('thou-shalt-not-be-seen');
post.html.should.eql(''); post.html.should.eql('');
}); });
@ -309,7 +308,7 @@ describe('api/canary/content/posts', function () {
should.exist(jsonResponse.posts); should.exist(jsonResponse.posts);
const post = jsonResponse.posts[0]; const post = jsonResponse.posts[0];
localUtils.API.checkResponse(post, 'post', contentGatingFields, null); localUtils.API.checkResponse(post, 'post', null, null);
post.slug.should.eql('thou-shalt-be-paid-for'); post.slug.should.eql('thou-shalt-be-paid-for');
post.html.should.eql(''); post.html.should.eql('');
}); });
@ -348,7 +347,7 @@ describe('api/canary/content/posts', function () {
should.exist(jsonResponse.posts); should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts'); localUtils.API.checkResponse(jsonResponse, 'posts');
jsonResponse.posts.should.have.length(14); jsonResponse.posts.should.have.length(14);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', contentGatingFields, null); localUtils.API.checkResponse(jsonResponse.posts[0], 'post', null, null);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true); _.isBoolean(jsonResponse.posts[0].featured).should.eql(true);

View file

@ -28,6 +28,8 @@ const expectedProperties = {
.without('type') .without('type')
// canary returns a calculated excerpt field // canary returns a calculated excerpt field
.concat('excerpt') .concat('excerpt')
// Access is a calculated property in >= v3
.concat('access')
// returns meta fields from `posts_meta` schema // returns meta fields from `posts_meta` schema
.concat( .concat(
..._(schema.posts_meta).keys().without('post_id', 'id') ..._(schema.posts_meta).keys().without('post_id', 'id')

View file

@ -227,7 +227,6 @@ describe('api/v3/content/posts', function () {
let publicPost; let publicPost;
let membersPost; let membersPost;
let paidPost; let paidPost;
let contentGatingFields = ['access'];
before(function () { before(function () {
// NOTE: ideally this would be set through Admin API request not a stub // NOTE: ideally this would be set through Admin API request not a stub
@ -291,7 +290,7 @@ describe('api/v3/content/posts', function () {
should.exist(jsonResponse.posts); should.exist(jsonResponse.posts);
const post = jsonResponse.posts[0]; const post = jsonResponse.posts[0];
localUtils.API.checkResponse(post, 'post', contentGatingFields, null); localUtils.API.checkResponse(post, 'post', null, null);
post.slug.should.eql('thou-shalt-not-be-seen'); post.slug.should.eql('thou-shalt-not-be-seen');
post.html.should.eql(''); post.html.should.eql('');
}); });
@ -309,7 +308,7 @@ describe('api/v3/content/posts', function () {
should.exist(jsonResponse.posts); should.exist(jsonResponse.posts);
const post = jsonResponse.posts[0]; const post = jsonResponse.posts[0];
localUtils.API.checkResponse(post, 'post', contentGatingFields, null); localUtils.API.checkResponse(post, 'post', null, null);
post.slug.should.eql('thou-shalt-be-paid-for'); post.slug.should.eql('thou-shalt-be-paid-for');
post.html.should.eql(''); post.html.should.eql('');
}); });
@ -348,7 +347,7 @@ describe('api/v3/content/posts', function () {
should.exist(jsonResponse.posts); should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts'); localUtils.API.checkResponse(jsonResponse, 'posts');
jsonResponse.posts.should.have.length(14); jsonResponse.posts.should.have.length(14);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', contentGatingFields, null); localUtils.API.checkResponse(jsonResponse.posts[0], 'post', null, null);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true); _.isBoolean(jsonResponse.posts[0].featured).should.eql(true);

View file

@ -28,6 +28,8 @@ const expectedProperties = {
.without('type') .without('type')
// v3 returns a calculated excerpt field // v3 returns a calculated excerpt field
.concat('excerpt') .concat('excerpt')
// Access is a calculated property in >= v3
.concat('access')
// returns meta fields from `posts_meta` schema // returns meta fields from `posts_meta` schema
.concat( .concat(
..._(schema.posts_meta).keys().without('post_id', 'id') ..._(schema.posts_meta).keys().without('post_id', 'id')