mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
fix: "url" field is undefined when restricting returned fields (#7089)
closes #6625 - "url" and "author" fields depend on {id, published_at, slug, author_id} to construct post url. - implemented a generic solution by defining defaultColumnsToFetch() in base class for models. - findPage() calls defaultColumnsToFetch() before loading models - results are transformed by filtering out additional properties to return just the requested fields - Added a test case to check for url and author fields - Renamed allColumns as requestedColumns and used _.map instead of Promise.map
This commit is contained in:
parent
7904253f62
commit
ffd3ec563a
3 changed files with 47 additions and 8 deletions
|
@ -65,6 +65,11 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
|||
};
|
||||
},
|
||||
|
||||
// When loading an instance, subclasses can specify default to fetch
|
||||
defaultColumnsToFetch: function defaultColumnsToFetch() {
|
||||
return [];
|
||||
},
|
||||
|
||||
// Bookshelf `initialize` - declare a constructor-like method for model creation
|
||||
initialize: function initialize() {
|
||||
var self = this,
|
||||
|
@ -318,10 +323,10 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
|||
findPage: function findPage(options) {
|
||||
options = options || {};
|
||||
|
||||
var self = this,
|
||||
itemCollection = this.forge(null, {context: options.context}),
|
||||
tableName = _.result(this.prototype, 'tableName'),
|
||||
allColumns = options.columns;
|
||||
var self = this,
|
||||
itemCollection = this.forge(null, {context: options.context}),
|
||||
tableName = _.result(this.prototype, 'tableName'),
|
||||
requestedColumns = options.columns;
|
||||
|
||||
// Set this to true or pass ?debug=true as an API option to get output
|
||||
itemCollection.debug = options.debug && process.env.NODE_ENV !== 'production';
|
||||
|
@ -342,8 +347,10 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
|||
options.withRelated = _.union(options.withRelated, options.include);
|
||||
|
||||
// Ensure only valid fields/columns are added to query
|
||||
// and append default columns to fetch
|
||||
if (options.columns) {
|
||||
options.columns = _.intersection(options.columns, this.prototype.permittedAttributes());
|
||||
options.columns = _.union(options.columns, this.prototype.defaultColumnsToFetch());
|
||||
}
|
||||
|
||||
if (options.order) {
|
||||
|
@ -355,13 +362,18 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
|||
}
|
||||
|
||||
return itemCollection.fetchPage(options).then(function formatResponse(response) {
|
||||
var data = {};
|
||||
var data = {},
|
||||
models = [];
|
||||
|
||||
options.columns = requestedColumns;
|
||||
models = response.collection.toJSON(options);
|
||||
|
||||
// re-add any computed properties that were stripped out before the call to fetchPage
|
||||
options.columns = allColumns;
|
||||
data[tableName] = response.collection.toJSON(options);
|
||||
// pick only requested before returning JSON
|
||||
data[tableName] = _.map(models, function transform(model) {
|
||||
return options.columns ? _.pick(model, options.columns) : model;
|
||||
});
|
||||
data.meta = {pagination: response.pagination};
|
||||
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
|
|
@ -393,6 +393,10 @@ Post = ghostBookshelf.Model.extend({
|
|||
return this.morphMany('AppField', 'relatable');
|
||||
},
|
||||
|
||||
defaultColumnsToFetch: function defaultColumnsToFetch() {
|
||||
return ['id', 'published_at', 'slug', 'author_id'];
|
||||
},
|
||||
|
||||
toJSON: function toJSON(options) {
|
||||
options = options || {};
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ var Promise = require('bluebird'),
|
|||
should = require('should'),
|
||||
_ = require('lodash'),
|
||||
testUtils = require('../../utils'),
|
||||
configUtils = require('../../utils/configUtils'),
|
||||
errors = require('../../../server/errors'),
|
||||
db = require('../../../server/data/db'),
|
||||
models = require('../../../server/models'),
|
||||
|
@ -45,6 +46,16 @@ describe('Post API', function () {
|
|||
should.exist(PostAPI);
|
||||
|
||||
describe('Browse', function () {
|
||||
beforeEach(function () {
|
||||
configUtils.set({theme: {
|
||||
permalinks: '/:slug/'
|
||||
}});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
configUtils.restore();
|
||||
});
|
||||
|
||||
it('can fetch all posts with internal context in correct order', function (done) {
|
||||
PostAPI.browse({context: {internal: true}}).then(function (results) {
|
||||
should.exist(results.posts);
|
||||
|
@ -359,6 +370,18 @@ describe('Post API', function () {
|
|||
}).catch(done);
|
||||
});
|
||||
|
||||
it('with context.user can fetch url and author fields', function (done) {
|
||||
PostAPI.browse({context: {user: 1}, status: 'all', limit: 5}).then(function (results) {
|
||||
should.exist(results.posts);
|
||||
|
||||
should.exist(results.posts[0].url);
|
||||
should.notEqual(results.posts[0].url, 'undefined');
|
||||
should.exist(results.posts[0].author);
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('with context.user can fetch multiple fields and be case insensitive', function (done) {
|
||||
PostAPI.browse({context: {user: 1}, status: 'all', limit: 5, fields: 'Slug,Published_At'}).then(function (results) {
|
||||
should.exist(results.posts);
|
||||
|
|
Loading…
Add table
Reference in a new issue