From d318f1cc65c3a61f6e5caaebdf936a7ef3f9dc1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Georget?= Date: Mon, 1 Feb 2016 17:38:08 +0100 Subject: [PATCH] Handle fields selection in query --- .../hooks/jsonapi/helpers/request.js | 37 ++++++++++++++----- .../hooks/jsonapi/helpers/response.js | 10 ++--- .../hooks/jsonapi/utils/utils.js | 14 +++++-- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/lib/configuration/hooks/jsonapi/helpers/request.js b/lib/configuration/hooks/jsonapi/helpers/request.js index 5d81e347ac..7dcaa7df51 100644 --- a/lib/configuration/hooks/jsonapi/helpers/request.js +++ b/lib/configuration/hooks/jsonapi/helpers/request.js @@ -82,15 +82,34 @@ module.exports = { */ fetchQuery: function * (ctx) { - _.forEach(_.keys(ctx.query), function (key) { - if (_.includes(['include', 'fields', 'sort', 'page', 'filter'], key)) { - throw { - status: 400, - body: { - message: 'Parameter `' + key + '` is not supported yet' - } - }; - } + // Use context namespace for passing information throug middleware + ctx.state.filter = { + fields: {} + }; + + _.forEach(ctx.query, function (value, key) { + if (_.includes(['include', 'sort', 'page', 'filter'], key)) { + throw { + status: 400, + body: { + message: 'Parameter `' + key + '` is not supported yet' + } + }; + } else if (key.indexOf('fields') !== -1) { + const alias = key.match(/\[(.*?)\]/)[1]; + const type = utils.getType(ctx, alias); + + if (_.isUndefined(type)) { + throw { + status: 403, + body: { + message: 'Wrong `type` in fields parameters' + } + }; + } + + ctx.state.filter.fields[type] = value.split(','); + } }); }, diff --git a/lib/configuration/hooks/jsonapi/helpers/response.js b/lib/configuration/hooks/jsonapi/helpers/response.js index 60f40d9d1a..cc4e37a68d 100644 --- a/lib/configuration/hooks/jsonapi/helpers/response.js +++ b/lib/configuration/hooks/jsonapi/helpers/response.js @@ -91,14 +91,14 @@ module.exports = { } }; - toSerialize.attributes = _.keys(_.last(value)); + toSerialize.attributes = ctx.state.filter.fields[type] || _.keys(_.last(value)); } else if (_.isObject(value) && !_.isEmpty(value)) { // Object if (!_.isNull(PK) && value.hasOwnProperty(PK)) { value[PK] = value[PK].toString(); } - toSerialize.attributes = _.keys(value); + toSerialize.attributes = ctx.state.filter.fields[type] || _.keys(value); } switch (object) { @@ -125,7 +125,7 @@ module.exports = { // Display JSON API version support if (_.isPlainObject(strapi.config.jsonapi) && strapi.config.jsonapi.hasOwnProperty('showVersion') && strapi.config.jsonapi.showVersion === true) { - return _.assign(new JSONAPI(type, value, toSerialize), { + return _.assign(new JSONAPI.Serializer(type, value, toSerialize), { jsonapi: { version: '1.0' } @@ -157,7 +157,7 @@ module.exports = { ref: PK, included: strapi.config.jsonapi.included || false, ignoreRelationshipData: strapi.config.jsonapi.ignoreRelationshipData || false, - attributes: _.keys(_.omit(strapi.models[type].attributes, _.isFunction)), + attributes: ctx.state.filter.fields[relation.model] || _.keys(_.omit(strapi.models[type].attributes, _.isFunction)), relationshipLinks: { self: function (record) { if (record.hasOwnProperty(PK) && availableRoutes.relSlSelf) { @@ -193,7 +193,7 @@ module.exports = { included: strapi.config.jsonapi.included || false, ignoreRelationshipData: strapi.config.jsonapi.ignoreRelationshipData || false, typeForAttribute: relation.collection, - attributes: _.keys(_.omit(strapi.models[type].attributes, _.isFunction)), + attributes: ctx.state.filter.fields[relation.collection] || _.keys(_.omit(strapi.models[type].attributes, _.isFunction)), relationshipLinks: { self: function (record) { if (record.hasOwnProperty(PK) && availableRoutes.relSlSelf) { diff --git a/lib/configuration/hooks/jsonapi/utils/utils.js b/lib/configuration/hooks/jsonapi/utils/utils.js index df5a6267ce..802f47ece0 100644 --- a/lib/configuration/hooks/jsonapi/utils/utils.js +++ b/lib/configuration/hooks/jsonapi/utils/utils.js @@ -53,9 +53,6 @@ module.exports = { */ getType: function (ctx, supposedType) { - // TODO: - // - Parse the URL and try to extract useful information to find the type - // Relationships or related ressource if (strapi.models.hasOwnProperty(supposedType.toLowerCase()) && ctx.params.hasOwnProperty('relation')) { return _.first(_.reject(_.map(strapi.models[supposedType.toLowerCase()].associations, function (relation) { @@ -63,6 +60,17 @@ module.exports = { }), _.isUndefined)); } else if (strapi.models.hasOwnProperty(supposedType.toLowerCase())) { return supposedType.toLowerCase(); + } else if (!strapi.models.hasOwnProperty(supposedType.toLowerCase())) { + // Deep search based on the relation alias + const tryFindType = _.reject(_.flattenDeep(_.map(strapi.models, function (model) { + return _.map(model.associations, function (relation) { + return (supposedType.toLowerCase() === relation.alias) ? relation.model || relation.collection : undefined; + }); + })), _.isUndefined); + + if (!_.isUndefined(tryFindType)) { + return _.first(tryFindType); + } } return undefined;