mirror of
https://github.com/strapi/strapi.git
synced 2025-12-03 18:42:47 +00:00
Merge branch 'master' into patch-1
This commit is contained in:
commit
3549bc03f6
@ -63,10 +63,10 @@ Do the same thing for other environments.
|
||||
|
||||
#### HTTP call
|
||||
|
||||
Now it is time to make the HTTP call. In this example we will use `request` as it is already in the list of Strapi's dependencies. Let's install it:
|
||||
Now it is time to make the HTTP call. In this example we will use `axios`. Let's install it:
|
||||
|
||||
```
|
||||
npm i request --save
|
||||
npm i axios --save
|
||||
```
|
||||
|
||||
Edit `api/yourContentType/models/YourContentType.js`:
|
||||
@ -76,7 +76,7 @@ Edit `api/yourContentType/models/YourContentType.js`:
|
||||
```js
|
||||
'use strict';
|
||||
|
||||
const request = require('request');
|
||||
const axios = require('axios');
|
||||
|
||||
/**
|
||||
* Lifecycle callbacks for the `Post` model.
|
||||
@ -119,5 +119,5 @@ So, to trigger an url on delete, please add `request.post(strapi.config.currentE
|
||||
- `delete` action of `plugins/content-manager/services/ContentManager.js` (triggered by the Content Manager).
|
||||
|
||||
::: note
|
||||
Do not forget to require `request` at the top of these files.
|
||||
Do not forget to require `axios` at the top of these files.
|
||||
:::
|
||||
|
||||
@ -25,3 +25,4 @@
|
||||
- [Migration guide from alpha.16 to alpha.17](migration-guide-alpha.16-to-alpha.17.md)
|
||||
- [Migration guide from alpha.17 to alpha.18](migration-guide-alpha.17-to-alpha.18.md)
|
||||
- [Migration guide from alpha.18 to alpha.19](migration-guide-alpha.18-to-alpha.19.md)
|
||||
- [Migration guide from alpha.19 to alpha.20](migration-guide-alpha.19-to-alpha.20.md)
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
# Migration guide from alpha.19 to alpha.20
|
||||
|
||||
**Here are the major changes:**
|
||||
|
||||
- Fix email issue on user update
|
||||
- Improve GraphQL performances
|
||||
|
||||
**Useful links:**
|
||||
- Changelog: [https://github.com/strapi/strapi/releases/tag/v3.0.0-alpha.20](https://github.com/strapi/strapi/releases/tag/v3.0.0-alpha.20)
|
||||
- GitHub diff: [https://github.com/strapi/strapi/compare/v3.0.0-alpha.19...v3.0.0-alpha.20](https://github.com/strapi/strapi/compare/v3.0.0-alpha.19...v3.0.0-alpha.20)
|
||||
|
||||
<br>
|
||||
|
||||
::: note
|
||||
Feel free to [join us on Slack](http://slack.strapi.io) and ask questions about the migration process.
|
||||
:::
|
||||
|
||||
<br>
|
||||
|
||||
## Getting started
|
||||
|
||||
Install Strapi `alpha.20` globally on your computer. To do so run `npm install strapi@3.0.0-alpha.20 -g`.
|
||||
|
||||
When it's done, generate a new empty project `strapi new myNewProject` (don't pay attention to the database configuration).
|
||||
|
||||
<br>
|
||||
|
||||
## Update node modules
|
||||
|
||||
Update the Strapi's dependencies version (move Strapi's dependencies to `3.0.0-alpha.20` version) of your project.
|
||||
|
||||
Run `npm install strapi@3.0.0-alpha.20 --save` to update your strapi version.
|
||||
|
||||
<br>
|
||||
|
||||
## Update the Admin
|
||||
|
||||
::: note
|
||||
If you performed updates in the Admin, you will have to manually migrate your changes.
|
||||
:::
|
||||
|
||||
Delete your old admin folder and replace it with the new one.
|
||||
|
||||
<br>
|
||||
|
||||
## Update the Plugins
|
||||
|
||||
::: note
|
||||
If you did a custom update on one of the plugins, you will have to manually migrate your update.
|
||||
:::
|
||||
|
||||
Copy the fields and relations you had in your `/plugins/users-permissions/models/User.settings.json` and `/plugins/users-permissions/config/jwt.json` file in the new one.
|
||||
|
||||
Then, delete your old `plugins` folder and replace it with the new one.
|
||||
|
||||
## Update services
|
||||
|
||||
For both bookshelf and mongoose, you will have to update all services of your generated API.
|
||||
|
||||
You will have to update one line of the `fetchAll` function.
|
||||
|
||||
**Mongoose** replace `.populate(populate);` by `.populate(filters.populate || populate);`.
|
||||
**Bookshelf**: replace `withRelated: populate` by `withRelated: filters.populate || populate`.
|
||||
|
||||
<br>
|
||||
|
||||
That's all, you have now upgraded to Strapi `alpha.20`.
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"assert": "~1.3.0",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-admin",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Strapi Admin",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -31,8 +31,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"sanitize.css": "^4.1.0",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.19",
|
||||
"strapi-utils": "3.0.0-alpha.19"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.20",
|
||||
"strapi-utils": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-admin",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Generate the default admin panel for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -15,8 +15,8 @@
|
||||
"dependencies": {
|
||||
"fs-extra": "^4.0.1",
|
||||
"lodash": "^4.17.5",
|
||||
"strapi-admin": "3.0.0-alpha.19",
|
||||
"strapi-utils": "3.0.0-alpha.19"
|
||||
"strapi-admin": "3.0.0-alpha.20",
|
||||
"strapi-utils": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-api",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Generate an API for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* global <%= globalID %> */
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
@ -46,7 +47,7 @@ module.exports = {
|
||||
qb.offset(filters.start);
|
||||
qb.limit(filters.limit);
|
||||
}).fetchAll({
|
||||
withRelated: populate
|
||||
withRelated: filters.populate || populate
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ module.exports = {
|
||||
.sort(filters.sort)
|
||||
.skip(filters.start)
|
||||
.limit(filters.limit)
|
||||
.populate(populate);
|
||||
.populate(filters.populate || populate);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-controller",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Generate a controller for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-model",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Generate a model for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
const { packageManager } = require('strapi-utils');
|
||||
|
||||
/**
|
||||
@ -72,7 +72,7 @@ module.exports = scope => {
|
||||
}],
|
||||
'strapi': {
|
||||
'packageManager': pkgManager,
|
||||
'uuid': uuid()
|
||||
'uuid': scope.uuid
|
||||
},
|
||||
'engines': {
|
||||
"node": ">= 10.0.0",
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
const { exec, execSync } = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
@ -15,6 +15,7 @@ const fs = require('fs-extra');
|
||||
const npm = require('enpeem');
|
||||
const ora = require('ora');
|
||||
const shell = require('shelljs');
|
||||
const request = require('request');
|
||||
|
||||
// Logger.
|
||||
const { packageManager } = require('strapi-utils');
|
||||
@ -32,6 +33,8 @@ module.exports = (scope, cb) => {
|
||||
console.log(`The app has been connected to the database ${green('successfully')}!`);
|
||||
console.log();
|
||||
|
||||
trackSuccess('didConnectDatabase', scope);
|
||||
|
||||
console.log('🏗 Application generation:');
|
||||
|
||||
let loader = ora('Copy dashboard').start();
|
||||
@ -193,7 +196,19 @@ module.exports = (scope, cb) => {
|
||||
console.log('⚡️ Start application:');
|
||||
console.log(`$ ${green('strapi start')}`);
|
||||
|
||||
trackSuccess('didCreateProject', scope);
|
||||
|
||||
cb();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function trackSuccess(event, scope) {
|
||||
request
|
||||
.post('https://analytics.strapi.io/track')
|
||||
.form({
|
||||
event,
|
||||
uuid: scope.uuid
|
||||
})
|
||||
.on('error', () => {});
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ const {cyan} = require('chalk');
|
||||
const fs = require('fs-extra');
|
||||
const inquirer = require('inquirer');
|
||||
const shell = require('shelljs');
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
// Logger.
|
||||
const { packageManager } = require('strapi-utils');
|
||||
@ -46,6 +47,7 @@ module.exports = (scope, cb) => {
|
||||
// Make changes to the rootPath where the Strapi project will be created.
|
||||
scope.rootPath = path.resolve(process.cwd(), scope.name || '');
|
||||
scope.tmpPath = path.resolve(os.tmpdir(), `strapi${ crypto.randomBytes(6).toString('hex') }`);
|
||||
scope.uuid = uuid();
|
||||
|
||||
// Ensure we aren't going to inadvertently delete any files.
|
||||
try {
|
||||
|
||||
@ -66,7 +66,10 @@ module.exports = {
|
||||
'public/uploads': {
|
||||
folder: {}
|
||||
},
|
||||
|
||||
// Copy gitkeep into uploads directory.
|
||||
'public/uploads/.gitkeep': {
|
||||
copy: 'gitkeep'
|
||||
},
|
||||
// Empty node_modules directory.
|
||||
'node_modules': {
|
||||
folder: {}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-new",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Generate a new Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -19,7 +19,8 @@
|
||||
"listr": "^0.14.1",
|
||||
"lodash": "^4.17.5",
|
||||
"ora": "^2.1.0",
|
||||
"strapi-utils": "3.0.0-alpha.19",
|
||||
"request": "^2.88.0",
|
||||
"strapi-utils": "3.0.0-alpha.20",
|
||||
"uuid": "^3.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@ -80,7 +80,8 @@ $RECYCLE.BIN/
|
||||
ssl
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
public/uploads/*
|
||||
!public/uploads/.gitkeep
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
|
||||
0
packages/strapi-generate-new/templates/gitkeep
Normal file
0
packages/strapi-generate-new/templates/gitkeep
Normal file
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-plugin",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Generate an plugin for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-policy",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Generate a policy for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-service",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Generate a service for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Master of ceremonies for the Strapi generators.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -17,7 +17,7 @@
|
||||
"fs-extra": "^4.0.0",
|
||||
"lodash": "^4.17.5",
|
||||
"reportback": "^2.0.1",
|
||||
"strapi-utils": "3.0.0-alpha.19"
|
||||
"strapi-utils": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-helper-plugin",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Helper for Strapi plugins development",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0",
|
||||
|
||||
@ -1071,6 +1071,10 @@ module.exports = function(strapi) {
|
||||
result.key = 'limit';
|
||||
result.value = parseFloat(value);
|
||||
break;
|
||||
case '_populate':
|
||||
result.key = 'populate';
|
||||
result.value = value;
|
||||
break;
|
||||
case '_contains':
|
||||
case '_containss':
|
||||
result.key = `where.${key}`;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-bookshelf",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Bookshelf hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -21,8 +21,8 @@
|
||||
"lodash": "^4.17.5",
|
||||
"pluralize": "^6.0.0",
|
||||
"rimraf": "^2.6.2",
|
||||
"strapi-hook-knex": "3.0.0-alpha.19",
|
||||
"strapi-utils": "3.0.0-alpha.19"
|
||||
"strapi-hook-knex": "3.0.0-alpha.20",
|
||||
"strapi-utils": "3.0.0-alpha.20"
|
||||
},
|
||||
"strapi": {
|
||||
"dependencies": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-ejs",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "EJS hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-knex",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Knex hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -522,6 +522,10 @@ module.exports = function (strapi) {
|
||||
result.key = 'limit';
|
||||
result.value = parseFloat(value);
|
||||
break;
|
||||
case '_populate':
|
||||
result.key = `populate`;
|
||||
result.value = value;
|
||||
break;
|
||||
case '_contains':
|
||||
result.key = `where.${key}`;
|
||||
result.value = {
|
||||
|
||||
@ -17,7 +17,7 @@ module.exports = (mongoose = new Mongoose()) => {
|
||||
return this.toString();
|
||||
};
|
||||
|
||||
return {
|
||||
const fn = {
|
||||
convertType: mongooseType => {
|
||||
switch (mongooseType.toLowerCase()) {
|
||||
case 'array':
|
||||
@ -52,4 +52,6 @@ module.exports = (mongoose = new Mongoose()) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return fn;
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-mongoose",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Mongoose hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -20,7 +20,7 @@
|
||||
"mongoose-float": "^1.0.3",
|
||||
"pluralize": "^6.0.0",
|
||||
"rimraf": "^2.6.2",
|
||||
"strapi-utils": "3.0.0-alpha.19"
|
||||
"strapi-utils": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-hook-redis",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Redis hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -19,7 +19,7 @@
|
||||
"lodash": "^4.17.5",
|
||||
"rimraf": "^2.6.2",
|
||||
"stack-trace": "0.0.10",
|
||||
"strapi-utils": "3.0.0-alpha.19"
|
||||
"strapi-utils": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-lint",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Strapi eslint and prettier configurations",
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-middleware-views",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Views middleware to enable server-side rendering for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -143,8 +143,8 @@ module.exports = {
|
||||
delete: async function (params) {
|
||||
// Delete entry.
|
||||
return this
|
||||
.remove({
|
||||
[this.primaryKey]: params.id
|
||||
.findOneAndDelete({
|
||||
[this.primaryKey]: params.id,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-content-manager",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "A powerful UI to easily manage your data.",
|
||||
"strapi": {
|
||||
"name": "Content Manager",
|
||||
@ -26,7 +26,7 @@
|
||||
"draft-js": "^0.10.5",
|
||||
"react-select": "^1.2.1",
|
||||
"showdown": "^1.8.6",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.19"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.20"
|
||||
},
|
||||
"dependencies": {
|
||||
"pluralize": "^7.0.0"
|
||||
|
||||
@ -161,6 +161,10 @@ module.exports = {
|
||||
id: params.id
|
||||
});
|
||||
|
||||
if (!response) {
|
||||
throw `This resource doesn't exist.`;
|
||||
}
|
||||
|
||||
params[primaryKey] = response[primaryKey];
|
||||
params.values = Object.keys(JSON.parse(JSON.stringify(response))).reduce((acc, current) => {
|
||||
const association = (strapi.models[params.model] || strapi.plugins[source].models[params.model]).associations.filter(x => x.alias === current)[0];
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-content-type-builder",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Strapi plugin to create content type (API).",
|
||||
"strapi": {
|
||||
"name": "Content Type Builder",
|
||||
@ -24,11 +24,11 @@
|
||||
"dependencies": {
|
||||
"immutable": "^3.8.2",
|
||||
"pluralize": "^7.0.0",
|
||||
"strapi-generate": "3.0.0-alpha.19",
|
||||
"strapi-generate-api": "3.0.0-alpha.19"
|
||||
"strapi-generate": "3.0.0-alpha.20",
|
||||
"strapi-generate-api": "3.0.0-alpha.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.19"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
|
||||
@ -194,18 +194,35 @@ export class HomePage extends React.Component {
|
||||
}
|
||||
|
||||
HomePage.defaultProps = {
|
||||
currentDocVersion: '',
|
||||
didCheckErrors: false,
|
||||
docVersions: [],
|
||||
form: [],
|
||||
formErrors: [],
|
||||
isLoading: true,
|
||||
onChange: () => {},
|
||||
onClickDeleteDoc: () => {},
|
||||
onConfirmDeleteDoc: () => {},
|
||||
onSubmit: () => {},
|
||||
onUpdateDoc: () => {},
|
||||
versionToDelete: '',
|
||||
|
||||
};
|
||||
|
||||
HomePage.propTypes = {
|
||||
currentDocVersion: PropTypes.string,
|
||||
didCheckErrors: PropTypes.bool,
|
||||
docVersions: PropTypes.array,
|
||||
form: PropTypes.array,
|
||||
formErrors: PropTypes.array,
|
||||
getDocInfos: PropTypes.func.isRequired,
|
||||
isLoading: PropTypes.bool,
|
||||
onChange: PropTypes.func,
|
||||
onClickDeleteDoc: PropTypes.func,
|
||||
onConfirmDeleteDoc: PropTypes.func,
|
||||
onSubmit: PropTypes.func,
|
||||
onUpdateDoc: PropTypes.func,
|
||||
versionToDelete: PropTypes.string,
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-documentation",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "Documentation",
|
||||
@ -29,7 +29,7 @@
|
||||
"swagger-ui-dist": "^3.18.3-republish2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.19"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "soupette",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-email",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "Email",
|
||||
@ -22,11 +22,11 @@
|
||||
"prepublishOnly": "IS_MONOREPO=true npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"strapi-provider-email-sendmail": "3.0.0-alpha.19"
|
||||
"strapi-provider-email-sendmail": "3.0.0-alpha.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-copy-to-clipboard": "5.0.1",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.19"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-graphql",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "graphql",
|
||||
@ -22,15 +22,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"apollo-server-koa": "^2.0.7",
|
||||
"dataloader": "^1.4.0",
|
||||
"glob": "^7.1.3",
|
||||
"graphql": "^14.0.2",
|
||||
"graphql-depth-limit": "^1.1.0",
|
||||
"graphql-playground-middleware-koa": "^1.6.4",
|
||||
"graphql-tools": "^3.1.1",
|
||||
"graphql-type-json": "^0.2.1",
|
||||
"graphql-type-datetime": "^0.2.2",
|
||||
"graphql-type-json": "^0.2.1",
|
||||
"pluralize": "^7.0.0",
|
||||
"strapi-utils": "3.0.0-alpha.19"
|
||||
"strapi-utils": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "A Strapi developer",
|
||||
|
||||
217
packages/strapi-plugin-graphql/services/Loaders.js
Normal file
217
packages/strapi-plugin-graphql/services/Loaders.js
Normal file
@ -0,0 +1,217 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Loaders.js service
|
||||
*
|
||||
* @description: A set of functions similar to controller's actions to avoid code duplication.
|
||||
*/
|
||||
|
||||
const _ = require('lodash');
|
||||
const DataLoader = require('dataloader');
|
||||
|
||||
module.exports = {
|
||||
loaders: {},
|
||||
|
||||
initializeLoader: function() {
|
||||
this.resetLoaders();
|
||||
|
||||
// Create loaders for each relational field (exclude core models).
|
||||
Object.keys(strapi.models)
|
||||
.filter(model => model !== 'core_store')
|
||||
.forEach(model => {
|
||||
(strapi.models[model].associations || []).forEach(association => this.createLoader(association.collection || association.model, association.plugin));
|
||||
});
|
||||
|
||||
// Reproduce the same pattern for each plugin.
|
||||
Object.keys(strapi.plugins).forEach(plugin => {
|
||||
Object.keys(strapi.plugins[plugin].models).forEach(model => {
|
||||
(strapi.plugins[plugin].models[model].associations || []).forEach(association => this.createLoader(association.collection || association.model, association.plugin));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
resetLoaders: function () {
|
||||
this.loaders = {};
|
||||
},
|
||||
|
||||
createLoader: function(model, plugin) {
|
||||
const name = plugin ? `${plugin}__${model}`: model;
|
||||
|
||||
// Exclude polymorphic from loaders.
|
||||
if (name === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.loaders[name]) {
|
||||
return this.loaders[name];
|
||||
}
|
||||
|
||||
this.loaders[name] = new DataLoader(keys => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
// Extract queries from keys and merge similar queries.
|
||||
const { queries, map } = this.extractQueries(model, _.cloneDeep(keys));
|
||||
// Run queries in parallel.
|
||||
const results = await Promise.all(queries.map((query) => this.makeQuery(model, query)));
|
||||
// Use to match initial queries order.
|
||||
const data = this.mapData(model, keys, map, results);
|
||||
|
||||
resolve(data);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}, {
|
||||
cacheKeyFn: (key) => {
|
||||
return _.isObjectLike(key) ? JSON.stringify(_.cloneDeep(key)) : key;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
mapData: function(model, originalMap, map, results) {
|
||||
// Use map to re-dispatch data correctly based on initial keys.
|
||||
return originalMap.map((query, index) => {
|
||||
// Find the index of where we should extract the results.
|
||||
const indexResults = map.findIndex(queryMap => queryMap.indexOf(index) !== -1);
|
||||
const data = results[indexResults];
|
||||
|
||||
// Retrieving referring model.
|
||||
const ref = this.retrieveModel(model, query.options.source);
|
||||
|
||||
if (query.single) {
|
||||
// Return object instead of array for one-to-many relationship.
|
||||
return data.find(entry => entry[ref.primaryKey].toString() === (query.params[ref.primaryKey] || '').toString());
|
||||
}
|
||||
|
||||
// Generate constant for skip parameters.
|
||||
// Note: we shouldn't support both way of doing this kind of things in the future.
|
||||
const skip = query.options.start || query.options.skip;
|
||||
|
||||
// Extracting ids from original request to map with query results.
|
||||
const ids = this.extractIds(query, ref);
|
||||
|
||||
if (!_.isArray(ids)) {
|
||||
return data
|
||||
.filter(entry => entry[ids.alias].toString() === ids.value.toString())
|
||||
.slice(skip, skip + query.options.limit);
|
||||
}
|
||||
|
||||
// Critical: don't touch this part until you truly understand what you're doing.
|
||||
// The data array takes care of the sorting of the entries. It explains why we are looping from this array and not the `ids` array.
|
||||
// Then, we're applying the `limit`, `start` and `skip` argument.
|
||||
return data
|
||||
.filter(entry => entry !== undefined)
|
||||
.filter(entry => ids.map(id => id.toString()).includes(entry[ref.primaryKey].toString()))
|
||||
.slice(skip, skip + query.options.limit);
|
||||
});
|
||||
},
|
||||
|
||||
extractIds: (query, ref) => {
|
||||
if ( _.get(query.options, `query.${ref.primaryKey}`)) {
|
||||
return _.get(query.options, `query.${ref.primaryKey}`);
|
||||
}
|
||||
|
||||
// Single object to retrieve (one-to-many).
|
||||
const alias = _.first(Object.keys(query.options.query));
|
||||
|
||||
return {
|
||||
alias,
|
||||
value: _.get(query.options, `query.${alias}`)
|
||||
};
|
||||
},
|
||||
|
||||
makeQuery: async function(model, query = {}) {
|
||||
if (_.isEmpty(query.ids)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const ref = this.retrieveModel(model, query.options.source);
|
||||
|
||||
// Construct parameters object sent to the Content Manager service.
|
||||
// We are faking the `start`, `skip` and `limit` argument because it doesn't make sense because we are merging different requests in one.
|
||||
// Note: we're trying to avoid useless populate for performances. Please be careful if you're updating this part.
|
||||
const populate = ref.associations
|
||||
.filter(association => !association.dominant && _.isEmpty(association.model))
|
||||
.map(association => association.alias);
|
||||
|
||||
const params = {
|
||||
...query.options,
|
||||
populate,
|
||||
query: query.options.where || {},
|
||||
start: 0,
|
||||
skip: 0,
|
||||
limit: 100,
|
||||
};
|
||||
|
||||
params.query[query.alias] = _.uniq(query.ids.filter(x => !_.isEmpty(x)).map(x => x.toString()));
|
||||
|
||||
if (['id', '_id'].includes(query.alias)) {
|
||||
// However, we're applying a limit based on the number of entries we've to fetch.
|
||||
// We'll apply the real `skip`, `start` and `limit` parameters during the mapping above.
|
||||
params.limit = params.query[query.alias].length;
|
||||
}
|
||||
|
||||
// Run query and remove duplicated ID.
|
||||
const request = await strapi.plugins['content-manager'].services['contentmanager'].fetchAll({ model }, params);
|
||||
|
||||
return request && request.toJSON ? request.toJSON() : request;
|
||||
},
|
||||
|
||||
retrieveModel: function(model, source) {
|
||||
// Retrieve refering model.
|
||||
return source ?
|
||||
strapi.plugins[source].models[model]:
|
||||
strapi.models[model];
|
||||
},
|
||||
|
||||
extractQueries: function(model, keys) {
|
||||
const queries = [];
|
||||
const map = [];
|
||||
|
||||
keys.forEach((current, index) => {
|
||||
// Extract query options.
|
||||
// Note: the `single` means that we've only one entry to fetch.
|
||||
const { single = false, params = {}, association } = current;
|
||||
const { query = {}, ...options } = current.options;
|
||||
|
||||
// Retrieving referring model.
|
||||
const ref = this.retrieveModel(model, options.source);
|
||||
|
||||
// Find similar query.
|
||||
const indexQueries = queries.findIndex(query => _.isEqual(query.options, options));
|
||||
|
||||
// Generate array of IDs to fetch.
|
||||
const ids = [];
|
||||
|
||||
// Only one entry to fetch.
|
||||
if (single) {
|
||||
ids.push(params[ref.primaryKey]);
|
||||
} else if (_.isArray(query[ref.primaryKey])) {
|
||||
ids.push(...query[ref.primaryKey]);
|
||||
} else {
|
||||
ids.push(query[association.via]);
|
||||
}
|
||||
|
||||
if (indexQueries !== -1) {
|
||||
// Push to the same query the new IDs to fetch.
|
||||
queries[indexQueries].ids.push(...ids);
|
||||
map[indexQueries].push(index);
|
||||
} else {
|
||||
// Create new query in the query.
|
||||
queries.push({
|
||||
ids,
|
||||
options,
|
||||
alias: _.first(Object.keys(query)) || ref.primaryKey
|
||||
});
|
||||
|
||||
map[queries.length - 1 > 0 ? queries.length - 1 : 0] = [];
|
||||
map[queries.length - 1].push(index);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
queries,
|
||||
map
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -10,6 +10,8 @@ const _ = require('lodash');
|
||||
const pluralize = require('pluralize');
|
||||
const policyUtils = require('strapi-utils').policy;
|
||||
|
||||
const Loaders = require('./Loaders');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Convert parameters to valid filters parameters.
|
||||
@ -31,7 +33,7 @@ module.exports = {
|
||||
* @return String
|
||||
*/
|
||||
|
||||
amountLimiting: params => {
|
||||
amountLimiting: (params = {}) => {
|
||||
if (params.limit && params.limit < 0) {
|
||||
params.limit = 0;
|
||||
} else if (params.limit && params.limit > strapi.plugins.graphql.config.amountLimit) {
|
||||
@ -165,7 +167,7 @@ module.exports = {
|
||||
return async (ctx, next) => {
|
||||
ctx.params = {
|
||||
...params,
|
||||
[model.primaryKey]: ctx.params.id,
|
||||
[model.primaryKey]: ctx.query[model.primaryKey],
|
||||
};
|
||||
|
||||
// Return the controller.
|
||||
@ -174,15 +176,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
// Plural.
|
||||
return async (ctx, next) => {
|
||||
ctx.params = this.amountLimiting(ctx.params);
|
||||
ctx.query = Object.assign(
|
||||
this.convertToParams(_.omit(ctx.params, 'where')),
|
||||
ctx.params.where,
|
||||
);
|
||||
|
||||
return controller(ctx, next);
|
||||
};
|
||||
return controller;
|
||||
})();
|
||||
|
||||
// The controller hasn't been found.
|
||||
@ -230,7 +224,9 @@ module.exports = {
|
||||
),
|
||||
);
|
||||
|
||||
return async (obj, options, { context }) => {
|
||||
return async (obj, options = {}, { context }) => {
|
||||
const _options = _.cloneDeep(options);
|
||||
|
||||
// Hack to be able to handle permissions for each query.
|
||||
const ctx = Object.assign(_.clone(context), {
|
||||
request: Object.assign(_.clone(context.request), {
|
||||
@ -254,13 +250,33 @@ module.exports = {
|
||||
return policy;
|
||||
}
|
||||
|
||||
// Initiliase loaders for this request.
|
||||
Loaders.initializeLoader();
|
||||
|
||||
// Resolver can be a function. Be also a native resolver or a controller's action.
|
||||
if (_.isFunction(resolver)) {
|
||||
context.query = this.convertToParams(options);
|
||||
context.params = this.amountLimiting(options);
|
||||
// Note: we've to used the Object.defineProperties to reset the prototype. It seems that the cloning the context
|
||||
// cause a lost of the Object prototype.
|
||||
Object.defineProperties(ctx, {
|
||||
query: {
|
||||
value: {
|
||||
...this.convertToParams(_.omit(_options, 'where')),
|
||||
..._options.where,
|
||||
// Avoid population.
|
||||
_populate: model.associations.filter(a => !a.dominant && _.isEmpty(a.model)).map(a => a.alias),
|
||||
},
|
||||
writable: true,
|
||||
configurable: true
|
||||
},
|
||||
params: {
|
||||
value: this.convertToParams(this.amountLimiting(_options)),
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
|
||||
if (isController) {
|
||||
const values = await resolver.call(null, context);
|
||||
const values = await resolver.call(null, ctx);
|
||||
|
||||
if (ctx.body) {
|
||||
return ctx.body;
|
||||
@ -269,7 +285,7 @@ module.exports = {
|
||||
return values && values.toJSON ? values.toJSON() : values;
|
||||
}
|
||||
|
||||
return resolver.call(null, obj, options, context);
|
||||
return resolver.call(null, obj, _options, ctx);
|
||||
}
|
||||
|
||||
// Resolver can be a promise.
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
const _ = require('lodash');
|
||||
const pluralize = require('pluralize');
|
||||
const Aggregator = require('./Aggregator');
|
||||
const Loaders = require('./Loaders');
|
||||
const Query = require('./Query.js');
|
||||
const Mutation = require('./Mutation.js');
|
||||
const Types = require('./Types.js');
|
||||
@ -379,20 +380,21 @@ module.exports = {
|
||||
: strapi.models[params.model];
|
||||
|
||||
if (association.type === 'model') {
|
||||
params.id = _.get(obj, [association.alias, ref.primaryKey], obj[association.alias]);
|
||||
params[ref.primaryKey] = _.get(obj, [association.alias, ref.primaryKey], obj[association.alias]);
|
||||
} else {
|
||||
// Apply optional arguments to make more precise nested request.
|
||||
const convertedParams = strapi.utils.models.convertParams(
|
||||
name,
|
||||
Query.convertToParams(Query.amountLimiting(options)),
|
||||
);
|
||||
|
||||
const where = strapi.utils.models.convertParams(
|
||||
name,
|
||||
options.where || {},
|
||||
);
|
||||
|
||||
// Limit, order, etc.
|
||||
Object.assign(queryOpts, convertedParams);
|
||||
Object.assign(queryOpts, convertedParams, { where: where.where });
|
||||
|
||||
// Skip.
|
||||
queryOpts.skip = convertedParams.start;
|
||||
@ -404,24 +406,23 @@ module.exports = {
|
||||
return related[ref.primaryKey] || related;
|
||||
}
|
||||
);
|
||||
|
||||
Object.assign(queryOpts, {
|
||||
...queryOpts,
|
||||
query: {
|
||||
[ref.primaryKey]: arrayOfIds
|
||||
}
|
||||
});
|
||||
|
||||
// Where.
|
||||
queryOpts.query = strapi.utils.models.convertParams(name, {
|
||||
// Construct the "where" query to only retrieve entries which are
|
||||
// related to this entry.
|
||||
[ref.primaryKey]: arrayOfIds,
|
||||
...where.where,
|
||||
}).where;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Where.
|
||||
queryOpts.query = strapi.utils.models.convertParams(name, {
|
||||
// Construct the "where" query to only retrieve entries which are
|
||||
// related to this entry.
|
||||
[association.via]: obj[ref.primaryKey],
|
||||
...where.where,
|
||||
}).where;
|
||||
Object.assign(queryOpts, {
|
||||
...queryOpts,
|
||||
query: {
|
||||
[association.via]: obj[ref.primaryKey]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,20 +430,20 @@ module.exports = {
|
||||
queryOpts.query.hasOwnProperty('id') &&
|
||||
queryOpts.query.id.hasOwnProperty('value') &&
|
||||
Array.isArray(queryOpts.query.id.value)
|
||||
){
|
||||
) {
|
||||
queryOpts.query.id.symbol = 'IN';
|
||||
}
|
||||
|
||||
const value = await (association.model
|
||||
? resolvers.fetch(params, association.plugin, [])
|
||||
: resolvers.fetchAll(params, { ...queryOpts, populate: [] }));
|
||||
const loaderName = association.plugin ? `${association.plugin}__${params.model}`: params.model;
|
||||
|
||||
return value && value.toJSON ? value.toJSON() : value;
|
||||
return association.model ?
|
||||
Loaders.loaders[loaderName].load({ params, options: queryOpts, single: true }):
|
||||
Loaders.loaders[loaderName].load({ options: queryOpts, association });
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, initialState);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -29,6 +29,7 @@ module.exports = {
|
||||
modelName = '',
|
||||
attributeName = '',
|
||||
rootType = 'query',
|
||||
action = ''
|
||||
}) {
|
||||
// Type
|
||||
if (definition.type) {
|
||||
@ -62,7 +63,7 @@ module.exports = {
|
||||
break;
|
||||
}
|
||||
|
||||
if (definition.required) {
|
||||
if (definition.required && action !== 'update') {
|
||||
type += '!';
|
||||
}
|
||||
|
||||
@ -191,7 +192,6 @@ module.exports = {
|
||||
return `
|
||||
input ${inputName} {
|
||||
${Object.keys(model.attributes)
|
||||
.filter(attribute => model.attributes[attribute].private !== true)
|
||||
.map(attribute => {
|
||||
return `${attribute}: ${this.convertType({
|
||||
definition: model.attributes[attribute],
|
||||
@ -202,6 +202,20 @@ module.exports = {
|
||||
})
|
||||
.join('\n')}
|
||||
}
|
||||
|
||||
input edit${inputName} {
|
||||
${Object.keys(model.attributes)
|
||||
.map(attribute => {
|
||||
return `${attribute}: ${this.convertType({
|
||||
definition: model.attributes[attribute],
|
||||
modelName: globalId,
|
||||
attributeName: attribute,
|
||||
rootType: 'mutation',
|
||||
action: 'update'
|
||||
})}`;
|
||||
})
|
||||
.join('\n')}
|
||||
}
|
||||
`;
|
||||
/* eslint-enable */
|
||||
},
|
||||
@ -224,7 +238,7 @@ module.exports = {
|
||||
`;
|
||||
case 'update':
|
||||
return `
|
||||
input ${type}${inputName} { where: InputID, data: ${inputName} }
|
||||
input ${type}${inputName} { where: InputID, data: edit${inputName} }
|
||||
type ${type}${payloadName} { ${pluralize.singular(name)}: ${
|
||||
model.globalId
|
||||
} }
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-settings-manager",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Strapi plugin to manage settings.",
|
||||
"strapi": {
|
||||
"name": "Settings Manager",
|
||||
@ -25,7 +25,7 @@
|
||||
"devDependencies": {
|
||||
"flag-icon-css": "^2.8.0",
|
||||
"react-select": "^1.0.0-rc.5",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.19"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-upload",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "Files Upload",
|
||||
@ -22,12 +22,12 @@
|
||||
"prepublishOnly": "IS_MONOREPO=true npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"strapi-provider-upload-local": "3.0.0-alpha.19",
|
||||
"strapi-provider-upload-local": "3.0.0-alpha.20",
|
||||
"stream-to-array": "^2.3.0",
|
||||
"uuid": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.19"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "A Strapi developer",
|
||||
|
||||
@ -110,7 +110,7 @@ export class EditPage extends React.Component { // eslint-disable-line react/pre
|
||||
showLoaderForm = () => {
|
||||
const { editPage: { modifiedData }, match: { params: { actionType } } } = this.props;
|
||||
|
||||
return actionType !== 'create' && get(modifiedData, ['name'], '') === '';
|
||||
return actionType !== 'create' && isEmpty(modifiedData);
|
||||
}
|
||||
|
||||
showLoaderPermissions = () => {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = {
|
||||
type: {
|
||||
UsersPermissionsPermission: false // Make this type NOT queriable.
|
||||
@ -63,7 +65,7 @@ module.exports = {
|
||||
description: 'Update an existing role',
|
||||
resolverOf: 'UsersPermissions.updateRole',
|
||||
resolver: async (obj, options, ctx) => {
|
||||
await strapi.plugins['users-permissions'].controllers.userspermissions.updateRole(ctx);
|
||||
await strapi.plugins['users-permissions'].controllers.userspermissions.updateRole(ctx.params, ctx.body);
|
||||
|
||||
return { ok: true };
|
||||
}
|
||||
@ -76,6 +78,56 @@ module.exports = {
|
||||
|
||||
return { ok: true };
|
||||
}
|
||||
},
|
||||
createUser: {
|
||||
description: 'Create a new user',
|
||||
resolverOf: 'User.create',
|
||||
resolver: async (obj, options, { context }) => {
|
||||
context.params = _.toPlainObject(options.input.where);
|
||||
context.request.body = _.toPlainObject(options.input.data);
|
||||
|
||||
await strapi.plugins['users-permissions'].controllers.user.create(context);
|
||||
|
||||
return {
|
||||
user: context.body.toJSON ? context.body.toJSON() : context.body
|
||||
};
|
||||
}
|
||||
},
|
||||
updateUser: {
|
||||
description: 'Update an existing user',
|
||||
resolverOf: 'User.update',
|
||||
resolver: async (obj, options, { context }) => {
|
||||
context.params = _.toPlainObject(options.input.where);
|
||||
context.request.body = _.toPlainObject(options.input.data);
|
||||
|
||||
await strapi.plugins['users-permissions'].controllers.user.update(context);
|
||||
|
||||
return {
|
||||
user: context.body.toJSON ? context.body.toJSON() : context.body
|
||||
};
|
||||
}
|
||||
},
|
||||
deleteUser: {
|
||||
description: 'Delete an existing user',
|
||||
resolverOf: 'User.destroy',
|
||||
resolver: async (obj, options, { context }) => {
|
||||
// Set parameters to context.
|
||||
context.params = _.toPlainObject(options.input.where);
|
||||
context.request.body = _.toPlainObject(options.input.data);
|
||||
|
||||
// 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);
|
||||
// Assign result to user.
|
||||
const user = context.body.toJSON ? context.body.toJSON() : context.body;
|
||||
|
||||
// Run destroy query.
|
||||
await strapi.plugins['users-permissions'].controllers.user.destroy(context);
|
||||
|
||||
return {
|
||||
user
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
/* eslint-disable no-useless-escape */
|
||||
const crypto = require('crypto');
|
||||
const _ = require('lodash');
|
||||
|
||||
const emailRegExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
|
||||
module.exports = {
|
||||
@ -326,6 +327,10 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAdmin) {
|
||||
strapi.emit('didCreateFirstAdmin');
|
||||
}
|
||||
|
||||
ctx.send({
|
||||
jwt,
|
||||
user: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken'])
|
||||
|
||||
@ -95,6 +95,7 @@ module.exports = {
|
||||
|
||||
try {
|
||||
const data = await strapi.plugins['users-permissions'].services.user.add(ctx.request.body);
|
||||
|
||||
// Send 201 `created`
|
||||
ctx.created(data);
|
||||
} catch(error) {
|
||||
@ -120,7 +121,7 @@ module.exports = {
|
||||
if (advancedConfigs.unique_email && ctx.request.body.email) {
|
||||
const users = await strapi.plugins['users-permissions'].services.user.fetchAll({ email: ctx.request.body.email });
|
||||
|
||||
if (users && _.find(users, user => (user.id || user._id).toString() !== ctx.params._id)) {
|
||||
if (users && _.find(users, user => (user.id || user._id).toString() !== (ctx.params.id || ctx.params._id))) {
|
||||
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.email.taken', field: ['email'] }] }] : 'Email is already taken.');
|
||||
}
|
||||
}
|
||||
@ -140,7 +141,7 @@ module.exports = {
|
||||
email: ctx.request.body.email
|
||||
});
|
||||
|
||||
if (user !== null && (user.id || user._id).toString() !== ctx.params._id) {
|
||||
if (user !== null && (user.id || user._id).toString() !== (ctx.params.id || ctx.params._id)) {
|
||||
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.email.taken', field: ['email'] }] }] : 'Email is already taken.');
|
||||
}
|
||||
}
|
||||
@ -162,7 +163,7 @@ module.exports = {
|
||||
|
||||
destroy: async (ctx) => {
|
||||
const data = await strapi.plugins['users-permissions'].services.user.remove(ctx.params);
|
||||
|
||||
|
||||
// Send 200 `ok`
|
||||
ctx.send(data);
|
||||
},
|
||||
|
||||
@ -49,5 +49,6 @@
|
||||
"plugin": "users-permissions",
|
||||
"configurable": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"collectionName": "users-permissions_user"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-users-permissions",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Protect your API with a full-authentication process based on JWT",
|
||||
"strapi": {
|
||||
"name": "Roles & Permissions",
|
||||
@ -29,11 +29,11 @@
|
||||
"koa2-ratelimit": "^0.6.1",
|
||||
"purest": "^2.0.1",
|
||||
"request": "^2.83.0",
|
||||
"strapi-utils": "3.0.0-alpha.19",
|
||||
"strapi-utils": "3.0.0-alpha.20",
|
||||
"uuid": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.19"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
|
||||
@ -109,7 +109,7 @@ module.exports = {
|
||||
params.model = 'user';
|
||||
params.id = (params._id || params.id);
|
||||
|
||||
await strapi.plugins['content-manager'].services['contentmanager'].delete(params, {source: 'users-permissions'});
|
||||
return await strapi.plugins['content-manager'].services['contentmanager'].delete(params, {source: 'users-permissions'});
|
||||
}
|
||||
|
||||
return strapi.query('user', 'users-permissions').delete(params);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-provider-email-amazon-ses",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Amazon SES provider for strapi email",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-provider-email-mailgun",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Mailgun provider for strapi email plugin",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-provider-email-sendgrid",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Sendgrid provider for strapi email",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-provider-email-sendmail",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Sendmail provider for strapi email",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-provider-upload-aws-s3",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "AWS S3 provider for strapi upload",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-provider-upload-cloudinary",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Cloudinary provider for strapi upload",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-provider-upload-local",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Local provider for strapi upload",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-provider-upload-rackspace",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Rackspace provider for strapi upload",
|
||||
"main": "./lib",
|
||||
"scripts": {
|
||||
|
||||
@ -477,7 +477,7 @@ module.exports = {
|
||||
formattedValue = value;
|
||||
}
|
||||
|
||||
if (_.includes(['_start', '_limit'], key)) {
|
||||
if (_.includes(['_start', '_limit', '_populate'], key)) {
|
||||
result = convertor(formattedValue, key);
|
||||
} else if (key === '_sort') {
|
||||
const [attr, order = 'ASC'] = formattedValue.split(':');
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-utils",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "Shared utilities for the Strapi packages",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -58,13 +58,17 @@ module.exports = function() {
|
||||
$('body').attr('back', `/`);
|
||||
}
|
||||
|
||||
fs.writeFile(sourcePath, $.html(), (err) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
if (!strapi.config.currentEnvironment.server.production) {
|
||||
fs.writeFile(sourcePath, $.html(), (err) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi",
|
||||
"version": "3.0.0-alpha.19",
|
||||
"version": "3.0.0-alpha.20",
|
||||
"description": "An open source solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -60,16 +60,16 @@
|
||||
"rimraf": "^2.6.2",
|
||||
"semver": "^5.4.1",
|
||||
"stack-trace": "0.0.10",
|
||||
"strapi-generate": "3.0.0-alpha.19",
|
||||
"strapi-generate-admin": "3.0.0-alpha.19",
|
||||
"strapi-generate-api": "3.0.0-alpha.19",
|
||||
"strapi-generate-controller": "3.0.0-alpha.19",
|
||||
"strapi-generate-model": "3.0.0-alpha.19",
|
||||
"strapi-generate-new": "3.0.0-alpha.19",
|
||||
"strapi-generate-plugin": "3.0.0-alpha.19",
|
||||
"strapi-generate-policy": "3.0.0-alpha.19",
|
||||
"strapi-generate-service": "3.0.0-alpha.19",
|
||||
"strapi-utils": "3.0.0-alpha.19"
|
||||
"strapi-generate": "3.0.0-alpha.20",
|
||||
"strapi-generate-admin": "3.0.0-alpha.20",
|
||||
"strapi-generate-api": "3.0.0-alpha.20",
|
||||
"strapi-generate-controller": "3.0.0-alpha.20",
|
||||
"strapi-generate-model": "3.0.0-alpha.20",
|
||||
"strapi-generate-new": "3.0.0-alpha.20",
|
||||
"strapi-generate-plugin": "3.0.0-alpha.20",
|
||||
"strapi-generate-policy": "3.0.0-alpha.20",
|
||||
"strapi-generate-service": "3.0.0-alpha.20",
|
||||
"strapi-utils": "3.0.0-alpha.20"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user