diff --git a/core/server/models/base/index.js b/core/server/models/base/index.js index d87464e53a..63b5214589 100644 --- a/core/server/models/base/index.js +++ b/core/server/models/base/index.js @@ -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; }); }, diff --git a/core/server/models/post.js b/core/server/models/post.js index dbe13c007d..49d016c6bc 100644 --- a/core/server/models/post.js +++ b/core/server/models/post.js @@ -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 || {}; diff --git a/core/test/integration/api/api_posts_spec.js b/core/test/integration/api/api_posts_spec.js index 491ff7786c..001011d020 100644 --- a/core/test/integration/api/api_posts_spec.js +++ b/core/test/integration/api/api_posts_spec.js @@ -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);