diff --git a/core/server/api/utils.js b/core/server/api/utils.js index e19e131362..f9e6ce5c72 100644 --- a/core/server/api/utils.js +++ b/core/server/api/utils.js @@ -23,7 +23,7 @@ utils = { // ### Manual Default Options // These must be provided by the endpoint // browseDefaultOptions - valid for all browse api endpoints - browseDefaultOptions: ['page', 'limit'], + browseDefaultOptions: ['page', 'limit', 'fields'], // idDefaultOptions - valid whenever an id is valid idDefaultOptions: ['id'], @@ -112,6 +112,7 @@ utils = { uuid: {isUUID: true}, page: {matches: /^\d+$/}, limit: {matches: /^\d+|all$/}, + fields: {matches: /^[a-z0-9_,]+$/}, name: {} }, // these values are sanitised/validated separately @@ -223,6 +224,15 @@ utils = { return include; }, + prepareFields: function prepareFields(fields) { + fields = fields || ''; + if (_.isString(fields)) { + fields = fields.split(','); + } + + return fields; + }, + /** * ## Convert Options * @param {Array} allowedIncludes @@ -238,6 +248,10 @@ utils = { if (options.include) { options.include = utils.prepareInclude(options.include, allowedIncludes); } + if (options.fields) { + options.columns = utils.prepareFields(options.fields); + delete options.fields; + } return options; }; }, diff --git a/core/server/models/post.js b/core/server/models/post.js index 2a5ea6e6ab..26c8d23fcc 100644 --- a/core/server/models/post.js +++ b/core/server/models/post.js @@ -264,11 +264,18 @@ Post = ghostBookshelf.Model.extend({ }, toJSON: function toJSON(options) { + options = options || {}; + var attrs = ghostBookshelf.Model.prototype.toJSON.call(this, options); - attrs.author = attrs.author || attrs.author_id; - attrs.url = config.urlPathForPost(attrs, permalinkSetting); - delete attrs.author_id; + if (!options.columns || (options.columns && options.columns.indexOf('author') > -1)) { + attrs.author = attrs.author || attrs.author_id; + delete attrs.author_id; + } + + if (!options.columns || (options.columns && options.columns.indexOf('url') > -1)) { + attrs.url = config.urlPathForPost(attrs, permalinkSetting); + } return attrs; } @@ -346,7 +353,7 @@ Post = ghostBookshelf.Model.extend({ validOptions = { findAll: ['withRelated'], findOne: ['importing', 'withRelated'], - findPage: ['page', 'limit', 'status', 'staticPages', 'featured'], + findPage: ['page', 'limit', 'columns', 'status', 'staticPages', 'featured'], add: ['importing'] }; diff --git a/core/server/models/tag.js b/core/server/models/tag.js index 3029f0eb3f..df8fa0bd44 100644 --- a/core/server/models/tag.js +++ b/core/server/models/tag.js @@ -49,6 +49,8 @@ Tag = ghostBookshelf.Model.extend({ }, toJSON: function toJSON(options) { + options = options || {}; + var attrs = ghostBookshelf.Model.prototype.toJSON.call(this, options); attrs.parent = attrs.parent || attrs.parent_id; @@ -81,7 +83,7 @@ Tag = ghostBookshelf.Model.extend({ // whitelists for the `options` hash argument on methods, by method name. // these are the only options that can be passed to Bookshelf / Knex. validOptions = { - findPage: ['page', 'limit'] + findPage: ['page', 'limit', 'columns'] }; if (validOptions[methodName]) { diff --git a/core/server/models/user.js b/core/server/models/user.js index 81678eb521..3a5c927261 100644 --- a/core/server/models/user.js +++ b/core/server/models/user.js @@ -120,6 +120,8 @@ User = ghostBookshelf.Model.extend({ }, toJSON: function toJSON(options) { + options = options || {}; + var attrs = ghostBookshelf.Model.prototype.toJSON.call(this, options); // remove password hash for security reasons delete attrs.password; @@ -229,7 +231,7 @@ User = ghostBookshelf.Model.extend({ findAll: ['withRelated'], setup: ['id'], edit: ['withRelated', 'id'], - findPage: ['page', 'limit', 'status'] + findPage: ['page', 'limit', 'columns', 'status'] }; if (validOptions[methodName]) { diff --git a/core/test/unit/api_utils_spec.js b/core/test/unit/api_utils_spec.js index ad1e0ff759..b6b5af0415 100644 --- a/core/test/unit/api_utils_spec.js +++ b/core/test/unit/api_utils_spec.js @@ -18,7 +18,7 @@ describe('API Utils', function () { describe('Default Options', function () { it('should provide a set of default options', function () { apiUtils.globalDefaultOptions.should.eql(['context', 'include']); - apiUtils.browseDefaultOptions.should.eql(['page', 'limit']); + apiUtils.browseDefaultOptions.should.eql(['page', 'limit', 'fields']); apiUtils.dataDefaultOptions.should.eql(['data']); apiUtils.idDefaultOptions.should.eql(['id']); });