Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit 929660c

Browse files
committed
Add v2.6.1
1 parent 57871ab commit 929660c

File tree

16 files changed

+161
-135
lines changed

16 files changed

+161
-135
lines changed

core/built/assets/vendor.min-3d45f4fcdb055b37c95a7c146cc49d44.js core/built/assets/vendor.min-4267009638f156224c1b0468b72f2410.js

+15-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/server/api/v2/utils/serializers/input/posts.js

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const _ = require('lodash');
22
const debug = require('ghost-ignition').debug('api:v2:utils:serializers:input:posts');
33
const url = require('./utils/url');
44
const utils = require('../../index');
5+
const labs = require('../../../../../services/labs');
56

67
function removeMobiledocFormat(frame) {
78
if (frame.options.formats && frame.options.formats.includes('mobiledoc')) {
@@ -11,6 +12,14 @@ function removeMobiledocFormat(frame) {
1112
}
1213
}
1314

15+
function includeTags(frame) {
16+
if (!frame.options.withRelated) {
17+
frame.options.withRelated = ['tags'];
18+
} else if (!frame.options.withRelated.includes('tags')) {
19+
frame.options.withRelated.push('tags');
20+
}
21+
}
22+
1423
module.exports = {
1524
browse(apiConfig, frame) {
1625
debug('browse');
@@ -39,6 +48,10 @@ module.exports = {
3948
}
4049
// CASE: the content api endpoint for posts should not return mobiledoc
4150
removeMobiledocFormat(frame);
51+
if (labs.isSet('members')) {
52+
// CASE: Members needs to have the tags to check if its allowed access
53+
includeTags(frame);
54+
}
4255
}
4356

4457
debug(frame.options);
@@ -58,6 +71,10 @@ module.exports = {
5871
frame.data.page = false;
5972
// CASE: the content api endpoint for posts should not return mobiledoc
6073
removeMobiledocFormat(frame);
74+
if (labs.isSet('members')) {
75+
// CASE: Members needs to have the tags to check if its allowed access
76+
includeTags(frame);
77+
}
6178
}
6279

6380
debug(frame.options);

core/server/api/v2/utils/serializers/output/utils/mapper.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const utils = require('../../../index');
22
const url = require('./url');
33
const date = require('./date');
4+
const members = require('./members');
45

56
const mapPost = (model, frame) => {
67
const jsonModel = model.toJSON(frame.options);
@@ -9,6 +10,7 @@ const mapPost = (model, frame) => {
910

1011
if (utils.isContentAPI(frame)) {
1112
date.forPost(jsonModel);
13+
members.forPost(jsonModel, frame);
1214
}
1315

1416
if (frame.options && frame.options.withRelated) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const labs = require('../../../../../../services/labs');
2+
const MEMBER_TAG = '#members';
3+
4+
// Checks if request should hide memnbers only content
5+
function hideMembersOnlyContent(attrs, frame) {
6+
let hasMemberTag = false;
7+
if (labs.isSet('members') && !frame.original.context.member && attrs.tags) {
8+
hasMemberTag = attrs.tags.find((tag) => {
9+
return (tag.name === MEMBER_TAG);
10+
});
11+
}
12+
return hasMemberTag;
13+
}
14+
15+
const forPost = (attrs, frame) => {
16+
const hideFormatsData = hideMembersOnlyContent(attrs, frame);
17+
if (hideFormatsData) {
18+
['plaintext', 'html'].forEach((field) => {
19+
attrs[field] = '';
20+
});
21+
}
22+
if (labs.isSet('members')) {
23+
// CASE: Members always adds tags, remove if the user didn't originally ask for them
24+
const origQueryOrOptions = frame.original.query || frame.original.options || {};
25+
const origInclude = origQueryOrOptions.include;
26+
27+
if (!origInclude || !origInclude.includes('tags')) {
28+
delete attrs.tags;
29+
}
30+
}
31+
32+
return attrs;
33+
};
34+
35+
module.exports.forPost = forPost;

core/server/data/schema/schema.js

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
/* String Column Sizes Information
2+
* (From: https://github.com/TryGhost/Ghost/pull/7932)
3+
*
4+
* Small strings = length 50
5+
* Medium strings = length 191
6+
* Large strings = length 1000-2000
7+
* Text = length 65535 (64 KiB)
8+
* Long text = length 1,000,000,000
9+
*/
110
module.exports = {
211
posts: {
312
id: {type: 'string', maxlength: 24, nullable: false, primary: true},

core/server/models/base/index.js

+2-14
Original file line numberDiff line numberDiff line change
@@ -646,15 +646,10 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
646646
var options = this.filterOptions(unfilteredOptions, 'findAll'),
647647
itemCollection = this.forge();
648648

649-
// transforms fictive keywords like 'all' (status:all) into correct allowed values
650-
if (this.processOptions) {
651-
this.processOptions(options);
652-
}
653-
654649
// @TODO: we can't use order raw when running migrations (see https://github.com/tgriesser/knex/issues/2763)
655650
if (this.orderDefaultRaw && !options.migrating) {
656651
itemCollection.query((qb) => {
657-
qb.orderByRaw(this.orderDefaultRaw());
652+
qb.orderByRaw(this.orderDefaultRaw(options));
658653
});
659654
}
660655

@@ -702,13 +697,6 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
702697
// Set this to true or pass ?debug=true as an API option to get output
703698
itemCollection.debug = options.debug && config.get('env') !== 'production';
704699

705-
// This applies default properties like 'staticPages' and 'status'
706-
// And then converts them to 'where' options... this behaviour is effectively deprecated in favour
707-
// of using filter - it's only be being kept here so that we can transition cleanly.
708-
if (this.processOptions) {
709-
this.processOptions(options);
710-
}
711-
712700
// Add Filter behaviour
713701
itemCollection.applyDefaultAndCustomFilters(options);
714702

@@ -722,7 +710,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
722710
if (options.order) {
723711
options.order = this.parseOrderOption(options.order, options.withRelated);
724712
} else if (this.orderDefaultRaw) {
725-
options.orderRaw = this.orderDefaultRaw();
713+
options.orderRaw = this.orderDefaultRaw(options);
726714
} else if (this.orderDefaultOptions) {
727715
options.order = this.orderDefaultOptions();
728716
}

core/server/models/invite.js

-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ Invite = ghostBookshelf.Model.extend({
2424
return {};
2525
},
2626

27-
processOptions: function processOptions(options) {
28-
return options;
29-
},
30-
3127
add: function add(data, unfilteredOptions) {
3228
const options = Invite.filterOptions(unfilteredOptions, 'add');
3329
data = data || {};

core/server/models/plugins/filter.js

+3-19
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ filter = function filter(Bookshelf) {
8383
},
8484
defaultFilters: function defaultFilters() {
8585
},
86+
extraFilters: function extraFilters() {
87+
},
8688

8789
preProcessFilters: function preProcessFilters() {
8890
this._filters.statements = gql.json.replaceStatements(this._filters.statements, {prop: /primary_tag/}, function (statement) {
@@ -124,15 +126,6 @@ filter = function filter(Bookshelf) {
124126
.query('leftOuterJoin', 'posts_tags', 'posts_tags.post_id', '=', 'posts.id')
125127
.query('leftOuterJoin', 'tags', 'posts_tags.tag_id', '=', 'tags.id');
126128

127-
// The order override should ONLY happen if we are doing an "IN" query
128-
// TODO move the order handling to the query building that is currently inside pagination
129-
// TODO make the order handling in pagination handle orderByRaw
130-
// TODO extend this handling to all joins
131-
if (gql.json.findStatement(this._filters.statements, {prop: /^tags/, op: 'IN'})) {
132-
// TODO make this count the number of MATCHING tags, not just the number of tags
133-
this.query('orderByRaw', 'count(tags.id) DESC');
134-
}
135-
136129
// We need to add a group by to counter the double left outer join
137130
// TODO improve on the group by handling
138131
options.groups = options.groups || [];
@@ -146,15 +139,6 @@ filter = function filter(Bookshelf) {
146139
.query('leftOuterJoin', 'posts_authors', 'posts_authors.post_id', '=', 'posts.id')
147140
.query('leftOuterJoin', 'users as authors', 'posts_authors.author_id', '=', 'authors.id');
148141

149-
// The order override should ONLY happen if we are doing an "IN" query
150-
// TODO move the order handling to the query building that is currently inside pagination
151-
// TODO make the order handling in pagination handle orderByRaw
152-
// TODO extend this handling to all joins
153-
if (gql.json.findStatement(this._filters.statements, {prop: /^authors/, op: 'IN'})) {
154-
// TODO make this count the number of MATCHING authors, not just the number of authors
155-
this.query('orderByRaw', 'count(authors.id) DESC');
156-
}
157-
158142
// We need to add a group by to counter the double left outer join
159143
// TODO improve on the group by handling
160144
options.groups = options.groups || [];
@@ -184,7 +168,7 @@ filter = function filter(Bookshelf) {
184168
this.enforcedFilters(options),
185169
this.defaultFilters(options),
186170
options.filter,
187-
options.where
171+
this.extraFilters(options)
188172
);
189173

190174
return this;

core/server/models/post.js

+55-36
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const config = require('../config');
1111
const converters = require('../lib/mobiledoc/converters');
1212
const relations = require('./relations');
1313
const MOBILEDOC_REVISIONS_COUNT = 10;
14+
const ALL_STATUSES = ['published', 'draft', 'scheduled'];
1415

1516
let Post;
1617
let Posts;
@@ -517,6 +518,51 @@ Post = ghostBookshelf.Model.extend({
517518
}
518519

519520
return options.context && options.context.public ? 'page:false' : 'page:false+status:published';
521+
},
522+
523+
/**
524+
* You can pass an extra `status=VALUES` or "staticPages" field.
525+
* Long-Term: We should deprecate these short cuts and force users to use the filter param.
526+
*/
527+
extraFilters: function extraFilters(options) {
528+
if (!options.staticPages && !options.status) {
529+
return null;
530+
}
531+
532+
let filter = null;
533+
534+
// CASE: "staticPages" is passed
535+
if (options.staticPages && options.staticPages !== 'all') {
536+
// CASE: convert string true/false to boolean
537+
if (!_.isBoolean(options.staticPages)) {
538+
options.staticPages = _.includes(['true', '1'], options.staticPages);
539+
}
540+
541+
filter = `page:${options.staticPages}`;
542+
} else if (options.staticPages === 'all') {
543+
filter = 'page:[true, false]';
544+
}
545+
546+
// CASE: "status" is passed, combine filters
547+
if (options.status && options.status !== 'all') {
548+
options.status = _.includes(ALL_STATUSES, options.status) ? options.status : 'published';
549+
550+
if (!filter) {
551+
filter = `status:${options.status}`;
552+
} else {
553+
filter = `${filter}+status:${options.status}`;
554+
}
555+
} else if (options.status === 'all') {
556+
if (!filter) {
557+
filter = `status:[${ALL_STATUSES}]`;
558+
} else {
559+
filter = `${filter}+status:[${ALL_STATUSES}]`;
560+
}
561+
}
562+
563+
delete options.status;
564+
delete options.staticPages;
565+
return filter;
520566
}
521567
}, {
522568
allowedFormats: ['mobiledoc', 'html', 'plaintext'],
@@ -530,53 +576,26 @@ Post = ghostBookshelf.Model.extend({
530576
};
531577
},
532578

533-
orderDefaultRaw: function () {
534-
return '' +
579+
orderDefaultRaw: function (options) {
580+
let order = '' +
535581
'CASE WHEN posts.status = \'scheduled\' THEN 1 ' +
536582
'WHEN posts.status = \'draft\' THEN 2 ' +
537583
'ELSE 3 END ASC,' +
538584
'CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,' +
539585
'posts.updated_at DESC,' +
540586
'posts.id DESC';
541-
},
542-
543-
/**
544-
* @deprecated in favour of filter
545-
*/
546-
processOptions: function processOptions(options) {
547-
if (!options.staticPages && !options.status) {
548-
return options;
549-
}
550-
551-
// This is the only place that 'options.where' is set now
552-
options.where = {statements: []};
553587

554-
// Step 4: Setup filters (where clauses)
555-
if (options.staticPages && options.staticPages !== 'all') {
556-
// convert string true/false to boolean
557-
if (!_.isBoolean(options.staticPages)) {
558-
options.staticPages = _.includes(['true', '1'], options.staticPages);
559-
}
560-
options.where.statements.push({prop: 'page', op: '=', value: options.staticPages});
561-
delete options.staticPages;
562-
} else if (options.staticPages === 'all') {
563-
options.where.statements.push({prop: 'page', op: 'IN', value: [true, false]});
564-
delete options.staticPages;
588+
// CASE: if the filter contains an `IN` operator, we should return the posts first, which match both tags
589+
if (options.filter && options.filter.match(/(tags|tag):\s?\[.*\]/)) {
590+
order = `count(tags.id) DESC, ${order}`;
565591
}
566592

567-
// Unless `all` is passed as an option, filter on
568-
// the status provided.
569-
if (options.status && options.status !== 'all') {
570-
// make sure that status is valid
571-
options.status = _.includes(['published', 'draft', 'scheduled'], options.status) ? options.status : 'published';
572-
options.where.statements.push({prop: 'status', op: '=', value: options.status});
573-
delete options.status;
574-
} else if (options.status === 'all') {
575-
options.where.statements.push({prop: 'status', op: 'IN', value: ['published', 'draft', 'scheduled']});
576-
delete options.status;
593+
// CASE: if the filter contains an `IN` operator, we should return the posts first, which match both authors
594+
if (options.filter && options.filter.match(/(authors|author):\s?\[.*\]/)) {
595+
order = `count(authors.id) DESC, ${order}`;
577596
}
578597

579-
return options;
598+
return order;
580599
},
581600

582601
/**

core/server/models/subscriber.js

-6
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@ Subscriber = ghostBookshelf.Model.extend({
3535
orderDefaultOptions: function orderDefaultOptions() {
3636
return {};
3737
},
38-
/**
39-
* @deprecated in favour of filter
40-
*/
41-
processOptions: function processOptions(options) {
42-
return options;
43-
},
4438

4539
permittedOptions: function permittedOptions(methodName) {
4640
var options = ghostBookshelf.Model.permittedOptions.call(this, methodName),

core/server/models/tag.js

-7
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,6 @@ Tag = ghostBookshelf.Model.extend({
7575
return {};
7676
},
7777

78-
/**
79-
* @deprecated in favour of filter
80-
*/
81-
processOptions: function processOptions(options) {
82-
return options;
83-
},
84-
8578
permittedOptions: function permittedOptions(methodName) {
8679
var options = ghostBookshelf.Model.permittedOptions.call(this, methodName),
8780

0 commit comments

Comments
 (0)