From c7049253d6d71c2722f29531d964e54101ab4f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Georget?= Date: Wed, 27 Jan 2016 16:45:44 +0100 Subject: [PATCH] Use generators, send strapi instance in parser and optimizations --- .../hooks/jsonapi/helpers/request.js | 81 +++++++++++-------- lib/configuration/hooks/jsonapi/index.js | 69 +++++++++------- lib/configuration/hooks/router/index.js | 2 +- 3 files changed, 91 insertions(+), 61 deletions(-) diff --git a/lib/configuration/hooks/jsonapi/helpers/request.js b/lib/configuration/hooks/jsonapi/helpers/request.js index e633aa3d49..6828cc4db5 100644 --- a/lib/configuration/hooks/jsonapi/helpers/request.js +++ b/lib/configuration/hooks/jsonapi/helpers/request.js @@ -19,17 +19,16 @@ module.exports = { * Parse request */ - parse: function (ctx, cb) { + parse: function * (ctx, cb) { switch (ctx.method.toUpperCase()) { case 'GET': console.log('GET'); break; case 'PUT': case 'POST': - this.fetchSchema(ctx, function (err) { - cb(err); + yield this.fetchSchema(ctx, function * (err) { + yield cb(err); }); - console.log('POST|PUT'); break; case 'DELETE': console.log('DELETE'); @@ -42,40 +41,56 @@ module.exports = { * Fetch attributes schema */ - fetchSchema : function (ctx, cb) { + fetchSchema: function * (ctx, cb) { const attributes = ctx.request.body; if (!attributes.hasOwnProperty('data')) { - ctx.response.status = 404; - ctx.response.body = 'Missing `data` member'; + return yield cb({ + status: 403, + body: 'Missing `data` member' + }); } else if (!attributes.data.hasOwnProperty('type')) { - ctx.response.status = 404; - ctx.response.body = 'Missing `type` member'; + return yield cb({ + status: 403, + body: 'Missing `type` member' + }); } else if (!strapi.models.hasOwnProperty(attributes.data.type)) { - ctx.response.status = 404; - ctx.response.body = 'Unknow `type` ' + attributes.data.type; - } else { - // Extract required attributes - const requiredAttributes = _.filter(strapi.models[attributes.data.type].attributes, {required:true}); - // Identify required relationships - const relationships = _.indexBy(strapi.models[attributes.data.type].associations, 'alias'); - // Extract required relationships - const requiredRelationships = _.intersection(_.keys(requiredAttributes), _.keys(relationships)); - - console.log(requiredAttributes); - console.log(requiredRelationships); - - if (_.size(requiredAttributes) > 0 && _.isEmpty(attributes.data.attributes)) { - ctx.response.status = 404; - ctx.response.body = 'Missing required attributes'; - } else if (!_.isEmpty(_.difference(_.keys(requiredRelationships), _.keys(attributes.data.relationships)))) { - ctx.response.status = 404; - ctx.response.body = 'Missing required relationships'; - } else { - cb(); - console.log("coucou"); - // Looks good - } + return yield cb({ + status: 403, + body: 'Unknow `type` ' + attributes.data.type + }); } + + // Extract required attributes + const requiredAttributes = _.omit(_.mapValues(strapi.models[attributes.data.type].attributes, function (attr) { + return attr.required ? attr : undefined; + }), _.isUndefined); + // Identify missing attributes + const missingAttributes = _.difference(_.keys(requiredAttributes), _.keys(attributes.data.attributes)); + + if (!_.isEmpty(missingAttributes)) { + return yield cb({ + status: 403, + body: 'Missing required attributes (' + missingAttributes.toString() + ')' + }); + } + + // Identify required relationships + const relationships = _.indexBy(strapi.models[attributes.data.type].associations, 'alias'); + // Extract required relationships + const requiredRelationships = _.intersection(_.keys(requiredAttributes), _.keys(relationships)); + // Identify missing relationships + const missingRelationships = _.difference(_.keys(requiredRelationships), _.keys(attributes.data.relationships)); + + if (!_.isEmpty(missingRelationships)) { + return yield cb({ + status: 403, + body: 'Missing required relationships (' + missingRelationships.toString() + ')' + }); + } + + // Looks good + yield cb(); + } }; diff --git a/lib/configuration/hooks/jsonapi/index.js b/lib/configuration/hooks/jsonapi/index.js index 2f04ff124e..41fcfa7033 100644 --- a/lib/configuration/hooks/jsonapi/index.js +++ b/lib/configuration/hooks/jsonapi/index.js @@ -39,26 +39,29 @@ module.exports = function (strapi) { // Wait for downstream middleware/handlers to execute to build the response yield next; - // Verify Content-Type header - if (this.request.type !== 'application/vnd.api+json') { - this.status = 406; - this.body = ''; - } else if (this.request.method === 'GET') { - // Intercept only GET request + // Exclude administration routes + if (!strapi.api.admin.config.routes.hasOwnProperty(this.request.method + ' ' + this.request.url)) { + // Verify Content-Type header + if (this.request.type !== 'application/vnd.api+json') { + this.status = 406; + this.body = ''; + } else if (this.request.method === 'GET') { + // Intercept only GET request - // Detect route - const matchedRoute = _.find(strapi.router.stack, function (stack) { - if (new RegExp(stack.regexp).test(self.request.url) && _.includes(stack.methods, self.request.method.toUpperCase())) { - return stack; - } - }); + // Detect route + const matchedRoute = _.find(strapi.router.stack, function (stack) { + if (new RegExp(stack.regexp).test(self.request.url) && _.includes(stack.methods, self.request.method.toUpperCase())) { + return stack; + } + }); - // Handlers set the response body - if (!_.isUndefined(matchedRoute)) { - const actionRoute = strapi.config.routes[self.request.method.toUpperCase() + ' ' + matchedRoute.path]; + // Handlers set the response body + if (!_.isUndefined(matchedRoute)) { + const actionRoute = strapi.config.routes[self.request.method.toUpperCase() + ' ' + matchedRoute.path]; - if (!_.isUndefined(actionRoute)) { - response.set(this, matchedRoute, actionRoute); + if (!_.isUndefined(actionRoute)) { + response.set(this, matchedRoute, actionRoute); + } } } } @@ -69,17 +72,29 @@ module.exports = function (strapi) { cb(); }, - parse: function * (next) { - // Verify Content-Type header - if (this.request.type !== 'application/vnd.api+json') { - this.response.status = 406; - this.response.body = ''; - } else { - request.parse(this, function * (err) { - if (!err) { + /** + * Parse request and attributes + */ + + parse: function (strapi) { + return function * (next) { + const self = this; + + // Verify Content-Type header and exclude administration routes + if (strapi.api.admin.config.routes.hasOwnProperty(this.request.method + ' ' + this.request.url)) { + yield next; + } else if (this.request.type !== 'application/vnd.api+json') { + this.response.status = 406; + this.response.body = ''; + } else { + yield request.parse(this, function * (err) { + if (err) { + return _.assign(self.response, err); + } + yield next; - } - }); + }); + } } } }; diff --git a/lib/configuration/hooks/router/index.js b/lib/configuration/hooks/router/index.js index 5bda18178e..1ca8e9ed8c 100644 --- a/lib/configuration/hooks/router/index.js +++ b/lib/configuration/hooks/router/index.js @@ -87,7 +87,7 @@ module.exports = function (strapi) { // Add the `globalPolicy`. policies.push(globalPolicy(endpoint, value, route)); - policies.push(JSONAPI.parse); + policies.push(JSONAPI.parse(strapi)); if (_.isArray(value.policies) && !_.isEmpty(value.policies)) { _.forEach(value.policies, function (policy) {