diff --git a/examples/getstarted/api/menu/models/Menu.settings.json b/examples/getstarted/api/menu/models/Menu.settings.json index b4300ad8a9..0b6af898f0 100755 --- a/examples/getstarted/api/menu/models/Menu.settings.json +++ b/examples/getstarted/api/menu/models/Menu.settings.json @@ -17,6 +17,10 @@ "restaurant": { "model": "restaurant", "via": "menu" + }, + "menusections": { + "collection": "menusection", + "via": "menu" } } } \ No newline at end of file diff --git a/examples/getstarted/api/menusection/models/Menusection.settings.json b/examples/getstarted/api/menusection/models/Menusection.settings.json index 07645c83b9..11bbb14b92 100755 --- a/examples/getstarted/api/menusection/models/Menusection.settings.json +++ b/examples/getstarted/api/menusection/models/Menusection.settings.json @@ -25,7 +25,8 @@ "repeatable": true }, "menu": { - "model": "menu" + "model": "menu", + "via": "menusections" } } } \ No newline at end of file diff --git a/examples/getstarted/package.json b/examples/getstarted/package.json index 0ad449ac26..2af0748367 100644 --- a/examples/getstarted/package.json +++ b/examples/getstarted/package.json @@ -1,7 +1,7 @@ { "name": "getstarted", "private": true, - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "A Strapi application.", "scripts": { "develop": "strapi develop", @@ -15,23 +15,23 @@ "mysql": "^2.17.1", "pg": "^7.10.0", "sqlite3": "^4.0.6", - "strapi": "3.0.0-beta.16.4", - "strapi-admin": "3.0.0-beta.16.4", - "strapi-hook-bookshelf": "3.0.0-beta.16.4", - "strapi-hook-knex": "3.0.0-beta.16.4", - "strapi-hook-mongoose": "3.0.0-beta.16.4", - "strapi-middleware-views": "3.0.0-beta.16.4", - "strapi-plugin-content-manager": "3.0.0-beta.16.4", - "strapi-plugin-content-type-builder": "3.0.0-beta.16.4", - "strapi-plugin-documentation": "3.0.0-beta.16.4", - "strapi-plugin-email": "3.0.0-beta.16.4", - "strapi-plugin-graphql": "3.0.0-beta.16.4", - "strapi-plugin-settings-manager": "3.0.0-beta.16.4", - "strapi-plugin-upload": "3.0.0-beta.16.4", - "strapi-plugin-users-permissions": "3.0.0-beta.16.4", - "strapi-provider-email-mailgun": "3.0.0-beta.16.4", - "strapi-provider-upload-aws-s3": "3.0.0-beta.16.4", - "strapi-utils": "3.0.0-beta.16.4" + "strapi": "3.0.0-beta.16.5", + "strapi-admin": "3.0.0-beta.16.5", + "strapi-hook-bookshelf": "3.0.0-beta.16.5", + "strapi-hook-knex": "3.0.0-beta.16.5", + "strapi-hook-mongoose": "3.0.0-beta.16.5", + "strapi-middleware-views": "3.0.0-beta.16.5", + "strapi-plugin-content-manager": "3.0.0-beta.16.5", + "strapi-plugin-content-type-builder": "3.0.0-beta.16.5", + "strapi-plugin-documentation": "3.0.0-beta.16.5", + "strapi-plugin-email": "3.0.0-beta.16.5", + "strapi-plugin-graphql": "3.0.0-beta.16.5", + "strapi-plugin-settings-manager": "3.0.0-beta.16.5", + "strapi-plugin-upload": "3.0.0-beta.16.5", + "strapi-plugin-users-permissions": "3.0.0-beta.16.5", + "strapi-provider-email-mailgun": "3.0.0-beta.16.5", + "strapi-provider-upload-aws-s3": "3.0.0-beta.16.5", + "strapi-utils": "3.0.0-beta.16.5" }, "strapi": { "uuid": "getstarted" diff --git a/lerna.json b/lerna.json index 40e30c5ac6..e0961cc449 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "packages": [ "packages/*", "examples/*" diff --git a/packages/create-strapi-app/package.json b/packages/create-strapi-app/package.json index b808b26192..64993d93eb 100644 --- a/packages/create-strapi-app/package.json +++ b/packages/create-strapi-app/package.json @@ -1,6 +1,6 @@ { "name": "create-strapi-app", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Generate a new Strapi application.", "license": "MIT", "homepage": "http://strapi.io", @@ -21,7 +21,7 @@ ], "dependencies": { "commander": "^2.20.0", - "strapi-generate-new": "3.0.0-beta.16.4" + "strapi-generate-new": "3.0.0-beta.16.5" }, "scripts": { "test": "echo \"no tests yet\"" diff --git a/packages/strapi-admin/package.json b/packages/strapi-admin/package.json index c80d84ab03..9c2e70dc70 100644 --- a/packages/strapi-admin/package.json +++ b/packages/strapi-admin/package.json @@ -1,6 +1,6 @@ { "name": "strapi-admin", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Strapi Admin", "repository": { "type": "git", @@ -72,8 +72,8 @@ "sanitize.css": "^4.1.0", "sass-loader": "^7.1.0", "shelljs": "^0.7.8", - "strapi-helper-plugin": "3.0.0-beta.16.4", - "strapi-utils": "3.0.0-beta.16.4", + "strapi-helper-plugin": "3.0.0-beta.16.5", + "strapi-utils": "3.0.0-beta.16.5", "style-loader": "^0.23.1", "styled-components": "^4.2.0", "terser-webpack-plugin": "^1.2.3", diff --git a/packages/strapi-generate-api/package.json b/packages/strapi-generate-api/package.json index 8f958bf6c4..2172ee0008 100644 --- a/packages/strapi-generate-api/package.json +++ b/packages/strapi-generate-api/package.json @@ -1,6 +1,6 @@ { "name": "strapi-generate-api", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Generate an API for a Strapi application.", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-generate-controller/package.json b/packages/strapi-generate-controller/package.json index cb720ff069..3a19c579eb 100644 --- a/packages/strapi-generate-controller/package.json +++ b/packages/strapi-generate-controller/package.json @@ -1,6 +1,6 @@ { "name": "strapi-generate-controller", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Generate a controller for a Strapi API.", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-generate-model/package.json b/packages/strapi-generate-model/package.json index 50a40f9e22..9001c7f9d5 100644 --- a/packages/strapi-generate-model/package.json +++ b/packages/strapi-generate-model/package.json @@ -1,6 +1,6 @@ { "name": "strapi-generate-model", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Generate a model for a Strapi API.", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-generate-new/package.json b/packages/strapi-generate-new/package.json index f864981ebd..4c82d09afb 100644 --- a/packages/strapi-generate-new/package.json +++ b/packages/strapi-generate-new/package.json @@ -1,6 +1,6 @@ { "name": "strapi-generate-new", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Generate a new Strapi application.", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-generate-plugin/package.json b/packages/strapi-generate-plugin/package.json index fb36e68238..ca3a72ee63 100644 --- a/packages/strapi-generate-plugin/package.json +++ b/packages/strapi-generate-plugin/package.json @@ -1,6 +1,6 @@ { "name": "strapi-generate-plugin", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Generate an plugin for a Strapi application.", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-generate-policy/package.json b/packages/strapi-generate-policy/package.json index 0cbe7397b4..370b38271e 100644 --- a/packages/strapi-generate-policy/package.json +++ b/packages/strapi-generate-policy/package.json @@ -1,6 +1,6 @@ { "name": "strapi-generate-policy", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Generate a policy for a Strapi API.", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-generate-service/package.json b/packages/strapi-generate-service/package.json index 10f1113c0a..a142f8c3b6 100644 --- a/packages/strapi-generate-service/package.json +++ b/packages/strapi-generate-service/package.json @@ -1,6 +1,6 @@ { "name": "strapi-generate-service", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Generate a service for a Strapi API.", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-generate/package.json b/packages/strapi-generate/package.json index eabbb02643..18489c700c 100644 --- a/packages/strapi-generate/package.json +++ b/packages/strapi-generate/package.json @@ -1,6 +1,6 @@ { "name": "strapi-generate", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Master of ceremonies for the Strapi generators.", "homepage": "http://strapi.io", "keywords": [ @@ -20,7 +20,7 @@ "fs-extra": "^8.0.1", "lodash": "^4.17.11", "reportback": "^2.0.2", - "strapi-utils": "3.0.0-beta.16.4" + "strapi-utils": "3.0.0-beta.16.5" }, "author": { "name": "Strapi team", diff --git a/packages/strapi-helper-plugin/package.json b/packages/strapi-helper-plugin/package.json index f4156444ea..bc5b7fe0d6 100644 --- a/packages/strapi-helper-plugin/package.json +++ b/packages/strapi-helper-plugin/package.json @@ -1,6 +1,6 @@ { "name": "strapi-helper-plugin", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Helper for Strapi plugins development", "files": [ "dist" diff --git a/packages/strapi-hook-bookshelf/package.json b/packages/strapi-hook-bookshelf/package.json index 4cccc16b57..8c0171e04a 100644 --- a/packages/strapi-hook-bookshelf/package.json +++ b/packages/strapi-hook-bookshelf/package.json @@ -1,6 +1,6 @@ { "name": "strapi-hook-bookshelf", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Bookshelf hook for the Strapi framework", "homepage": "http://strapi.io", "keywords": [ @@ -22,8 +22,8 @@ "lodash": "^4.17.11", "pluralize": "^7.0.0", "rimraf": "^2.6.3", - "strapi-hook-knex": "3.0.0-beta.16.4", - "strapi-utils": "3.0.0-beta.16.4" + "strapi-hook-knex": "3.0.0-beta.16.5", + "strapi-utils": "3.0.0-beta.16.5" }, "strapi": { "dependencies": [ diff --git a/packages/strapi-hook-ejs/package.json b/packages/strapi-hook-ejs/package.json index f35604aaa2..96b87f4792 100644 --- a/packages/strapi-hook-ejs/package.json +++ b/packages/strapi-hook-ejs/package.json @@ -1,6 +1,6 @@ { "name": "strapi-hook-ejs", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "EJS hook for the Strapi framework", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-hook-knex/package.json b/packages/strapi-hook-knex/package.json index 84f5d48abf..4df44a8c5a 100644 --- a/packages/strapi-hook-knex/package.json +++ b/packages/strapi-hook-knex/package.json @@ -1,6 +1,6 @@ { "name": "strapi-hook-knex", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Knex hook for the Strapi framework", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-hook-mongoose/package.json b/packages/strapi-hook-mongoose/package.json index 7cde46caeb..3ab6de15e5 100644 --- a/packages/strapi-hook-mongoose/package.json +++ b/packages/strapi-hook-mongoose/package.json @@ -1,6 +1,6 @@ { "name": "strapi-hook-mongoose", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Mongoose hook for the Strapi framework", "homepage": "http://strapi.io", "keywords": [ @@ -20,7 +20,7 @@ "mongoose-float": "^1.0.4", "mongoose-long": "^0.2.1", "pluralize": "^7.0.0", - "strapi-utils": "3.0.0-beta.16.4" + "strapi-utils": "3.0.0-beta.16.5" }, "author": { "email": "hi@strapi.io", diff --git a/packages/strapi-hook-redis/package.json b/packages/strapi-hook-redis/package.json index 2880dc30ee..abb46dd07d 100644 --- a/packages/strapi-hook-redis/package.json +++ b/packages/strapi-hook-redis/package.json @@ -1,6 +1,6 @@ { "name": "strapi-hook-redis", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Redis hook for the Strapi framework", "homepage": "http://strapi.io", "keywords": [ @@ -19,7 +19,7 @@ "lodash": "^4.17.11", "rimraf": "^2.6.3", "stack-trace": "0.0.10", - "strapi-utils": "3.0.0-beta.16.4" + "strapi-utils": "3.0.0-beta.16.5" }, "author": { "email": "hi@strapi.io", diff --git a/packages/strapi-middleware-views/package.json b/packages/strapi-middleware-views/package.json index daa7699685..94fdec0c29 100644 --- a/packages/strapi-middleware-views/package.json +++ b/packages/strapi-middleware-views/package.json @@ -1,6 +1,6 @@ { "name": "strapi-middleware-views", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Views middleware to enable server-side rendering for the Strapi framework", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-plugin-content-manager/package.json b/packages/strapi-plugin-content-manager/package.json index 5af0b01a91..46f154a52d 100644 --- a/packages/strapi-plugin-content-manager/package.json +++ b/packages/strapi-plugin-content-manager/package.json @@ -1,6 +1,6 @@ { "name": "strapi-plugin-content-manager", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "A powerful UI to easily manage your data.", "strapi": { "name": "Content Manager", @@ -32,8 +32,8 @@ "redux-immutable": "^4.0.0", "reselect": "^3.0.1", "showdown": "^1.9.0", - "strapi-helper-plugin": "3.0.0-beta.16.4", - "strapi-utils": "3.0.0-beta.16.4", + "strapi-helper-plugin": "3.0.0-beta.16.5", + "strapi-utils": "3.0.0-beta.16.5", "styled-components": "^4.2.0", "yup": "^0.27.0" }, diff --git a/packages/strapi-plugin-content-type-builder/package.json b/packages/strapi-plugin-content-type-builder/package.json index b535c0a891..34c8c54b3b 100644 --- a/packages/strapi-plugin-content-type-builder/package.json +++ b/packages/strapi-plugin-content-type-builder/package.json @@ -1,6 +1,6 @@ { "name": "strapi-plugin-content-type-builder", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Strapi plugin to create content type (API).", "strapi": { "name": "Content Type Builder", @@ -29,9 +29,9 @@ "redux": "^4.0.1", "redux-immutable": "^4.0.0", "reselect": "^3.0.1", - "strapi-generate": "3.0.0-beta.16.4", - "strapi-generate-api": "3.0.0-beta.16.4", - "strapi-helper-plugin": "3.0.0-beta.16.4", + "strapi-generate": "3.0.0-beta.16.5", + "strapi-generate-api": "3.0.0-beta.16.5", + "strapi-helper-plugin": "3.0.0-beta.16.5", "yup": "^0.27.0" }, "author": { diff --git a/packages/strapi-plugin-documentation/package.json b/packages/strapi-plugin-documentation/package.json index 6274edad3b..793cd2fd1a 100755 --- a/packages/strapi-plugin-documentation/package.json +++ b/packages/strapi-plugin-documentation/package.json @@ -1,6 +1,6 @@ { "name": "strapi-plugin-documentation", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "This is the description of the plugin.", "strapi": { "name": "Documentation", @@ -32,7 +32,7 @@ "redux": "^4.0.1", "redux-immutable": "^4.0.0", "reselect": "^4.0.0", - "strapi-helper-plugin": "3.0.0-beta.16.4", + "strapi-helper-plugin": "3.0.0-beta.16.5", "swagger-ui-dist": "3.22.1" }, "author": { diff --git a/packages/strapi-plugin-email/package.json b/packages/strapi-plugin-email/package.json index e9cc74a988..cccbef88ea 100644 --- a/packages/strapi-plugin-email/package.json +++ b/packages/strapi-plugin-email/package.json @@ -1,6 +1,6 @@ { "name": "strapi-plugin-email", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "This is the description of the plugin.", "strapi": { "name": "Email", @@ -12,13 +12,13 @@ "test": "echo \"no tests yet\"" }, "dependencies": { - "strapi-provider-email-sendmail": "3.0.0-beta.16.4", - "strapi-utils": "3.0.0-beta.16.4" + "strapi-provider-email-sendmail": "3.0.0-beta.16.5", + "strapi-utils": "3.0.0-beta.16.5" }, "devDependencies": { "react-copy-to-clipboard": "5.0.1", "rimraf": "^2.6.3", - "strapi-helper-plugin": "3.0.0-beta.16.4" + "strapi-helper-plugin": "3.0.0-beta.16.5" }, "author": { "name": "Strapi team", diff --git a/packages/strapi-plugin-graphql/package.json b/packages/strapi-plugin-graphql/package.json index 993783ff9c..26d923b4ee 100644 --- a/packages/strapi-plugin-graphql/package.json +++ b/packages/strapi-plugin-graphql/package.json @@ -1,6 +1,6 @@ { "name": "strapi-plugin-graphql", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "This is the description of the plugin.", "strapi": { "name": "graphql", @@ -23,7 +23,7 @@ "graphql-type-long": "^0.1.1", "koa-compose": "^4.1.0", "pluralize": "^7.0.0", - "strapi-utils": "3.0.0-beta.16.4" + "strapi-utils": "3.0.0-beta.16.5" }, "devDependencies": { "cross-env": "^5.2.0", diff --git a/packages/strapi-plugin-graphql/services/Mutation.js b/packages/strapi-plugin-graphql/services/Mutation.js index 411e285a05..3b1f590cf0 100644 --- a/packages/strapi-plugin-graphql/services/Mutation.js +++ b/packages/strapi-plugin-graphql/services/Mutation.js @@ -174,7 +174,8 @@ module.exports = { ) ); - return async (obj, options, { context }) => { + return async (obj, options, graphqlCtx) => { + const { context } = graphqlCtx; // Hack to be able to handle permissions for each query. const ctx = Object.assign(_.clone(context), { request: Object.assign(_.clone(context.request), { @@ -234,7 +235,7 @@ module.exports = { : body; } - return resolver.call(null, obj, options, context); + return resolver.call(null, obj, options, graphqlCtx); } // Resolver can be a promise. diff --git a/packages/strapi-plugin-graphql/services/Schema.js b/packages/strapi-plugin-graphql/services/Schema.js index 7ce4304a08..8accdef12c 100644 --- a/packages/strapi-plugin-graphql/services/Schema.js +++ b/packages/strapi-plugin-graphql/services/Schema.js @@ -202,56 +202,63 @@ const schemaBuilder = { // Transform object to only contain function. Object.keys(resolvers).reduce((acc, type) => { - return Object.keys(acc[type]).reduce((acc, resolver) => { + return Object.keys(acc[type]).reduce((acc, resolverName) => { + const resolverObj = acc[type][resolverName]; // Disabled this query. - if (acc[type][resolver] === false) { - delete acc[type][resolver]; + if (resolverObj === false) { + delete acc[type][resolverName]; return acc; } - if (!_.isFunction(acc[type][resolver])) { - acc[type][resolver] = acc[type][resolver].resolver; + if (_.isFunction(resolverObj)) { + return acc; } - if ( - _.isString(acc[type][resolver]) || - _.isPlainObject(acc[type][resolver]) - ) { - const { plugin = '' } = _.isPlainObject(acc[type][resolver]) - ? acc[type][resolver] - : {}; + let plugin; + if (_.has(resolverObj, ['plugin'])) { + plugin = resolverObj.plugin; + } else if (_.has(resolverObj, ['resolver', 'plugin'])) { + plugin = resolverObj.resolver.plugin; + } - switch (type) { - case 'Mutation': { - let name, action; - if (_.isString(acc[type][resolver])) { - [name, action] = acc[type][resolver].split('.'); - } else if ( - _.isPlainObject(acc[type][resolver]) && - _.isString(acc[type][resolver].handler) - ) { - [name, action] = acc[type][resolver].handler.split('.'); - } - - acc[type][resolver] = Mutation.composeMutationResolver({ - _schema: strapi.plugins.graphql.config._schema.graphql, - plugin, - name: _.toLower(name), - action, - }); - break; + switch (type) { + case 'Mutation': { + let name, action; + if ( + _.has(resolverObj, ['resolver']) && + _.isString(resolverObj.resolver) + ) { + [name, action] = resolverObj.resolver.split('.'); + } else if ( + _.has(resolverObj, ['resolver', 'handler']) && + _.isString(resolverObj.handler) + ) { + [name, action] = resolverObj.resolver.handler.split('.'); + } else { + name = null; + action = resolverName; } - case 'Query': - default: - acc[type][resolver] = Query.composeQueryResolver({ - _schema: strapi.plugins.graphql.config._schema.graphql, - plugin, - name: resolver, - isSingular: 'force', // Avoid singular/pluralize and force query name. - }); - break; + + const mutationResolver = Mutation.composeMutationResolver({ + _schema: strapi.plugins.graphql.config._schema.graphql, + plugin, + name: _.toLower(name), + action, + }); + + acc[type][resolverName] = mutationResolver; + break; } + case 'Query': + default: + acc[type][resolverName] = Query.composeQueryResolver({ + _schema: strapi.plugins.graphql.config._schema.graphql, + plugin, + name: resolverName, + isSingular: 'force', // Avoid singular/pluralize and force query name. + }); + break; } return acc; diff --git a/packages/strapi-plugin-settings-manager/package.json b/packages/strapi-plugin-settings-manager/package.json index 487a2b787e..fc66a78450 100644 --- a/packages/strapi-plugin-settings-manager/package.json +++ b/packages/strapi-plugin-settings-manager/package.json @@ -1,6 +1,6 @@ { "name": "strapi-plugin-settings-manager", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Strapi plugin to manage settings.", "strapi": { "name": "Settings Manager", @@ -27,7 +27,7 @@ "redux": "^4.0.1", "reselect": "^3.0.1", "shelljs": "^0.7.8", - "strapi-helper-plugin": "3.0.0-beta.16.4" + "strapi-helper-plugin": "3.0.0-beta.16.5" }, "author": { "name": "Strapi team", diff --git a/packages/strapi-plugin-upload/package.json b/packages/strapi-plugin-upload/package.json index e84501e8d3..f4300cbc14 100644 --- a/packages/strapi-plugin-upload/package.json +++ b/packages/strapi-plugin-upload/package.json @@ -1,6 +1,6 @@ { "name": "strapi-plugin-upload", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "This is the description of the plugin.", "strapi": { "name": "Files Upload", @@ -23,9 +23,9 @@ "react-router-dom": "^5.0.0", "react-transition-group": "^2.5.0", "reactstrap": "^5.0.0", - "strapi-helper-plugin": "3.0.0-beta.16.4", - "strapi-provider-upload-local": "3.0.0-beta.16.4", - "strapi-utils": "3.0.0-beta.16.4", + "strapi-helper-plugin": "3.0.0-beta.16.5", + "strapi-provider-upload-local": "3.0.0-beta.16.5", + "strapi-utils": "3.0.0-beta.16.5", "stream-to-array": "^2.3.0", "uuid": "^3.2.1" }, diff --git a/packages/strapi-plugin-upload/test/graphqlUpload.test.e2e.js b/packages/strapi-plugin-upload/test/graphqlUpload.test.e2e.js new file mode 100644 index 0000000000..0c3fbe3d14 --- /dev/null +++ b/packages/strapi-plugin-upload/test/graphqlUpload.test.e2e.js @@ -0,0 +1,131 @@ +'use strict'; + +const fs = require('fs'); + +const { registerAndLogin } = require('../../../test/helpers/auth'); +const { createAuthRequest } = require('../../../test/helpers/request'); + +let rq; + +const defaultProviderConfig = { + provider: 'local', + name: 'Local server', + enabled: true, + sizeLimit: 1000000, +}; + +const resetProviderConfigToDefault = () => { + return setConfigOptions(defaultProviderConfig); +}; + +const setConfigOptions = assign => { + return rq.put('/upload/settings/development', { + body: { + ...defaultProviderConfig, + ...assign, + }, + }); +}; + +describe('Upload plugin end to end tests', () => { + beforeAll(async () => { + const token = await registerAndLogin(); + rq = createAuthRequest(token); + }, 60000); + + afterEach(async () => { + await resetProviderConfigToDefault(); + }); + + test('Upload a single file', async () => { + const req = rq.post('/graphql'); + const form = req.form(); + form.append( + 'operations', + JSON.stringify({ + query: /* GraphQL */ ` + mutation uploadFiles($file: Upload!) { + upload(file: $file) { + id + name + mime + url + } + } + `, + variables: { + file: null, + }, + }) + ); + + form.append( + 'map', + JSON.stringify({ + 0: ['variables.file'], + }) + ); + + form.append('0', fs.createReadStream(__dirname + '/rec.jpg')); + + const res = await req; + + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject({ + data: { + upload: { + id: expect.anything(), + name: 'rec.jpg', + }, + }, + }); + }); + + test('Upload multiple files', async () => { + const req = rq.post('/graphql'); + const form = req.form(); + form.append( + 'operations', + JSON.stringify({ + query: /* GraphQL */ ` + mutation uploadFiles($files: [Upload]!) { + multipleUpload(files: $files) { + id + name + mime + url + } + } + `, + variables: { + files: [null, null], + }, + }) + ); + + form.append( + 'map', + JSON.stringify({ + 0: ['variables.files.0'], + 1: ['variables.files.1'], + }) + ); + + form.append('0', fs.createReadStream(__dirname + '/rec.jpg')); + form.append('1', fs.createReadStream(__dirname + '/rec.jpg')); + + const res = await req; + + expect(res.statusCode).toBe(200); + expect(res.body).toEqual({ + data: { + multipleUpload: expect.arrayContaining([ + expect.objectContaining({ + id: expect.anything(), + name: 'rec.jpg', + }), + ]), + }, + }); + }); +}); diff --git a/packages/strapi-plugin-upload/test/upload.test.e2e.js b/packages/strapi-plugin-upload/test/upload.test.e2e.js index 579c180996..e38e327cfb 100644 --- a/packages/strapi-plugin-upload/test/upload.test.e2e.js +++ b/packages/strapi-plugin-upload/test/upload.test.e2e.js @@ -4,19 +4,8 @@ const fs = require('fs'); // Helpers. const { registerAndLogin } = require('../../../test/helpers/auth'); -// const createModelsUtils = require('../../../test/helpers/models'); -// const form = require('../../../test/helpers/generators'); const { createAuthRequest } = require('../../../test/helpers/request'); -// const cleanDate = entry => { -// delete entry.updatedAt; -// delete entry.createdAt; -// delete entry.created_at; -// delete entry.updated_at; -// }; - -// let data; -// let modelsUtils; let rq; const defaultProviderConfig = { @@ -43,28 +32,6 @@ describe('Upload plugin end to end tests', () => { beforeAll(async () => { const token = await registerAndLogin(); rq = createAuthRequest(token); - - // modelsUtils = createModelsUtils({ rq }); - - // await modelsUtils.createModels([ - // form.article, - // form.tag, - // form.category, - // form.reference, - // form.product, - // form.articlewithtag, - // ]); - }, 60000); - - afterAll(() => { - // modelsUtils.deleteModels([ - // 'article', - // 'tag', - // 'category', - // 'reference', - // 'product', - // 'articlewithtag', - // ]), }, 60000); afterEach(async () => { diff --git a/packages/strapi-plugin-users-permissions/config/schema.graphql b/packages/strapi-plugin-users-permissions/config/schema.graphql index e1593e1f9e..b41b6df2d1 100644 --- a/packages/strapi-plugin-users-permissions/config/schema.graphql +++ b/packages/strapi-plugin-users-permissions/config/schema.graphql @@ -2,7 +2,7 @@ const _ = require('lodash'); module.exports = { type: { - UsersPermissionsPermission: false // Make this type NOT queriable. + UsersPermissionsPermission: false, // Make this type NOT queriable. }, definition: ` type UsersPermissionsMe { @@ -30,105 +30,136 @@ module.exports = { resolverOf: 'User.me', resolver: { plugin: 'users-permissions', - handler: 'User.me' - } + handler: 'User.me', + }, }, role: { + plugin: 'users-permissions', resolverOf: 'UsersPermissions.getRole', - resolver: async (obj, options, { context }) => { - await strapi.plugins['users-permissions'].controllers.userspermissions.getRole(context); + resolver: async (obj, options, { context }) => { + await strapi.plugins[ + 'users-permissions' + ].controllers.userspermissions.getRole(context); return context.body.role; - } + }, }, roles: { description: `Retrieve all the existing roles. You can't apply filters on this query.`, + plugin: 'users-permissions', resolverOf: 'UsersPermissions.getRoles', // Apply the `getRoles` permissions on the resolver. - resolver: async (obj, options, { context }) => { - await strapi.plugins['users-permissions'].controllers.userspermissions.getRoles(context); + resolver: async (obj, options, { context }) => { + await strapi.plugins[ + 'users-permissions' + ].controllers.userspermissions.getRoles(context); return context.body.roles; - } - } + }, + }, }, Mutation: { createRole: { description: 'Create a new role', + plugin: 'users-permissions', resolverOf: 'UsersPermissions.createRole', - resolver: async (obj, options, { context }) => { - await strapi.plugins['users-permissions'].controllers.userspermissions.createRole(context); + resolver: async (obj, options, { context }) => { + await strapi.plugins[ + 'users-permissions' + ].controllers.userspermissions.createRole(context); return { ok: true }; - } + }, }, updateRole: { description: 'Update an existing role', + plugin: 'users-permissions', resolverOf: 'UsersPermissions.updateRole', - resolver: async (obj, options, { context }) => { - await strapi.plugins['users-permissions'].controllers.userspermissions.updateRole(context.params, context.body); + resolver: async (obj, options, { context }) => { + await strapi.plugins[ + 'users-permissions' + ].controllers.userspermissions.updateRole( + context.params, + context.body + ); return { ok: true }; - } + }, }, deleteRole: { description: 'Delete an existing role', + plugin: 'users-permissions', resolverOf: 'UsersPermissions.deleteRole', - resolver: async (obj, options, { context }) => { - await strapi.plugins['users-permissions'].controllers.userspermissions.deleteRole(context); + resolver: async (obj, options, { context }) => { + await strapi.plugins[ + 'users-permissions' + ].controllers.userspermissions.deleteRole(context); return { ok: true }; - } + }, }, createUser: { description: 'Create a new user', + plugin: 'users-permissions', resolverOf: 'User.create', resolver: async (obj, options, { context }) => { - context.params = _.toPlainObject(options.input.where); + context.params = _.toPlainObject(options.input.where); context.request.body = _.toPlainObject(options.input.data); - await strapi.plugins['users-permissions'].controllers.user.create(context); + await strapi.plugins['users-permissions'].controllers.user.create( + context + ); return { - user: context.body.toJSON ? context.body.toJSON() : context.body + user: context.body.toJSON ? context.body.toJSON() : context.body, }; - } + }, }, updateUser: { description: 'Update an existing user', + plugin: 'users-permissions', resolverOf: 'User.update', resolver: async (obj, options, { context }) => { - context.params = _.toPlainObject(options.input.where); + context.params = _.toPlainObject(options.input.where); context.request.body = _.toPlainObject(options.input.data); - await strapi.plugins['users-permissions'].controllers.user.update(context); + await strapi.plugins['users-permissions'].controllers.user.update( + context + ); - return { - user: context.body.toJSON ? context.body.toJSON() : context.body + return { + user: context.body.toJSON ? context.body.toJSON() : context.body, }; - } + }, }, deleteUser: { description: 'Delete an existing user', + plugin: 'users-permissions', resolverOf: 'User.destroy', resolver: async (obj, options, { context }) => { // Set parameters to context. - context.params = _.toPlainObject(options.input.where); + context.params = _.toPlainObject(options.input.where); context.request.body = _.toPlainObject(options.input.data); - // Retrieve user to be able to return it because + // Retrieve user to be able to return it because // Bookshelf doesn't return the row once deleted. - await strapi.plugins['users-permissions'].controllers.user.findOne(context); + await strapi.plugins['users-permissions'].controllers.user.findOne( + context + ); // Assign result to user. - const user = context.body.toJSON ? context.body.toJSON() : context.body; + const user = context.body.toJSON + ? context.body.toJSON() + : context.body; // Run destroy query. - await strapi.plugins['users-permissions'].controllers.user.destroy(context); + await strapi.plugins['users-permissions'].controllers.user.destroy( + context + ); return { - user + user, }; - } - } - } - } + }, + }, + }, + }, }; diff --git a/packages/strapi-plugin-users-permissions/controllers/User.js b/packages/strapi-plugin-users-permissions/controllers/User.js index 2a0451fc93..0307887aed 100644 --- a/packages/strapi-plugin-users-permissions/controllers/User.js +++ b/packages/strapi-plugin-users-permissions/controllers/User.js @@ -170,27 +170,37 @@ module.exports = { const { id } = ctx.params; const { email, username, password } = ctx.request.body; - if (!email) return ctx.badRequest('missing.email'); - if (!username) return ctx.badRequest('missing.username'); - if (!password) return ctx.badRequest('missing.password'); - - const userWithSameUsername = await strapi - .query('user', 'users-permissions') - .findOne({ username }); - - if (userWithSameUsername && userWithSameUsername.id != id) { - return ctx.badRequest( - null, - ctx.request.admin - ? adminError({ - message: 'Auth.form.error.username.taken', - field: ['username'], - }) - : 'username.alreadyTaken.' - ); + if (_.has(ctx.request.body, 'email') && !email) { + return ctx.badRequest('email.notNull'); } - if (advancedConfigs.unique_email) { + if (_.has(ctx.request.body, 'username') && !username) { + return ctx.badRequest('username.notNull'); + } + + if (_.has(ctx.request.body, 'password') && !password) { + return ctx.badRequest('password.notNull'); + } + + if (_.has(ctx.request.body, 'username')) { + const userWithSameUsername = await strapi + .query('user', 'users-permissions') + .findOne({ username }); + + if (userWithSameUsername && userWithSameUsername.id != id) { + return ctx.badRequest( + null, + ctx.request.admin + ? adminError({ + message: 'Auth.form.error.username.taken', + field: ['username'], + }) + : 'username.alreadyTaken.' + ); + } + } + + if (_.has(ctx.request.body, 'email') && advancedConfigs.unique_email) { const userWithSameEmail = await strapi .query('user', 'users-permissions') .findOne({ email }); @@ -216,7 +226,7 @@ module.exports = { ...ctx.request.body, }; - if (password === user.password) { + if (_.has(ctx.request.body, 'password') && password === user.password) { delete updateData.password; } diff --git a/packages/strapi-plugin-users-permissions/package.json b/packages/strapi-plugin-users-permissions/package.json index 167b504f89..b549b190ef 100644 --- a/packages/strapi-plugin-users-permissions/package.json +++ b/packages/strapi-plugin-users-permissions/package.json @@ -1,6 +1,6 @@ { "name": "strapi-plugin-users-permissions", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Protect your API with a full-authentication process based on JWT", "strapi": { "name": "Roles & Permissions", @@ -31,8 +31,8 @@ "reactstrap": "^5.0.0", "redux-saga": "^0.16.0", "request": "^2.83.0", - "strapi-helper-plugin": "3.0.0-beta.16.4", - "strapi-utils": "3.0.0-beta.16.4", + "strapi-helper-plugin": "3.0.0-beta.16.5", + "strapi-utils": "3.0.0-beta.16.5", "uuid": "^3.1.0" }, "devDependencies": { diff --git a/packages/strapi-plugin-users-permissions/test/graphql.test.e2e.js b/packages/strapi-plugin-users-permissions/test/graphql.test.e2e.js new file mode 100644 index 0000000000..b142803fe3 --- /dev/null +++ b/packages/strapi-plugin-users-permissions/test/graphql.test.e2e.js @@ -0,0 +1,241 @@ +// Helpers. +const { registerAndLogin } = require('../../../test/helpers/auth'); + +const { + createAuthRequest, + createRequest, +} = require('../../../test/helpers/request'); + +let authReq; +const data = {}; + +describe('Test Graphql user service', () => { + beforeAll(async () => { + const token = await registerAndLogin(); + authReq = createAuthRequest(token); + }, 60000); + + describe('Check createUser authorizations', () => { + test('createUser is forbidden to public', async () => { + const rq = createRequest(); + const res = await rq({ + url: '/graphql', + method: 'POST', + body: { + query: /* GraphQL */ ` + mutation { + createUser( + input: { + data: { username: "test", email: "test", password: "test" } + } + ) { + user { + id + username + } + } + } + `, + }, + }); + + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject({ + data: { + createUser: null, + }, + errors: [ + { + message: 'Forbidden', + }, + ], + }); + }); + + test('createUser is authorized for admins', async () => { + const res = await authReq({ + url: '/graphql', + method: 'POST', + body: { + query: /* GraphQL */ ` + mutation { + createUser( + input: { + data: { + username: "test" + email: "test@strapi.io" + password: "test" + } + } + ) { + user { + id + username + } + } + } + `, + }, + }); + + expect(res.statusCode).toBe(201); + expect(res.body).toMatchObject({ + data: { + createUser: { + user: { + id: expect.anything(), + username: 'test', + }, + }, + }, + }); + + data.user = res.body.data.createUser.user; + }); + }); + + describe('Check updateUser authorizations', () => { + test('updateUser is forbidden to public', async () => { + const rq = createRequest(); + const res = await rq({ + url: '/graphql', + method: 'POST', + body: { + query: /* GraphQL */ ` + mutation { + updateUser( + input: { + where: { id: 1 } + data: { username: "test", email: "test", password: "test" } + } + ) { + user { + id + username + } + } + } + `, + }, + }); + + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject({ + data: { + updateUser: null, + }, + errors: [ + { + message: 'Forbidden', + }, + ], + }); + }); + + test('updateUser is authorized for admins', async () => { + const res = await authReq({ + url: '/graphql', + method: 'POST', + body: { + query: /* GraphQL */ ` + mutation updateUser($id: ID!) { + updateUser( + input: { where: { id: $id }, data: { username: "newUsername" } } + ) { + user { + id + username + } + } + } + `, + variables: { + id: data.user.id, + }, + }, + }); + + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject({ + data: { + updateUser: { + user: { + id: expect.anything(), + username: 'newUsername', + }, + }, + }, + }); + + data.user = res.body.data.updateUser.user; + }); + }); + + describe('Check deleteUser authorizations', () => { + test('deleteUser is forbidden to public', async () => { + const rq = createRequest(); + const res = await rq({ + url: '/graphql', + method: 'POST', + body: { + query: /* GraphQL */ ` + mutation deleteUser($id: ID!) { + deleteUser(input: { where: { id: $id } }) { + user { + id + username + } + } + } + `, + variables: { + id: data.user.id, + }, + }, + }); + + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject({ + data: { + deleteUser: null, + }, + errors: [ + { + message: 'Forbidden', + }, + ], + }); + }); + + test('deleteUser is authorized for admins', async () => { + const res = await authReq({ + url: '/graphql', + method: 'POST', + body: { + query: /* GraphQL */ ` + mutation deleteUser($id: ID!) { + deleteUser(input: { where: { id: $id } }) { + user { + id + username + } + } + } + `, + variables: { + id: data.user.id, + }, + }, + }); + + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject({ + data: { + deleteUser: { + user: data.user, + }, + }, + }); + }); + }); +}); diff --git a/packages/strapi-provider-email-amazon-ses/package.json b/packages/strapi-provider-email-amazon-ses/package.json index 5841450119..b31e24766f 100644 --- a/packages/strapi-provider-email-amazon-ses/package.json +++ b/packages/strapi-provider-email-amazon-ses/package.json @@ -1,6 +1,6 @@ { "name": "strapi-provider-email-amazon-ses", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Amazon SES provider for strapi email", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-provider-email-mailgun/package.json b/packages/strapi-provider-email-mailgun/package.json index 7d650a1059..52409c889b 100644 --- a/packages/strapi-provider-email-mailgun/package.json +++ b/packages/strapi-provider-email-mailgun/package.json @@ -1,6 +1,6 @@ { "name": "strapi-provider-email-mailgun", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Mailgun provider for strapi email plugin", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-provider-email-sendgrid/package.json b/packages/strapi-provider-email-sendgrid/package.json index 0744e904c6..64da06a121 100644 --- a/packages/strapi-provider-email-sendgrid/package.json +++ b/packages/strapi-provider-email-sendgrid/package.json @@ -1,6 +1,6 @@ { "name": "strapi-provider-email-sendgrid", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Sendgrid provider for strapi email", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-provider-email-sendmail/package.json b/packages/strapi-provider-email-sendmail/package.json index 4f74eb098c..963e85a5db 100644 --- a/packages/strapi-provider-email-sendmail/package.json +++ b/packages/strapi-provider-email-sendmail/package.json @@ -1,6 +1,6 @@ { "name": "strapi-provider-email-sendmail", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Sendmail provider for strapi email", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-provider-upload-aws-s3/package.json b/packages/strapi-provider-upload-aws-s3/package.json index 0354ff6f48..c02d503335 100644 --- a/packages/strapi-provider-upload-aws-s3/package.json +++ b/packages/strapi-provider-upload-aws-s3/package.json @@ -1,6 +1,6 @@ { "name": "strapi-provider-upload-aws-s3", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "AWS S3 provider for strapi upload", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-provider-upload-cloudinary/package.json b/packages/strapi-provider-upload-cloudinary/package.json index ad97eb9db2..d6eadf6e41 100644 --- a/packages/strapi-provider-upload-cloudinary/package.json +++ b/packages/strapi-provider-upload-cloudinary/package.json @@ -1,6 +1,6 @@ { "name": "strapi-provider-upload-cloudinary", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Cloudinary provider for strapi upload", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-provider-upload-local/package.json b/packages/strapi-provider-upload-local/package.json index 60b4a22661..21d8cf6a99 100644 --- a/packages/strapi-provider-upload-local/package.json +++ b/packages/strapi-provider-upload-local/package.json @@ -1,6 +1,6 @@ { "name": "strapi-provider-upload-local", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Local provider for strapi upload", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi-provider-upload-rackspace/package.json b/packages/strapi-provider-upload-rackspace/package.json index c04b21d206..44ada5e631 100644 --- a/packages/strapi-provider-upload-rackspace/package.json +++ b/packages/strapi-provider-upload-rackspace/package.json @@ -1,6 +1,6 @@ { "name": "strapi-provider-upload-rackspace", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Rackspace provider for strapi upload", "main": "./lib", "keywords": [], diff --git a/packages/strapi-utils/package.json b/packages/strapi-utils/package.json index 86f66f0b9e..a2f63a6fcf 100644 --- a/packages/strapi-utils/package.json +++ b/packages/strapi-utils/package.json @@ -1,6 +1,6 @@ { "name": "strapi-utils", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "Shared utilities for the Strapi packages", "homepage": "http://strapi.io", "keywords": [ diff --git a/packages/strapi/package.json b/packages/strapi/package.json index 78ade58a4b..2205c20f0a 100644 --- a/packages/strapi/package.json +++ b/packages/strapi/package.json @@ -1,6 +1,6 @@ { "name": "strapi", - "version": "3.0.0-beta.16.4", + "version": "3.0.0-beta.16.5", "description": "An open source headless CMS solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier. Databases supported: MongoDB, MySQL, MariaDB, PostgreSQL, SQLite", "homepage": "http://strapi.io", "directories": { @@ -47,15 +47,15 @@ "resolve-cwd": "^3.0.0", "rimraf": "^2.6.2", "shelljs": "^0.8.3", - "strapi-generate": "3.0.0-beta.16.4", - "strapi-generate-api": "3.0.0-beta.16.4", - "strapi-generate-controller": "3.0.0-beta.16.4", - "strapi-generate-model": "3.0.0-beta.16.4", - "strapi-generate-new": "3.0.0-beta.16.4", - "strapi-generate-plugin": "3.0.0-beta.16.4", - "strapi-generate-policy": "3.0.0-beta.16.4", - "strapi-generate-service": "3.0.0-beta.16.4", - "strapi-utils": "3.0.0-beta.16.4" + "strapi-generate": "3.0.0-beta.16.5", + "strapi-generate-api": "3.0.0-beta.16.5", + "strapi-generate-controller": "3.0.0-beta.16.5", + "strapi-generate-model": "3.0.0-beta.16.5", + "strapi-generate-new": "3.0.0-beta.16.5", + "strapi-generate-plugin": "3.0.0-beta.16.5", + "strapi-generate-policy": "3.0.0-beta.16.5", + "strapi-generate-service": "3.0.0-beta.16.5", + "strapi-utils": "3.0.0-beta.16.5" }, "scripts": { "test": "jest --verbose",