mirror of
https://github.com/strapi/strapi.git
synced 2025-12-04 19:13:20 +00:00
Merge pull request #3822 from strapi/chore/routing-x-forwarded
Remove x-forwarded-host headers in admin panel and set default security options for development
This commit is contained in:
commit
6ed183d59d
10
README.md
10
README.md
@ -97,11 +97,11 @@ This project is currently in **Beta**. Significant breaking changes are unlikely
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Modern Admin Panel:** Elegant, entirely customizable, and a fully extensible admin panel.
|
- **Modern Admin Panel:** Elegant, entirely customizable and a fully extensible admin panel.
|
||||||
- **Secure by default:** Reusable policies, CSRF, CORS, P3P, Xframe, XSS, and more.
|
- **Secure by default:** Reusable policies, CORS, CSP, P3P, Xframe, XSS, and more.
|
||||||
- **Plugins Oriented:** Install auth systems, content management, custom plugins, and more, in seconds.
|
- **Plugins Oriented:** Install auth system, content management, custom plugins, and more, in seconds.
|
||||||
- **Blazing Fast:** Built on top of Node.js, Strapi delivers impressive performance.
|
- **Blazing Fast:** Built on top of Node.js, Strapi delivers amazing performance.
|
||||||
- **Front-end Agnostic:** Use any front-end framework, for example, React, Vue, Angular, mobile apps, or even IoT.
|
- **Front-end Agnostic:** Use any front-end framework (React, Vue, Angular, etc.), mobile apps or even IoT.
|
||||||
- **Powerful CLI:** Scaffold projects and APIs on the fly.
|
- **Powerful CLI:** Scaffold projects and APIs on the fly.
|
||||||
- **SQL & NoSQL databases:** Works with MongoDB, PostgreSQL, MySQL, MariaDB, and SQLite.
|
- **SQL & NoSQL databases:** Works with MongoDB, PostgreSQL, MySQL, MariaDB, and SQLite.
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,6 @@ The core of Strapi embraces a small list of middlewares for performances, securi
|
|||||||
- cors
|
- cors
|
||||||
- cron
|
- cron
|
||||||
- csp
|
- csp
|
||||||
- csrf
|
|
||||||
- favicon
|
- favicon
|
||||||
- gzip
|
- gzip
|
||||||
- hsts
|
- hsts
|
||||||
|
|||||||
@ -396,10 +396,6 @@ The session doesn't work with `mongo` as a client. The package that we should us
|
|||||||
|
|
||||||
**Path —** `./config/environments/**/security.json`.
|
**Path —** `./config/environments/**/security.json`.
|
||||||
|
|
||||||
- [`csrf`](https://en.wikipedia.org/wiki/Cross-site_request_forgery)
|
|
||||||
- `enabled` (boolean): Enable or disable CSRF. Default value: depends on the environment.
|
|
||||||
- `key` (string): The name of the CSRF token added to the model. Default value: `_csrf`.
|
|
||||||
- `secret` (string): The key to place on the session object which maps to the server side token. Default value: `_csrfSecret`.
|
|
||||||
- [`csp`](https://en.wikipedia.org/wiki/Content_Security_Policy)
|
- [`csp`](https://en.wikipedia.org/wiki/Content_Security_Policy)
|
||||||
- `enabled` (boolean): Enable or disable CSP to avoid Cross Site Scripting (XSS) and data injection attacks.
|
- `enabled` (boolean): Enable or disable CSP to avoid Cross Site Scripting (XSS) and data injection attacks.
|
||||||
- [`p3p`](https://en.wikipedia.org/wiki/P3P)
|
- [`p3p`](https://en.wikipedia.org/wiki/P3P)
|
||||||
|
|||||||
@ -15,6 +15,17 @@ You can simply copy and paste this code in your own controller file to customize
|
|||||||
In the following example we will consider your controller, service and model is named `product`
|
In the following example we will consider your controller, service and model is named `product`
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
#### Utils
|
||||||
|
|
||||||
|
First require the utility functions
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
|
||||||
|
```
|
||||||
|
|
||||||
|
- `parseMultipartData`: This function parses strapi's formData format.
|
||||||
|
- `sanitizeEntity`: This function removes all private fields from the model and its relations.
|
||||||
|
|
||||||
#### `find`
|
#### `find`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -25,11 +36,15 @@ module.exports = {
|
|||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
find(ctx) {
|
async find(ctx) {
|
||||||
|
let entities;
|
||||||
if (ctx.query._q) {
|
if (ctx.query._q) {
|
||||||
return strapi.services.product.search(ctx.query);
|
entities = await service.search(ctx.query);
|
||||||
|
} else {
|
||||||
|
entities = await service.find(ctx.query);
|
||||||
}
|
}
|
||||||
return strapi.services.product.find(ctx.query);
|
|
||||||
|
return entities.map(entity => sanitizeEntity(entity, { model }));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -44,8 +59,9 @@ module.exports = {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
findOne(ctx) {
|
async findOne(ctx) {
|
||||||
return strapi.services.product.findOne(ctx.params);
|
const entity = await service.findOne(ctx.params);
|
||||||
|
return sanitizeEntity(entity, { model });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -62,9 +78,9 @@ module.exports = {
|
|||||||
|
|
||||||
count(ctx) {
|
count(ctx) {
|
||||||
if (ctx.query._q) {
|
if (ctx.query._q) {
|
||||||
return strapi.services.product.countSearch(ctx.query);
|
return service.countSearch(ctx.query);
|
||||||
}
|
}
|
||||||
return strapi.services.product.count(ctx.query);
|
return service.count(ctx.query);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -79,14 +95,15 @@ module.exports = {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create(ctx) {
|
async create(ctx) {
|
||||||
|
let entity;
|
||||||
if (ctx.is('multipart')) {
|
if (ctx.is('multipart')) {
|
||||||
// Parses strapi's formData format
|
const { data, files } = parseMultipartData(ctx);
|
||||||
const { data, files } = this.parseMultipartData(ctx);
|
entity = await service.create(data, { files });
|
||||||
return service.create(data, { files });
|
} else {
|
||||||
|
entity = await service.create(ctx.request.body);
|
||||||
}
|
}
|
||||||
|
return sanitizeEntity(entity, { model });
|
||||||
return service.create(ctx.request.body);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -101,14 +118,16 @@ module.exports = {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
update(ctx) {
|
async update(ctx) {
|
||||||
|
let entity;
|
||||||
if (ctx.is('multipart')) {
|
if (ctx.is('multipart')) {
|
||||||
// Parses strapi's formData format
|
const { data, files } = parseMultipartData(ctx);
|
||||||
const { data, files } = this.parseMultipartData(ctx);
|
entity = await service.update(ctx.params, data, { files });
|
||||||
return service.update(ctx.params, data, { files });
|
} else {
|
||||||
|
entity = await service.update(ctx.params, ctx.request.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
return service.update(ctx.params, ctx.request.body);
|
return sanitizeEntity(entity, { model });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -123,8 +142,9 @@ module.exports = {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
delete(ctx) {
|
async delete(ctx) {
|
||||||
return strapi.services.product.delete(ctx.params);
|
const entity = await service.delete(ctx.params);
|
||||||
|
return sanitizeEntity(entity, { model });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|||||||
@ -1,30 +1,28 @@
|
|||||||
{
|
{
|
||||||
"csrf": {
|
|
||||||
"enabled": false,
|
|
||||||
"key": "_csrf",
|
|
||||||
"secret": "_csrfSecret"
|
|
||||||
},
|
|
||||||
"csp": {
|
"csp": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"policy": {
|
"policy": [
|
||||||
"default-src": "'self'"
|
{
|
||||||
}
|
"img-src": "'self' http:"
|
||||||
|
},
|
||||||
|
"block-all-mixed-content"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"p3p": {
|
"p3p": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"value": ""
|
"value": ""
|
||||||
},
|
},
|
||||||
"hsts": {
|
"hsts": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"maxAge": 31536000,
|
"maxAge": 31536000,
|
||||||
"includeSubDomains": true
|
"includeSubDomains": true
|
||||||
},
|
},
|
||||||
"xframe": {
|
"xframe": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"value": "SAMEORIGIN"
|
"value": "SAMEORIGIN"
|
||||||
},
|
},
|
||||||
"xss": {
|
"xss": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"mode": "block"
|
"mode": "block"
|
||||||
},
|
},
|
||||||
"cors": {
|
"cors": {
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
{
|
{
|
||||||
"csrf": {
|
|
||||||
"enabled": false,
|
|
||||||
"key": "_csrf",
|
|
||||||
"secret": "_csrfSecret"
|
|
||||||
},
|
|
||||||
"csp": {
|
"csp": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"policy": [
|
"policy": [
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
{
|
{
|
||||||
"csrf": {
|
|
||||||
"enabled": false,
|
|
||||||
"key": "_csrf",
|
|
||||||
"secret": "_csrfSecret"
|
|
||||||
},
|
|
||||||
"csp": {
|
"csp": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"policy": [
|
"policy": [
|
||||||
|
|||||||
@ -3,6 +3,10 @@
|
|||||||
const execa = require('execa');
|
const execa = require('execa');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const formatError = error => [
|
||||||
|
{ messages: [{ id: error.id, message: error.message, field: error.field }] },
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of functions called "actions" for `Admin`
|
* A set of functions called "actions" for `Admin`
|
||||||
*/
|
*/
|
||||||
@ -121,9 +125,38 @@ module.exports = {
|
|||||||
async create(ctx) {
|
async create(ctx) {
|
||||||
const { email, username, password, blocked } = ctx.request.body;
|
const { email, username, password, blocked } = ctx.request.body;
|
||||||
|
|
||||||
if (!email) return ctx.badRequest('missing.email');
|
if (!email) {
|
||||||
if (!username) return ctx.badRequest('missing.username');
|
return ctx.badRequest(
|
||||||
if (!password) return ctx.badRequest('missing.password');
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.email',
|
||||||
|
message: 'Missing email',
|
||||||
|
field: ['email'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
return ctx.badRequest(
|
||||||
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.username',
|
||||||
|
message: 'Missing username',
|
||||||
|
field: ['username'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!password) {
|
||||||
|
return ctx.badRequest(
|
||||||
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.password',
|
||||||
|
message: 'Missing password',
|
||||||
|
field: ['password'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const adminsWithSameEmail = await strapi
|
const adminsWithSameEmail = await strapi
|
||||||
.query('administrator', 'admin')
|
.query('administrator', 'admin')
|
||||||
@ -136,33 +169,22 @@ module.exports = {
|
|||||||
if (adminsWithSameEmail) {
|
if (adminsWithSameEmail) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [
|
id: 'Auth.form.error.email.taken',
|
||||||
{
|
message: 'Email already taken',
|
||||||
messages: [
|
field: ['email'],
|
||||||
{ id: 'Auth.form.error.email.taken', field: ['email'] },
|
})
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: 'email.alreadyTaken'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adminsWithSameUsername) {
|
if (adminsWithSameUsername) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [
|
id: 'Auth.form.error.username.taken',
|
||||||
{
|
message: 'Username already taken',
|
||||||
messages: [
|
field: ['username'],
|
||||||
{
|
})
|
||||||
id: 'Auth.form.error.username.taken',
|
|
||||||
field: ['username'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: 'username.alreadyTaken.'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,10 +211,38 @@ module.exports = {
|
|||||||
const { id } = ctx.params;
|
const { id } = ctx.params;
|
||||||
const { email, username, password, blocked } = ctx.request.body;
|
const { email, username, password, blocked } = ctx.request.body;
|
||||||
|
|
||||||
if (!email) return ctx.badRequest('Missing email');
|
if (!email) {
|
||||||
if (!username) return ctx.badRequest('Missing username');
|
return ctx.badRequest(
|
||||||
if (!password) return ctx.badRequest('Missing password');
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.email',
|
||||||
|
message: 'Missing email',
|
||||||
|
field: ['email'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
return ctx.badRequest(
|
||||||
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.username',
|
||||||
|
message: 'Missing username',
|
||||||
|
field: ['username'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!password) {
|
||||||
|
return ctx.badRequest(
|
||||||
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.password',
|
||||||
|
message: 'Missing password',
|
||||||
|
field: ['password'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
const admin = await strapi
|
const admin = await strapi
|
||||||
.query('administrator', 'admin')
|
.query('administrator', 'admin')
|
||||||
.findOne(ctx.params);
|
.findOne(ctx.params);
|
||||||
@ -209,15 +259,11 @@ module.exports = {
|
|||||||
if (adminsWithSameEmail && adminsWithSameEmail.id !== admin.id) {
|
if (adminsWithSameEmail && adminsWithSameEmail.id !== admin.id) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [
|
id: 'Auth.form.error.email.taken',
|
||||||
{
|
message: 'Email already taken',
|
||||||
messages: [
|
field: ['email'],
|
||||||
{ id: 'Auth.form.error.email.taken', field: ['email'] },
|
})
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: 'Email is already taken.'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,18 +277,11 @@ module.exports = {
|
|||||||
if (adminsWithSameUsername && adminsWithSameUsername.id !== admin.id) {
|
if (adminsWithSameUsername && adminsWithSameUsername.id !== admin.id) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [
|
id: 'Auth.form.error.username.taken',
|
||||||
{
|
message: 'Username already taken',
|
||||||
messages: [
|
field: ['username'],
|
||||||
{
|
})
|
||||||
id: 'Auth.form.error.username.taken',
|
|
||||||
field: ['username'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: 'Username is already taken.'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,9 @@ const crypto = require('crypto');
|
|||||||
const _ = require('lodash');
|
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,}))$/;
|
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,}))$/;
|
||||||
|
const formatError = error => [
|
||||||
|
{ messages: [{ id: error.id, message: error.message, field: error.field }] },
|
||||||
|
];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
async callback(ctx) {
|
async callback(ctx) {
|
||||||
@ -20,9 +23,10 @@ module.exports = {
|
|||||||
if (!params.identifier) {
|
if (!params.identifier) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }]
|
id: 'Auth.form.error.email.provide',
|
||||||
: 'Please provide your username or your e-mail.'
|
message: 'Please provide your username or your e-mail.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,9 +34,10 @@ module.exports = {
|
|||||||
if (!params.password) {
|
if (!params.password) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.password.provide' }] }]
|
id: 'Auth.form.error.password.provide',
|
||||||
: 'Please provide your password.'
|
message: 'Please provide your password.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,18 +59,20 @@ module.exports = {
|
|||||||
if (!admin) {
|
if (!admin) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.invalid' }] }]
|
id: 'Auth.form.error.invalid',
|
||||||
: 'Identifier or password invalid.'
|
message: 'Identifier or password invalid.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (admin.blocked === true) {
|
if (admin.blocked === true) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.blocked' }] }]
|
id: 'Auth.form.error.blocked',
|
||||||
: 'Your account has been blocked by the administrator.'
|
message: 'Your account has been blocked by the administrator.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,9 +84,10 @@ module.exports = {
|
|||||||
if (!validPassword) {
|
if (!validPassword) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.invalid' }] }]
|
id: 'Auth.form.error.invalid',
|
||||||
: 'Identifier or password invalid.'
|
message: 'Identifier or password invalid.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
admin.isAdmin = true;
|
admin.isAdmin = true;
|
||||||
@ -98,9 +106,10 @@ module.exports = {
|
|||||||
if (!params.username) {
|
if (!params.username) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.username.provide' }] }]
|
id: 'Auth.form.error.username.provide',
|
||||||
: 'Please provide your username.'
|
message: 'Please provide your username.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,9 +117,10 @@ module.exports = {
|
|||||||
if (!params.email) {
|
if (!params.email) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }]
|
id: 'Auth.form.error.email.provide',
|
||||||
: 'Please provide your email.'
|
message: 'Please provide your email.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,9 +137,10 @@ module.exports = {
|
|||||||
if (!params.password) {
|
if (!params.password) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.password.provide' }] }]
|
id: 'Auth.form.error.password.provide',
|
||||||
: 'Please provide your password.'
|
message: 'Please provide your password.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,9 +152,10 @@ module.exports = {
|
|||||||
if (admins.length > 0) {
|
if (admins.length > 0) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.admin.exist' }] }]
|
id: 'Auth.form.error.admin.exist',
|
||||||
: "You can't register a new admin."
|
message: "You can't register a new admin",
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,9 +170,10 @@ module.exports = {
|
|||||||
if (admin) {
|
if (admin) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.email.taken' }] }]
|
id: 'Auth.form.error.email.taken',
|
||||||
: 'Email is already taken.'
|
message: 'Email is already taken',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,13 +193,13 @@ module.exports = {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
strapi.log.error(err);
|
strapi.log.error(err);
|
||||||
const adminError = _.includes(err.message, 'username')
|
const adminError = _.includes(err.message, 'username')
|
||||||
? 'Auth.form.error.username.taken'
|
? {
|
||||||
: 'Auth.form.error.email.taken';
|
id: 'Auth.form.error.username.taken',
|
||||||
|
message: 'Username already taken',
|
||||||
|
}
|
||||||
|
: { id: 'Auth.form.error.email.taken', message: 'Email already taken' };
|
||||||
|
|
||||||
ctx.badRequest(
|
ctx.badRequest(null, formatError(adminError));
|
||||||
null,
|
|
||||||
ctx.request.admin ? [{ messages: [{ id: adminError }] }] : err.message
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -196,17 +209,42 @@ module.exports = {
|
|||||||
...ctx.params,
|
...ctx.params,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!password) return ctx.badRequest('Missing password');
|
if (!password) {
|
||||||
if (!passwordConfirmation)
|
return ctx.badRequest(
|
||||||
return ctx.badRequest('Missing passwordConfirmation');
|
null,
|
||||||
if (!code) return ctx.badRequest('Missing code');
|
formatError({
|
||||||
|
id: 'missing.password',
|
||||||
|
message: 'Missing password',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!passwordConfirmation) {
|
||||||
|
return ctx.badRequest(
|
||||||
|
formatError({
|
||||||
|
id: 'missing.passwordConfirmation',
|
||||||
|
message: 'Missing passwordConfirmation',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!code) {
|
||||||
|
return ctx.badRequest(
|
||||||
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.code',
|
||||||
|
message: 'Missing code',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (password !== passwordConfirmation) {
|
if (password !== passwordConfirmation) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.password.matching' }] }]
|
id: 'Auth.form.error.password.matching',
|
||||||
: 'Passwords do not match.'
|
message: 'Passwords do not match.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,9 +255,10 @@ module.exports = {
|
|||||||
if (!admin) {
|
if (!admin) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.code.provide' }] }]
|
id: 'Auth.form.error.code.provide',
|
||||||
: 'Incorrect code provided.'
|
message: 'Incorrect code provided.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,8 +280,24 @@ module.exports = {
|
|||||||
async forgotPassword(ctx) {
|
async forgotPassword(ctx) {
|
||||||
const { email, url } = ctx.request.body;
|
const { email, url } = ctx.request.body;
|
||||||
|
|
||||||
if (!email) return ctx.badRequest('Missing email');
|
if (!email) {
|
||||||
if (!url) return ctx.badRequest('Missing url');
|
return ctx.badRequest(
|
||||||
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.email',
|
||||||
|
message: 'Missing email',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!url) {
|
||||||
|
return ctx.badRequest(
|
||||||
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'missing.url',
|
||||||
|
message: 'Missing url',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Find the admin thanks to his email.
|
// Find the admin thanks to his email.
|
||||||
const admin = await strapi
|
const admin = await strapi
|
||||||
@ -253,9 +308,10 @@ module.exports = {
|
|||||||
if (!admin) {
|
if (!admin) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.user.not-exist' }] }]
|
id: 'Auth.form.error.user.not-exist',
|
||||||
: 'This email does not exist.'
|
message: 'This email does not exit',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +1,28 @@
|
|||||||
{
|
{
|
||||||
"csrf": {
|
|
||||||
"enabled": false,
|
|
||||||
"key": "_csrf",
|
|
||||||
"secret": "_csrfSecret"
|
|
||||||
},
|
|
||||||
"csp": {
|
"csp": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"policy": {
|
"policy": [
|
||||||
"default-src": "'self'"
|
{
|
||||||
}
|
"img-src": "'self' http:"
|
||||||
|
},
|
||||||
|
"block-all-mixed-content"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"p3p": {
|
"p3p": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"value": ""
|
"value": ""
|
||||||
},
|
},
|
||||||
"hsts": {
|
"hsts": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"maxAge": 31536000,
|
"maxAge": 31536000,
|
||||||
"includeSubDomains": true
|
"includeSubDomains": true
|
||||||
},
|
},
|
||||||
"xframe": {
|
"xframe": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"value": "SAMEORIGIN"
|
"value": "SAMEORIGIN"
|
||||||
},
|
},
|
||||||
"xss": {
|
"xss": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"mode": "block"
|
"mode": "block"
|
||||||
},
|
},
|
||||||
"cors": {
|
"cors": {
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
{
|
{
|
||||||
"csrf": {
|
|
||||||
"enabled": false,
|
|
||||||
"key": "_csrf",
|
|
||||||
"secret": "_csrfSecret"
|
|
||||||
},
|
|
||||||
"csp": {
|
"csp": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"policy": [
|
"policy": [
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
{
|
{
|
||||||
"csrf": {
|
|
||||||
"enabled": false,
|
|
||||||
"key": "_csrf",
|
|
||||||
"secret": "_csrfSecret"
|
|
||||||
},
|
|
||||||
"csp": {
|
"csp": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"policy": [
|
"policy": [
|
||||||
|
|||||||
@ -135,10 +135,7 @@ export default function request(...args) {
|
|||||||
{
|
{
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
options.headers,
|
options.headers
|
||||||
{
|
|
||||||
'X-Forwarded-Host': 'strapi',
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -178,7 +178,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
|
|||||||
const runDelete = async trx => {
|
const runDelete = async trx => {
|
||||||
await deleteGroups(entry, { transacting: trx });
|
await deleteGroups(entry, { transacting: trx });
|
||||||
await model.forge(params).destroy({ transacting: trx, require: false });
|
await model.forge(params).destroy({ transacting: trx, require: false });
|
||||||
return entry;
|
return entry.toJSON();
|
||||||
};
|
};
|
||||||
|
|
||||||
return wrapTransaction(runDelete, { transacting });
|
return wrapTransaction(runDelete, { transacting });
|
||||||
@ -217,7 +217,8 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
|
|||||||
})
|
})
|
||||||
.fetchAll({
|
.fetchAll({
|
||||||
withRelated: populate,
|
withRelated: populate,
|
||||||
});
|
})
|
||||||
|
.then(results => results.toJSON());
|
||||||
}
|
}
|
||||||
|
|
||||||
function countSearch(params) {
|
function countSearch(params) {
|
||||||
|
|||||||
@ -199,9 +199,9 @@ module.exports = ({ model, modelKey, strapi }) => {
|
|||||||
model,
|
model,
|
||||||
filters,
|
filters,
|
||||||
populate: populateOpt,
|
populate: populateOpt,
|
||||||
}).then(results => {
|
}).then(results =>
|
||||||
return results.map(result => (result ? result.toObject() : null));
|
results.map(result => (result ? result.toObject() : null))
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findOne(params, populate) {
|
async function findOne(params, populate) {
|
||||||
@ -326,7 +326,7 @@ module.exports = ({ model, modelKey, strapi }) => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
return entry;
|
return entry.toObject ? entry.toObject() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(params, populate) {
|
function search(params, populate) {
|
||||||
@ -340,7 +340,10 @@ module.exports = ({ model, modelKey, strapi }) => {
|
|||||||
.sort(filters.sort)
|
.sort(filters.sort)
|
||||||
.skip(filters.start)
|
.skip(filters.start)
|
||||||
.limit(filters.limit)
|
.limit(filters.limit)
|
||||||
.populate(populate || defaultPopulate);
|
.populate(populate || defaultPopulate)
|
||||||
|
.then(results =>
|
||||||
|
results.map(result => (result ? result.toObject() : null))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function countSearch(params) {
|
function countSearch(params) {
|
||||||
|
|||||||
@ -673,9 +673,7 @@ class Wysiwyg extends React.Component {
|
|||||||
uploadFile = files => {
|
uploadFile = files => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('files', files[0]);
|
formData.append('files', files[0]);
|
||||||
const headers = {
|
const headers = {};
|
||||||
'X-Forwarded-Host': 'strapi',
|
|
||||||
};
|
|
||||||
|
|
||||||
let newEditorState = this.getEditorState();
|
let newEditorState = this.getEditorState();
|
||||||
|
|
||||||
|
|||||||
@ -265,7 +265,7 @@ function EditView({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Change the request helper default headers so we can pass a FormData
|
// Change the request helper default headers so we can pass a FormData
|
||||||
const headers = { 'X-Forwarded-Host': 'strapi' };
|
const headers = {};
|
||||||
const method = isCreatingEntry ? 'POST' : 'PUT';
|
const method = isCreatingEntry ? 'POST' : 'PUT';
|
||||||
const endPoint = isCreatingEntry ? slug : `${slug}/${id}`;
|
const endPoint = isCreatingEntry ? slug : `${slug}/${id}`;
|
||||||
|
|
||||||
|
|||||||
@ -95,12 +95,13 @@ module.exports = {
|
|||||||
strapi.emit('didCreateFirstContentTypeEntry', ctx.params, source);
|
strapi.emit('didCreateFirstContentTypeEntry', ctx.params, source);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
strapi.log.error(error);
|
strapi.log.error(error);
|
||||||
ctx.badRequest(
|
ctx.badRequest(null, [
|
||||||
null,
|
{
|
||||||
ctx.request.admin
|
messages: [
|
||||||
? [{ messages: [{ id: error.message, field: error.field }] }]
|
{ id: error.message, message: error.message, field: error.field },
|
||||||
: error.message
|
],
|
||||||
);
|
},
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -131,12 +132,13 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
strapi.log.error(error);
|
strapi.log.error(error);
|
||||||
ctx.badRequest(
|
ctx.badRequest(null, [
|
||||||
null,
|
{
|
||||||
ctx.request.admin
|
messages: [
|
||||||
? [{ messages: [{ id: error.message, field: error.field }] }]
|
{ id: error.message, message: error.message, field: error.field },
|
||||||
: error.message
|
],
|
||||||
);
|
},
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -9,18 +9,26 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
send: async (ctx) => {
|
send: async ctx => {
|
||||||
// Retrieve provider configuration.
|
// Retrieve provider configuration.
|
||||||
const config = await strapi.store({
|
const config = await strapi
|
||||||
environment: strapi.config.environment,
|
.store({
|
||||||
type: 'plugin',
|
environment: strapi.config.environment,
|
||||||
name: 'email'
|
type: 'plugin',
|
||||||
}).get({ key: 'provider' });
|
name: 'email',
|
||||||
|
})
|
||||||
|
.get({ key: 'provider' });
|
||||||
|
|
||||||
// Verify if the file email is enable.
|
// Verify if the file email is enable.
|
||||||
if (config.enabled === false) {
|
if (config.enabled === false) {
|
||||||
strapi.log.error('Email is disabled');
|
strapi.log.error('Email is disabled');
|
||||||
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Email.status.disabled' }] }] : 'Emailis disabled');
|
return ctx.badRequest(null, [
|
||||||
|
{
|
||||||
|
messages: [
|
||||||
|
{ id: 'Email.status.disabled', message: 'Emails disabled' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Something is wrong
|
// Something is wrong
|
||||||
@ -36,33 +44,40 @@ module.exports = {
|
|||||||
ctx.send({});
|
ctx.send({});
|
||||||
},
|
},
|
||||||
|
|
||||||
getEnvironments: async (ctx) => {
|
getEnvironments: async ctx => {
|
||||||
const environments = _.map(_.keys(strapi.config.environments), environment => {
|
const environments = _.map(
|
||||||
return {
|
_.keys(strapi.config.environments),
|
||||||
name: environment,
|
environment => {
|
||||||
active: (strapi.config.environment === environment)
|
return {
|
||||||
};
|
name: environment,
|
||||||
});
|
active: strapi.config.environment === environment,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
ctx.send({ environments });
|
ctx.send({ environments });
|
||||||
},
|
},
|
||||||
|
|
||||||
getSettings: async (ctx) => {
|
getSettings: async ctx => {
|
||||||
let config = await strapi.plugins.email.services.email.getProviderConfig(ctx.params.environment);
|
let config = await strapi.plugins.email.services.email.getProviderConfig(
|
||||||
|
ctx.params.environment
|
||||||
|
);
|
||||||
|
|
||||||
ctx.send({
|
ctx.send({
|
||||||
providers: strapi.plugins.email.config.providers,
|
providers: strapi.plugins.email.config.providers,
|
||||||
config
|
config,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateSettings: async (ctx) => {
|
updateSettings: async ctx => {
|
||||||
await strapi.store({
|
await strapi
|
||||||
environment: ctx.params.environment,
|
.store({
|
||||||
type: 'plugin',
|
environment: ctx.params.environment,
|
||||||
name: 'email'
|
type: 'plugin',
|
||||||
}).set({key: 'provider', value: ctx.request.body});
|
name: 'email',
|
||||||
|
})
|
||||||
|
.set({ key: 'provider', value: ctx.request.body });
|
||||||
|
|
||||||
ctx.send({ok: true});
|
ctx.send({ ok: true });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "تكوين إعدادات الأمان الخاصة بك.",
|
"form.security.description": "تكوين إعدادات الأمان الخاصة بك.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "الزاوي",
|
|
||||||
"form.security.item.csrf.cookie": "الكعكات",
|
|
||||||
"form.security.item.csrf.key": "المفتاح",
|
|
||||||
"form.security.item.csrf.secret": "الحماية",
|
|
||||||
"form.security.item.hsts": "المضيفين",
|
"form.security.item.hsts": "المضيفين",
|
||||||
"form.security.item.hsts.includeSubDomains": "تضمين المجال الفرعي",
|
"form.security.item.hsts.includeSubDomains": "تضمين المجال الفرعي",
|
||||||
"form.security.item.hsts.maxAge": "أقصى عمر",
|
"form.security.item.hsts.maxAge": "أقصى عمر",
|
||||||
@ -629,4 +624,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "تمت إضافة اللغة بنجاح.",
|
"strapi.notification.success.languageAdd": "تمت إضافة اللغة بنجاح.",
|
||||||
"strapi.notification.success.languageDelete": "تم حذف اللغة بنجاح.",
|
"strapi.notification.success.languageDelete": "تم حذف اللغة بنجاح.",
|
||||||
"strapi.notification.success.settingsEdit": "تم تحديث الإعدادات بنجاح."
|
"strapi.notification.success.settingsEdit": "تم تحديث الإعدادات بنجاح."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Verwalte deine Sicherheitseinstellungen.",
|
"form.security.description": "Verwalte deine Sicherheitseinstellungen.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Key",
|
|
||||||
"form.security.item.csrf.secret": "Secret",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Subdomain mit einschließen",
|
"form.security.item.hsts.includeSubDomains": "Subdomain mit einschließen",
|
||||||
"form.security.item.hsts.maxAge": "Max Age",
|
"form.security.item.hsts.maxAge": "Max Age",
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Configure your security settings.",
|
"form.security.description": "Configure your security settings.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Key",
|
|
||||||
"form.security.item.csrf.secret": "Secret",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Include Sub Domain",
|
"form.security.item.hsts.includeSubDomains": "Include Sub Domain",
|
||||||
"form.security.item.hsts.maxAge": "Max Age",
|
"form.security.item.hsts.maxAge": "Max Age",
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Configurar las opciones de seguridad.",
|
"form.security.description": "Configurar las opciones de seguridad.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origen",
|
"form.security.item.cors.origin": "Origen",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Clave",
|
|
||||||
"form.security.item.csrf.secret": "Secreto",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Incluir Sub Dominio",
|
"form.security.item.hsts.includeSubDomains": "Incluir Sub Dominio",
|
||||||
"form.security.item.hsts.maxAge": "Edad Máxima",
|
"form.security.item.hsts.maxAge": "Edad Máxima",
|
||||||
|
|||||||
@ -54,12 +54,6 @@
|
|||||||
"form.security.description": "Configurations de sécurité.",
|
"form.security.description": "Configurations de sécurité.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origine",
|
"form.security.item.cors.origin": "Origine",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Clé",
|
|
||||||
"form.security.item.csrf.secret": "Clé secrète",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
|
||||||
"form.security.item.hsts.includeSubDomains": "Inclure les sous-domaines",
|
"form.security.item.hsts.includeSubDomains": "Inclure les sous-domaines",
|
||||||
"form.security.item.hsts.maxAge": "Max Age",
|
"form.security.item.hsts.maxAge": "Max Age",
|
||||||
"form.security.item.hsts.preload": "Preload",
|
"form.security.item.hsts.preload": "Preload",
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Configurare le impostazioni di sicurezza.",
|
"form.security.description": "Configurare le impostazioni di sicurezza.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origine",
|
"form.security.item.cors.origin": "Origine",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angolare",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Chiave",
|
|
||||||
"form.security.item.csrf.secret": "Segreto",
|
|
||||||
"form.security.item.hsts": "OSPITA",
|
"form.security.item.hsts": "OSPITA",
|
||||||
"form.security.item.hsts.includeSubDomains": "Includi domini secondari",
|
"form.security.item.hsts.includeSubDomains": "Includi domini secondari",
|
||||||
"form.security.item.hsts.maxAge": "Età Max",
|
"form.security.item.hsts.maxAge": "Età Max",
|
||||||
@ -629,4 +624,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "Il linguaggio è stato aggiunto con successo.",
|
"strapi.notification.success.languageAdd": "Il linguaggio è stato aggiunto con successo.",
|
||||||
"strapi.notification.success.languageDelete": "Il linguaggio è stato eliminato con successo.",
|
"strapi.notification.success.languageDelete": "Il linguaggio è stato eliminato con successo.",
|
||||||
"strapi.notification.success.settingsEdit": "Le impostazioni sono state aggiornate con successo."
|
"strapi.notification.success.settingsEdit": "Le impostazioni sono state aggiornate con successo."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "セキュリティ設定を構成します。",
|
"form.security.description": "セキュリティ設定を構成します。",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Key",
|
|
||||||
"form.security.item.csrf.secret": "Secret",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "サブドメインを含める",
|
"form.security.item.hsts.includeSubDomains": "サブドメインを含める",
|
||||||
"form.security.item.hsts.maxAge": "Max Age",
|
"form.security.item.hsts.maxAge": "Max Age",
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "보안 환경을 설정하세요.",
|
"form.security.description": "보안 환경을 설정하세요.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "앵귤러 (Angular)",
|
|
||||||
"form.security.item.csrf.cookie": "쿠키 (Cookie)",
|
|
||||||
"form.security.item.csrf.key": "키 (Key)",
|
|
||||||
"form.security.item.csrf.secret": "시크릿 (Secret)",
|
|
||||||
"form.security.item.hsts": "호스트 (HOSTS)",
|
"form.security.item.hsts": "호스트 (HOSTS)",
|
||||||
"form.security.item.hsts.includeSubDomains": "서브 도메인 포함",
|
"form.security.item.hsts.includeSubDomains": "서브 도메인 포함",
|
||||||
"form.security.item.hsts.maxAge": "만료 (Max Age)",
|
"form.security.item.hsts.maxAge": "만료 (Max Age)",
|
||||||
@ -629,4 +624,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "언어를 추가했습니다.",
|
"strapi.notification.success.languageAdd": "언어를 추가했습니다.",
|
||||||
"strapi.notification.success.languageDelete": "언어를 제거했습니다.",
|
"strapi.notification.success.languageDelete": "언어를 제거했습니다.",
|
||||||
"strapi.notification.success.settingsEdit": "설정을 업데이트했습니다."
|
"strapi.notification.success.settingsEdit": "설정을 업데이트했습니다."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Configureer je beveiliging instellingen.",
|
"form.security.description": "Configureer je beveiliging instellingen.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Key",
|
|
||||||
"form.security.item.csrf.secret": "Secret",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Inclusief Sub Domain",
|
"form.security.item.hsts.includeSubDomains": "Inclusief Sub Domain",
|
||||||
"form.security.item.hsts.maxAge": "Max Leeftijd",
|
"form.security.item.hsts.maxAge": "Max Leeftijd",
|
||||||
@ -634,4 +629,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "De taal is succesvol toegevoegd.",
|
"strapi.notification.success.languageAdd": "De taal is succesvol toegevoegd.",
|
||||||
"strapi.notification.success.languageDelete": "De taal is succesvol verwijderd.",
|
"strapi.notification.success.languageDelete": "De taal is succesvol verwijderd.",
|
||||||
"strapi.notification.success.settingsEdit": "De instellingen zijn succesvol geüpdatet"
|
"strapi.notification.success.settingsEdit": "De instellingen zijn succesvol geüpdatet"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Konfiguruj ustawienia bezpieczeństwa.",
|
"form.security.description": "Konfiguruj ustawienia bezpieczeństwa.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Źródło",
|
"form.security.item.cors.origin": "Źródło",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Klucz",
|
|
||||||
"form.security.item.csrf.secret": "Sekretny klucz",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Subdomeny",
|
"form.security.item.hsts.includeSubDomains": "Subdomeny",
|
||||||
"form.security.item.hsts.maxAge": "Max Age",
|
"form.security.item.hsts.maxAge": "Max Age",
|
||||||
@ -634,4 +629,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "Język został pomyślnie dodany.",
|
"strapi.notification.success.languageAdd": "Język został pomyślnie dodany.",
|
||||||
"strapi.notification.success.languageDelete": "Język został pomyślnie usunięty.",
|
"strapi.notification.success.languageDelete": "Język został pomyślnie usunięty.",
|
||||||
"strapi.notification.success.settingsEdit": "Ustawienia zostały pomyślnie zmienione."
|
"strapi.notification.success.settingsEdit": "Ustawienia zostały pomyślnie zmienione."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Defina as suas configurações de segurança.",
|
"form.security.description": "Defina as suas configurações de segurança.",
|
||||||
"form.security.item.cors": "CORS",
|
"form.security.item.cors": "CORS",
|
||||||
"form.security.item.cors.origin": "Origem",
|
"form.security.item.cors.origin": "Origem",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Chave",
|
|
||||||
"form.security.item.csrf.secret": "Segredo",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Incluir Sub Domínio",
|
"form.security.item.hsts.includeSubDomains": "Incluir Sub Domínio",
|
||||||
"form.security.item.hsts.maxAge": "Idade máxima",
|
"form.security.item.hsts.maxAge": "Idade máxima",
|
||||||
@ -629,4 +624,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "O idioma foi adicionado com sucesso.",
|
"strapi.notification.success.languageAdd": "O idioma foi adicionado com sucesso.",
|
||||||
"strapi.notification.success.languageDelete": "O idioma foi removido com sucesso.",
|
"strapi.notification.success.languageDelete": "O idioma foi removido com sucesso.",
|
||||||
"strapi.notification.success.settingsEdit": "As configurações foram atualizadas com sucesso."
|
"strapi.notification.success.settingsEdit": "As configurações foram atualizadas com sucesso."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Configure as suas definições de segurança.",
|
"form.security.description": "Configure as suas definições de segurança.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origem",
|
"form.security.item.cors.origin": "Origem",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Chave",
|
|
||||||
"form.security.item.csrf.secret": "Secreta",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Incluir Sub Domínio",
|
"form.security.item.hsts.includeSubDomains": "Incluir Sub Domínio",
|
||||||
"form.security.item.hsts.maxAge": "Idade máxima",
|
"form.security.item.hsts.maxAge": "Idade máxima",
|
||||||
@ -634,4 +629,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "O idioma foi adicionado com sucesso.",
|
"strapi.notification.success.languageAdd": "O idioma foi adicionado com sucesso.",
|
||||||
"strapi.notification.success.languageDelete": "O idioma foi excluido com sucesso.",
|
"strapi.notification.success.languageDelete": "O idioma foi excluido com sucesso.",
|
||||||
"strapi.notification.success.settingsEdit": "As configurações foram actualizadas com sucesso."
|
"strapi.notification.success.settingsEdit": "As configurações foram actualizadas com sucesso."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Задайте настройки безопасности.",
|
"form.security.description": "Задайте настройки безопасности.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Key",
|
|
||||||
"form.security.item.csrf.secret": "Secret",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Include Sub Domain",
|
"form.security.item.hsts.includeSubDomains": "Include Sub Domain",
|
||||||
"form.security.item.hsts.maxAge": "Max Age",
|
"form.security.item.hsts.maxAge": "Max Age",
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "Güvenlik ayarlarınızı yapılandırın.",
|
"form.security.description": "Güvenlik ayarlarınızı yapılandırın.",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Açısal",
|
|
||||||
"form.security.item.csrf.cookie": "Çerez",
|
|
||||||
"form.security.item.csrf.key": "Anahtar",
|
|
||||||
"form.security.item.csrf.secret": "Gizli",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "Alt Etki Alanını Dahil Et",
|
"form.security.item.hsts.includeSubDomains": "Alt Etki Alanını Dahil Et",
|
||||||
"form.security.item.hsts.maxAge": "Max Age",
|
"form.security.item.hsts.maxAge": "Max Age",
|
||||||
@ -634,4 +629,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "Dil başarıyla eklendi.",
|
"strapi.notification.success.languageAdd": "Dil başarıyla eklendi.",
|
||||||
"strapi.notification.success.languageDelete": "Dil başarıyla silindi.",
|
"strapi.notification.success.languageDelete": "Dil başarıyla silindi.",
|
||||||
"strapi.notification.success.settingsEdit": "Ayarlar başarıyla güncellendi."
|
"strapi.notification.success.settingsEdit": "Ayarlar başarıyla güncellendi."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,11 +53,6 @@
|
|||||||
"form.security.description": "配置安全设置。",
|
"form.security.description": "配置安全设置。",
|
||||||
"form.security.item.cors": "Cors",
|
"form.security.item.cors": "Cors",
|
||||||
"form.security.item.cors.origin": "Origin",
|
"form.security.item.cors.origin": "Origin",
|
||||||
"form.security.item.csrf": "CSRF",
|
|
||||||
"form.security.item.csrf.angular": "Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "Key",
|
|
||||||
"form.security.item.csrf.secret": "Secret",
|
|
||||||
"form.security.item.hsts": "HOSTS",
|
"form.security.item.hsts": "HOSTS",
|
||||||
"form.security.item.hsts.includeSubDomains": "包括子域",
|
"form.security.item.hsts.includeSubDomains": "包括子域",
|
||||||
"form.security.item.hsts.maxAge": "Max Age",
|
"form.security.item.hsts.maxAge": "Max Age",
|
||||||
@ -628,4 +623,4 @@
|
|||||||
"strapi.notification.success.languageAdd": "该语言已成功添加。",
|
"strapi.notification.success.languageAdd": "该语言已成功添加。",
|
||||||
"strapi.notification.success.languageDelete": "数据库已被成功删除。",
|
"strapi.notification.success.languageDelete": "数据库已被成功删除。",
|
||||||
"strapi.notification.success.settingsEdit": "设置已成功更新。"
|
"strapi.notification.success.settingsEdit": "设置已成功更新。"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
"form.security.description": "調整安全性設定",
|
"form.security.description": "調整安全性設定",
|
||||||
"form.security.item.cors": "跨域資源共享 (Cors)",
|
"form.security.item.cors": "跨域資源共享 (Cors)",
|
||||||
"form.security.item.cors.origin": "來源",
|
"form.security.item.cors.origin": "來源",
|
||||||
"form.security.item.csrf": "跨站請求偽造保護 (CSRF)",
|
|
||||||
"form.security.item.csrf.angular": "使用 Angular",
|
|
||||||
"form.security.item.csrf.cookie": "Cookie",
|
|
||||||
"form.security.item.csrf.key": "鍵值",
|
|
||||||
"form.security.item.csrf.secret": "密鑰鍵值",
|
|
||||||
"form.security.item.hsts": "強制安全傳輸 (HSTS)",
|
"form.security.item.hsts": "強制安全傳輸 (HSTS)",
|
||||||
"form.security.item.hsts.includeSubDomains": "包含子域名",
|
"form.security.item.hsts.includeSubDomains": "包含子域名",
|
||||||
"form.security.item.hsts.maxAge": "作用期",
|
"form.security.item.hsts.maxAge": "作用期",
|
||||||
|
|||||||
@ -285,70 +285,6 @@ module.exports = {
|
|||||||
name: 'form.security.name',
|
name: 'form.security.name',
|
||||||
description: 'form.security.description',
|
description: 'form.security.description',
|
||||||
sections: [
|
sections: [
|
||||||
{
|
|
||||||
name: 'form.security.item.csrf',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
name: 'form.security.item.csrf.enabled',
|
|
||||||
target: 'security.csrf.enabled',
|
|
||||||
type: 'boolean',
|
|
||||||
value: _.get(
|
|
||||||
strapi.config,
|
|
||||||
`environments.${env}.security.csrf.enabled`,
|
|
||||||
null
|
|
||||||
),
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
name: 'form.security.item.csrf.key',
|
|
||||||
target: 'security.csrf.key',
|
|
||||||
type: 'string',
|
|
||||||
value: _.get(
|
|
||||||
strapi.config,
|
|
||||||
`environments.${env}.security.csrf.key`,
|
|
||||||
null
|
|
||||||
),
|
|
||||||
validations: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'form.security.item.csrf.secret',
|
|
||||||
target: 'security.csrf.secret',
|
|
||||||
type: 'string',
|
|
||||||
value: _.get(
|
|
||||||
strapi.config,
|
|
||||||
`environments.${env}.security.csrf.secret`,
|
|
||||||
null
|
|
||||||
),
|
|
||||||
validations: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'form.security.item.csrf.cookie',
|
|
||||||
target: 'security.csrf.cookie',
|
|
||||||
type: 'string',
|
|
||||||
value: _.get(
|
|
||||||
strapi.config,
|
|
||||||
`environments.${env}.security.csrf.cookie`,
|
|
||||||
null
|
|
||||||
),
|
|
||||||
validations: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'form.security.item.csrf.angular',
|
|
||||||
target: 'security.csrf.angular',
|
|
||||||
type: 'boolean',
|
|
||||||
value: _.get(
|
|
||||||
strapi.config,
|
|
||||||
`environments.${env}.security.csrf.angular`,
|
|
||||||
null
|
|
||||||
),
|
|
||||||
validations: {},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
validations: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'form.security.item.p3p',
|
name: 'form.security.item.p3p',
|
||||||
items: [
|
items: [
|
||||||
|
|||||||
@ -51,9 +51,7 @@ function* dataGet() {
|
|||||||
function* uploadFiles(action) {
|
function* uploadFiles(action) {
|
||||||
try {
|
try {
|
||||||
yield put(setLoading());
|
yield put(setLoading());
|
||||||
const headers = {
|
const headers = {};
|
||||||
'X-Forwarded-Host': 'strapi',
|
|
||||||
};
|
|
||||||
const response = yield call(
|
const response = yield call(
|
||||||
request,
|
request,
|
||||||
'/upload',
|
'/upload',
|
||||||
|
|||||||
@ -25,9 +25,17 @@ module.exports = {
|
|||||||
if (config.enabled === false) {
|
if (config.enabled === false) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
|
||||||
? [{ messages: [{ id: 'Upload.status.disabled' }] }]
|
[
|
||||||
: 'File upload is disabled'
|
{
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
id: 'Upload.status.disabled',
|
||||||
|
message: 'File upload is disabled',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,12 +44,11 @@ module.exports = {
|
|||||||
const { files = {} } = ctx.request.files || {};
|
const { files = {} } = ctx.request.files || {};
|
||||||
|
|
||||||
if (_.isEmpty(files)) {
|
if (_.isEmpty(files)) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(null, [
|
||||||
null,
|
{
|
||||||
ctx.request.admin
|
messages: [{ id: 'Upload.status.empty', message: 'Files are empty' }],
|
||||||
? [{ messages: [{ id: 'Upload.status.empty' }] }]
|
},
|
||||||
: 'Files are empty'
|
]);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform stream files to buffer
|
// Transform stream files to buffer
|
||||||
@ -49,21 +56,17 @@ module.exports = {
|
|||||||
|
|
||||||
const enhancedFiles = buffers.map(file => {
|
const enhancedFiles = buffers.map(file => {
|
||||||
if (file.size > config.sizeLimit) {
|
if (file.size > config.sizeLimit) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(null, [
|
||||||
null,
|
{
|
||||||
ctx.request.admin
|
messages: [
|
||||||
? [
|
{
|
||||||
{
|
id: 'Upload.status.sizeLimit',
|
||||||
messages: [
|
message: `${file.name} file is bigger than limit size!`,
|
||||||
{
|
values: { file: file.name },
|
||||||
id: 'Upload.status.sizeLimit',
|
},
|
||||||
values: { file: file.name },
|
],
|
||||||
},
|
},
|
||||||
],
|
]);
|
||||||
},
|
|
||||||
]
|
|
||||||
: `${file.name} file is bigger than limit size!`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add details to the file to be able to create the relationships.
|
// Add details to the file to be able to create the relationships.
|
||||||
|
|||||||
@ -153,7 +153,7 @@ describe('Upload plugin end to end tests', () => {
|
|||||||
|
|
||||||
expect(res.statusCode).toBe(400);
|
expect(res.statusCode).toBe(400);
|
||||||
expect(res.body).toMatchObject({
|
expect(res.body).toMatchObject({
|
||||||
message: 'File upload is disabled',
|
message: [{ messages: [{ message: 'File upload is disabled' }] }],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ describe('Upload plugin end to end tests', () => {
|
|||||||
|
|
||||||
expect(res.statusCode).toBe(400);
|
expect(res.statusCode).toBe(400);
|
||||||
expect(res.body).toMatchObject({
|
expect(res.body).toMatchObject({
|
||||||
message: 'Files are empty',
|
message: [{ messages: [{ message: 'Files are empty' }] }],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -181,7 +181,11 @@ describe('Upload plugin end to end tests', () => {
|
|||||||
|
|
||||||
expect(res.statusCode).toBe(400);
|
expect(res.statusCode).toBe(400);
|
||||||
expect(res.body).toMatchObject({
|
expect(res.body).toMatchObject({
|
||||||
message: 'rec.jpg file is bigger than limit size!',
|
message: [
|
||||||
|
{
|
||||||
|
messages: [{ message: 'rec.jpg file is bigger than limit size!' }],
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,9 +5,16 @@ const lazyRateLimit = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = async (ctx, next) => {
|
module.exports = async (ctx, next) => {
|
||||||
const message = ctx.request.admin
|
const message = [
|
||||||
? [{ messages: [{ id: 'Auth.form.error.ratelimit' }] }]
|
{
|
||||||
: 'Too many attempts, please try again in a minute.';
|
messages: [
|
||||||
|
{
|
||||||
|
id: 'Auth.form.error.ratelimit',
|
||||||
|
message: 'Too many attempts, please try again in a minute.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return lazyRateLimit.RateLimit.middleware(
|
return lazyRateLimit.RateLimit.middleware(
|
||||||
Object.assign(
|
Object.assign(
|
||||||
|
|||||||
@ -10,8 +10,12 @@
|
|||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const grant = require('grant-koa');
|
const grant = require('grant-koa');
|
||||||
|
const { sanitizeEntity } = require('strapi-utils');
|
||||||
|
|
||||||
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,}))$/;
|
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,}))$/;
|
||||||
|
const formatError = error => [
|
||||||
|
{ messages: [{ id: error.id, message: error.message, field: error.field }] },
|
||||||
|
];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
async callback(ctx) {
|
async callback(ctx) {
|
||||||
@ -25,10 +29,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (provider === 'local') {
|
if (provider === 'local') {
|
||||||
if (
|
if (!_.get(await store.get({ key: 'grant' }), 'email.enabled')) {
|
||||||
!_.get(await store.get({ key: 'grant' }), 'email.enabled') &&
|
|
||||||
!ctx.request.admin
|
|
||||||
) {
|
|
||||||
return ctx.badRequest(null, 'This provider is disabled.');
|
return ctx.badRequest(null, 'This provider is disabled.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,9 +37,10 @@ module.exports = {
|
|||||||
if (!params.identifier) {
|
if (!params.identifier) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }]
|
id: 'Auth.form.error.email.provide',
|
||||||
: 'Please provide your username or your e-mail.'
|
message: 'Please provide your username or your e-mail.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,9 +48,10 @@ module.exports = {
|
|||||||
if (!params.password) {
|
if (!params.password) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.password.provide' }] }]
|
id: 'Auth.form.error.password.provide',
|
||||||
: 'Please provide your password.'
|
message: 'Please provide your password.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,9 +75,10 @@ module.exports = {
|
|||||||
if (!user) {
|
if (!user) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.invalid' }] }]
|
id: 'Auth.form.error.invalid',
|
||||||
: 'Identifier or password invalid.'
|
message: 'Identifier or password invalid.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,18 +88,20 @@ module.exports = {
|
|||||||
) {
|
) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.confirmed' }] }]
|
id: 'Auth.form.error.confirmed',
|
||||||
: 'Your account email is not confirmed.'
|
message: 'Your account email is not confirmed',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.blocked === true) {
|
if (user.blocked === true) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.blocked' }] }]
|
id: 'Auth.form.error.blocked',
|
||||||
: 'Your account has been blocked by the administrator.'
|
message: 'Your account has been blocked by an administrator',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,9 +109,11 @@ module.exports = {
|
|||||||
if (!user.password) {
|
if (!user.password) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.password.local' }] }]
|
id: 'Auth.form.error.password.local',
|
||||||
: 'This user never set a local password, please login thanks to the provider used during account creation.'
|
message:
|
||||||
|
'This user never set a local password, please login thanks to the provider used during account creation.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,24 +124,30 @@ module.exports = {
|
|||||||
if (!validPassword) {
|
if (!validPassword) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.invalid' }] }]
|
id: 'Auth.form.error.invalid',
|
||||||
: 'Identifier or password invalid.'
|
message: 'Identifier or password invalid.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ctx.send({
|
ctx.send({
|
||||||
jwt: strapi.plugins['users-permissions'].services.jwt.issue({
|
jwt: strapi.plugins['users-permissions'].services.jwt.issue({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
}),
|
}),
|
||||||
user: _.omit(user.toJSON ? user.toJSON() : user, [
|
user: sanitizeEntity(user.toJSON ? user.toJSON() : user, {
|
||||||
'password',
|
model: strapi.query('user', 'users-permissions').model,
|
||||||
'resetPasswordToken',
|
}),
|
||||||
]),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!_.get(await store.get({ key: 'grant' }), [provider, 'enabled'])) {
|
if (!_.get(await store.get({ key: 'grant' }), [provider, 'enabled'])) {
|
||||||
return ctx.badRequest(null, 'This provider is disabled.');
|
return ctx.badRequest(
|
||||||
|
null,
|
||||||
|
formatError({
|
||||||
|
id: 'provider.disabled',
|
||||||
|
message: 'This provider is disabled.',
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect the user thanks to the third-party provider.
|
// Connect the user thanks to the third-party provider.
|
||||||
@ -143,27 +157,20 @@ module.exports = {
|
|||||||
'users-permissions'
|
'users-permissions'
|
||||||
].services.providers.connect(provider, ctx.query);
|
].services.providers.connect(provider, ctx.query);
|
||||||
} catch ([user, error]) {
|
} catch ([user, error]) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(null, error === 'array' ? error[0] : error);
|
||||||
null,
|
|
||||||
error === 'array' ? (ctx.request.admin ? error[0] : error[1]) : error
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(null, error === 'array' ? error[0] : error);
|
||||||
null,
|
|
||||||
error === 'array' ? (ctx.request.admin ? error[0] : error[1]) : error
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.send({
|
ctx.send({
|
||||||
jwt: strapi.plugins['users-permissions'].services.jwt.issue({
|
jwt: strapi.plugins['users-permissions'].services.jwt.issue({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
}),
|
}),
|
||||||
user: _.omit(user.toJSON ? user.toJSON() : user, [
|
user: sanitizeEntity(user.toJSON ? user.toJSON() : user, {
|
||||||
'password',
|
model: strapi.query('user', 'users-permissions').model,
|
||||||
'resetPasswordToken',
|
}),
|
||||||
]),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -184,9 +191,10 @@ module.exports = {
|
|||||||
if (!user) {
|
if (!user) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.code.provide' }] }]
|
id: 'Auth.form.error.code.provide',
|
||||||
: 'Incorrect code provided.'
|
message: 'Incorrect code provided.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,10 +214,9 @@ module.exports = {
|
|||||||
jwt: strapi.plugins['users-permissions'].services.jwt.issue({
|
jwt: strapi.plugins['users-permissions'].services.jwt.issue({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
}),
|
}),
|
||||||
user: _.omit(user.toJSON ? user.toJSON() : user, [
|
user: sanitizeEntity(user.toJSON ? user.toJSON() : user, {
|
||||||
'password',
|
model: strapi.query('user', 'users-permissions').model,
|
||||||
'resetPasswordToken',
|
}),
|
||||||
]),
|
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
params.password &&
|
params.password &&
|
||||||
@ -218,16 +225,18 @@ module.exports = {
|
|||||||
) {
|
) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.password.matching' }] }]
|
id: 'Auth.form.error.password.matching',
|
||||||
: 'Passwords do not match.'
|
message: 'Passwords do not match.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.params.provide' }] }]
|
id: 'Auth.form.error.params.provide',
|
||||||
: 'Incorrect params provided.'
|
message: 'Incorrect params provided.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -270,9 +279,10 @@ module.exports = {
|
|||||||
if (!user) {
|
if (!user) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.user.not-exist' }] }]
|
id: 'Auth.form.error.user.not-exist',
|
||||||
: 'This email does not exist.'
|
message: 'This email does not exist.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,9 +363,10 @@ module.exports = {
|
|||||||
if (!settings.allow_register) {
|
if (!settings.allow_register) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.advanced.allow_register' }] }]
|
id: 'Auth.advanced.allow_register',
|
||||||
: 'Register action is currently disabled.'
|
message: 'Register action is currently disabled.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,9 +378,10 @@ module.exports = {
|
|||||||
if (!params.password) {
|
if (!params.password) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.password.provide' }] }]
|
id: 'Auth.form.error.password.provide',
|
||||||
: 'Please provide your password.'
|
message: 'Please provide your password.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,9 +389,10 @@ module.exports = {
|
|||||||
if (!params.email) {
|
if (!params.email) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }]
|
id: 'Auth.form.error.email.provide',
|
||||||
: 'Please provide your email.'
|
message: 'Please provide your email.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,9 +405,11 @@ module.exports = {
|
|||||||
) {
|
) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.password.format' }] }]
|
id: 'Auth.form.error.password.format',
|
||||||
: 'Your password cannot contain more than three times the symbol `$`.'
|
message:
|
||||||
|
'Your password cannot contain more than three times the symbol `$`.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,9 +420,10 @@ module.exports = {
|
|||||||
if (!role) {
|
if (!role) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.role.notFound' }] }]
|
id: 'Auth.form.error.role.notFound',
|
||||||
: 'Impossible to find the default role.'
|
message: 'Impossible to find the default role.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,18 +446,20 @@ module.exports = {
|
|||||||
if (user && user.provider === params.provider) {
|
if (user && user.provider === params.provider) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.email.taken' }] }]
|
id: 'Auth.form.error.email.taken',
|
||||||
: 'Email is already taken.'
|
message: 'Email is already taken.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user && user.provider !== params.provider && settings.unique_email) {
|
if (user && user.provider !== params.provider && settings.unique_email) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? [{ messages: [{ id: 'Auth.form.error.email.taken' }] }]
|
id: 'Auth.form.error.email.taken',
|
||||||
: 'Email is already taken.'
|
message: 'Email is already taken.',
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,20 +533,19 @@ module.exports = {
|
|||||||
|
|
||||||
ctx.send({
|
ctx.send({
|
||||||
jwt,
|
jwt,
|
||||||
user: _.omit(user.toJSON ? user.toJSON() : user, [
|
user: sanitizeEntity(user.toJSON ? user.toJSON() : user, {
|
||||||
'password',
|
model: strapi.query('user', 'users-permissions').model,
|
||||||
'resetPasswordToken',
|
}),
|
||||||
]),
|
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const adminError = _.includes(err.message, 'username')
|
const adminError = _.includes(err.message, 'username')
|
||||||
? 'Auth.form.error.username.taken'
|
? {
|
||||||
: 'Auth.form.error.email.taken';
|
id: 'Auth.form.error.username.taken',
|
||||||
|
message: 'Username already taken',
|
||||||
|
}
|
||||||
|
: { id: 'Auth.form.error.email.taken', message: 'Email already taken' };
|
||||||
|
|
||||||
ctx.badRequest(
|
ctx.badRequest(null, formatError(adminError));
|
||||||
null,
|
|
||||||
ctx.request.admin ? [{ messages: [{ id: adminError }] }] : err.message
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const { sanitizeEntity } = require('strapi-utils');
|
||||||
|
|
||||||
const sanitizeUser = user => _.omit(user, ['password', 'resetPasswordToken']);
|
const sanitizeUser = user =>
|
||||||
const adminError = error => [
|
sanitizeEntity(user, {
|
||||||
{ messages: [{ id: error.message, field: error.field }] },
|
model: strapi.query('user', 'users-permissions').model,
|
||||||
|
});
|
||||||
|
|
||||||
|
const formatError = error => [
|
||||||
|
{ messages: [{ id: error.id, message: error.message, field: error.field }] },
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@ -99,12 +104,11 @@ module.exports = {
|
|||||||
if (userWithSameUsername) {
|
if (userWithSameUsername) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? adminError({
|
id: 'Auth.form.error.username.taken',
|
||||||
message: 'Auth.form.error.username.taken',
|
message: 'Username already taken.',
|
||||||
field: ['username'],
|
field: ['username'],
|
||||||
})
|
})
|
||||||
: 'username.alreadyTaken.'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,12 +120,12 @@ module.exports = {
|
|||||||
if (userWithSameEmail) {
|
if (userWithSameEmail) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
|
||||||
? adminError({
|
formatError({
|
||||||
message: 'Auth.form.error.email.taken',
|
id: 'Auth.form.error.email.taken',
|
||||||
field: ['email'],
|
message: 'Email already taken.',
|
||||||
})
|
field: ['email'],
|
||||||
: 'email.alreadyTaken'
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,10 +150,7 @@ module.exports = {
|
|||||||
|
|
||||||
ctx.created(data);
|
ctx.created(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.badRequest(
|
ctx.badRequest(null, formatError(error));
|
||||||
null,
|
|
||||||
ctx.request.admin ? adminError(error) : error.message
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -190,12 +191,11 @@ module.exports = {
|
|||||||
if (userWithSameUsername && userWithSameUsername.id != id) {
|
if (userWithSameUsername && userWithSameUsername.id != id) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? adminError({
|
id: 'Auth.form.error.username.taken',
|
||||||
message: 'Auth.form.error.username.taken',
|
message: 'username.alreadyTaken.',
|
||||||
field: ['username'],
|
field: ['username'],
|
||||||
})
|
})
|
||||||
: 'username.alreadyTaken.'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,12 +208,11 @@ module.exports = {
|
|||||||
if (userWithSameEmail && userWithSameEmail.id != id) {
|
if (userWithSameEmail && userWithSameEmail.id != id) {
|
||||||
return ctx.badRequest(
|
return ctx.badRequest(
|
||||||
null,
|
null,
|
||||||
ctx.request.admin
|
formatError({
|
||||||
? adminError({
|
id: 'Auth.form.error.email.taken',
|
||||||
message: 'Auth.form.error.email.taken',
|
message: 'Eamil already taken',
|
||||||
field: ['email'],
|
field: ['email'],
|
||||||
})
|
})
|
||||||
: 'email.alreadyTaken'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
const convertRestQueryParams = require('./convertRestQueryParams');
|
const convertRestQueryParams = require('./convertRestQueryParams');
|
||||||
const buildQuery = require('./buildQuery');
|
const buildQuery = require('./buildQuery');
|
||||||
|
const parseMultipartData = require('./parse-multipart');
|
||||||
|
const sanitizeEntity = require('./sanitize-entity');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
cli: require('./cli'),
|
cli: require('./cli'),
|
||||||
@ -21,4 +23,6 @@ module.exports = {
|
|||||||
templateConfiguration: require('./templateConfiguration'),
|
templateConfiguration: require('./templateConfiguration'),
|
||||||
convertRestQueryParams,
|
convertRestQueryParams,
|
||||||
buildQuery,
|
buildQuery,
|
||||||
|
parseMultipartData,
|
||||||
|
sanitizeEntity,
|
||||||
};
|
};
|
||||||
|
|||||||
38
packages/strapi-utils/lib/sanitize-entity.js
Normal file
38
packages/strapi-utils/lib/sanitize-entity.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = function sanitizeEntity(data, { model, withPrivate = false }) {
|
||||||
|
if (typeof data !== 'object' || data == null) return data;
|
||||||
|
|
||||||
|
let plainData = typeof data.toJSON === 'function' ? data.toJSON() : data;
|
||||||
|
|
||||||
|
const attributes = model.attributes;
|
||||||
|
return Object.keys(plainData).reduce((acc, key) => {
|
||||||
|
const attribute = attributes[key];
|
||||||
|
if (attribute && attribute.private === true && withPrivate !== true) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
attribute &&
|
||||||
|
(attribute.model || attribute.collection || attribute.type === 'group')
|
||||||
|
) {
|
||||||
|
const targetName =
|
||||||
|
attribute.model || attribute.collection || attribute.group;
|
||||||
|
|
||||||
|
const targetModel = strapi.getModel(targetName, attribute.plugin);
|
||||||
|
|
||||||
|
if (targetModel && plainData[key] !== null) {
|
||||||
|
acc[key] = Array.isArray(plainData[key])
|
||||||
|
? plainData[key].map(entity =>
|
||||||
|
sanitizeEntity(entity, { model: targetModel, withPrivate })
|
||||||
|
)
|
||||||
|
: sanitizeEntity(plainData[key], { model: targetModel, withPrivate });
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
acc[key] = plainData[key];
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
@ -1,17 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const parseMultipartData = require('./utils/parse-multipart');
|
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
|
||||||
|
|
||||||
const proto = {
|
|
||||||
parseMultipartData,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* default bookshelf controller
|
* default bookshelf controller
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
module.exports = ({ service }) => {
|
module.exports = ({ service, model }) => {
|
||||||
return Object.assign(Object.create(proto), {
|
return {
|
||||||
/**
|
/**
|
||||||
* expose some utils so the end users can use them
|
* expose some utils so the end users can use them
|
||||||
*/
|
*/
|
||||||
@ -22,11 +18,15 @@ module.exports = ({ service }) => {
|
|||||||
* @return {Object|Array}
|
* @return {Object|Array}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
find(ctx) {
|
async find(ctx) {
|
||||||
|
let entities;
|
||||||
if (ctx.query._q) {
|
if (ctx.query._q) {
|
||||||
return service.search(ctx.query);
|
entities = await service.search(ctx.query);
|
||||||
|
} else {
|
||||||
|
entities = await service.find(ctx.query);
|
||||||
}
|
}
|
||||||
return service.find(ctx.query);
|
|
||||||
|
return entities.map(entity => sanitizeEntity(entity, { model }));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,8 +35,9 @@ module.exports = ({ service }) => {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
findOne(ctx) {
|
async findOne(ctx) {
|
||||||
return service.findOne(ctx.params);
|
const entity = await service.findOne(ctx.params);
|
||||||
|
return sanitizeEntity(entity, { model });
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,13 +59,15 @@ module.exports = ({ service }) => {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create(ctx) {
|
async create(ctx) {
|
||||||
|
let entity;
|
||||||
if (ctx.is('multipart')) {
|
if (ctx.is('multipart')) {
|
||||||
const { data, files } = this.parseMultipartData(ctx);
|
const { data, files } = parseMultipartData(ctx);
|
||||||
return service.create(data, { files });
|
entity = await service.create(data, { files });
|
||||||
|
} else {
|
||||||
|
entity = await service.create(ctx.request.body);
|
||||||
}
|
}
|
||||||
|
return sanitizeEntity(entity, { model });
|
||||||
return service.create(ctx.request.body);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,13 +76,16 @@ module.exports = ({ service }) => {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
update(ctx) {
|
async update(ctx) {
|
||||||
|
let entity;
|
||||||
if (ctx.is('multipart')) {
|
if (ctx.is('multipart')) {
|
||||||
const { data, files } = this.parseMultipartData(ctx);
|
const { data, files } = parseMultipartData(ctx);
|
||||||
return service.update(ctx.params, data, { files });
|
entity = await service.update(ctx.params, data, { files });
|
||||||
|
} else {
|
||||||
|
entity = await service.update(ctx.params, ctx.request.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
return service.update(ctx.params, ctx.request.body);
|
return sanitizeEntity(entity, { model });
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,8 +94,9 @@ module.exports = ({ service }) => {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
delete(ctx) {
|
async delete(ctx) {
|
||||||
return service.delete(ctx.params);
|
const entity = await service.delete(ctx.params);
|
||||||
|
return sanitizeEntity(entity, { model });
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
6
packages/strapi/lib/core/bootstrap.js
vendored
6
packages/strapi/lib/core/bootstrap.js
vendored
@ -77,7 +77,7 @@ module.exports = function(strapi) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const controller = Object.assign(
|
const controller = Object.assign(
|
||||||
createController({ service }),
|
createController({ service, model }),
|
||||||
userController,
|
userController,
|
||||||
{ identity: userController.identity || _.upperFirst(index) }
|
{ identity: userController.identity || _.upperFirst(index) }
|
||||||
);
|
);
|
||||||
@ -209,10 +209,6 @@ module.exports = function(strapi) {
|
|||||||
boom: {
|
boom: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
mask: {
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
// Necessary middlewares for the administration panel.
|
|
||||||
cors: {
|
cors: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -10,13 +10,7 @@ const defaults = {
|
|||||||
maxAge: 31536000,
|
maxAge: 31536000,
|
||||||
credentials: true,
|
credentials: true,
|
||||||
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
|
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
|
||||||
headers: [
|
headers: ['Content-Type', 'Authorization', 'Origin', 'Accept'],
|
||||||
'Content-Type',
|
|
||||||
'Authorization',
|
|
||||||
'Origin',
|
|
||||||
'Accept',
|
|
||||||
'X-Forwarded-Host',
|
|
||||||
],
|
|
||||||
keepHeadersOnError: false,
|
keepHeadersOnError: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"csrf": {
|
|
||||||
"enabled": false,
|
|
||||||
"key": "_csrf",
|
|
||||||
"secret": "_csrfSecret"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
const convert = require('koa-convert');
|
|
||||||
const { csrf } = require('koa-lusca');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CSRF hook
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = strapi => {
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Initialize the hook
|
|
||||||
*/
|
|
||||||
|
|
||||||
initialize() {
|
|
||||||
strapi.app.use(async (ctx, next) => {
|
|
||||||
if (ctx.request.admin) return await next();
|
|
||||||
|
|
||||||
return await convert(csrf(strapi.config.middleware.settings.csrf))(
|
|
||||||
ctx,
|
|
||||||
next
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -3,17 +3,6 @@
|
|||||||
const { uniq, difference, get, isUndefined, merge } = require('lodash');
|
const { uniq, difference, get, isUndefined, merge } = require('lodash');
|
||||||
|
|
||||||
module.exports = async function() {
|
module.exports = async function() {
|
||||||
// Set if is admin destination for middleware application.
|
|
||||||
this.app.use(async (ctx, next) => {
|
|
||||||
if (ctx.request.header['origin'] === 'http://localhost:4000') {
|
|
||||||
ctx.request.header['x-forwarded-host'] = 'strapi';
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.request.admin = ctx.request.header['x-forwarded-host'] === 'strapi';
|
|
||||||
|
|
||||||
await next();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** Utils */
|
/** Utils */
|
||||||
|
|
||||||
const middlewareConfig = this.config.middleware;
|
const middlewareConfig = this.config.middleware;
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"mask": {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,189 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask filter middleware
|
|
||||||
*/
|
|
||||||
|
|
||||||
const _ = require('lodash');
|
|
||||||
|
|
||||||
module.exports = strapi => {
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Initialize the hook
|
|
||||||
*/
|
|
||||||
|
|
||||||
initialize() {
|
|
||||||
// Enable the middleware if we need it.
|
|
||||||
const enabled = (() => {
|
|
||||||
const main = Object.keys(strapi.models).reduce((acc, current) => {
|
|
||||||
if (
|
|
||||||
Object.values(strapi.models[current].attributes).find(
|
|
||||||
attr => attr.private === true
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
acc = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
const plugins = Object.keys(strapi.plugins).reduce((acc, plugin) => {
|
|
||||||
const bool = Object.keys(strapi.plugins[plugin].models).reduce(
|
|
||||||
(acc, model) => {
|
|
||||||
if (
|
|
||||||
Object.values(
|
|
||||||
strapi.plugins[plugin].models[model].attributes
|
|
||||||
).find(attr => attr.private === true)
|
|
||||||
) {
|
|
||||||
acc = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
if (bool) {
|
|
||||||
acc = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
return main || plugins;
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
strapi.app.use(async (ctx, next) => {
|
|
||||||
// Execute next middleware.
|
|
||||||
await next();
|
|
||||||
|
|
||||||
// Recursive to mask the private properties.
|
|
||||||
const mask = payload => {
|
|
||||||
// Handle ORM toJSON() method to work on real JSON object.
|
|
||||||
payload = payload && payload.toJSON ? payload.toJSON() : payload;
|
|
||||||
|
|
||||||
if (_.isArray(payload)) {
|
|
||||||
return payload.map(mask);
|
|
||||||
} else if (_.isPlainObject(payload)) {
|
|
||||||
return this.mask(
|
|
||||||
ctx,
|
|
||||||
Object.keys(payload).reduce((acc, current) => {
|
|
||||||
acc[current] = _.isObjectLike(payload[current])
|
|
||||||
? mask(payload[current])
|
|
||||||
: payload[current];
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, {})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return payload;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Only pick successful JSON requests.
|
|
||||||
if (
|
|
||||||
[200, 201, 202].includes(ctx.status) &&
|
|
||||||
ctx.type === 'application/json' &&
|
|
||||||
!ctx.request.admin
|
|
||||||
) {
|
|
||||||
ctx.body = mask(ctx.body);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mask(ctx, value) {
|
|
||||||
const models = this.filteredModels(
|
|
||||||
this.whichModels(value, ctx.request.route.plugin)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (models.length === 0) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const attributesToHide = models.reduce((acc, match) => {
|
|
||||||
const attributes = match.plugin
|
|
||||||
? strapi.plugins[match.plugin].models[match.model].attributes
|
|
||||||
: strapi.models[match.model].attributes;
|
|
||||||
|
|
||||||
acc = acc.concat(
|
|
||||||
Object.keys(attributes).filter(
|
|
||||||
attr => attributes[attr].private === true
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Hide attribute.
|
|
||||||
return _.omit(value, attributesToHide);
|
|
||||||
},
|
|
||||||
|
|
||||||
whichModels(value) {
|
|
||||||
const keys = Object.keys(value);
|
|
||||||
let maxMatch = 0;
|
|
||||||
let matchs = [];
|
|
||||||
|
|
||||||
const match = (model, plugin) => {
|
|
||||||
const attributes = plugin
|
|
||||||
? Object.keys(strapi.plugins[plugin].models[model].attributes)
|
|
||||||
: Object.keys(strapi.models[model].attributes);
|
|
||||||
|
|
||||||
const intersection = _.intersection(
|
|
||||||
keys,
|
|
||||||
attributes.filter(attr => ['id', '_id', '_v'].indexOf(attr) === -1)
|
|
||||||
).length;
|
|
||||||
|
|
||||||
// Most matched model.
|
|
||||||
if (intersection > maxMatch) {
|
|
||||||
maxMatch = intersection;
|
|
||||||
matchs = [
|
|
||||||
{
|
|
||||||
plugin,
|
|
||||||
model,
|
|
||||||
intersection,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
} else if (intersection === maxMatch && intersection > 0) {
|
|
||||||
matchs.push({
|
|
||||||
plugin,
|
|
||||||
model,
|
|
||||||
intersection,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Application models.
|
|
||||||
Object.keys(strapi.models).forEach(model => match(model));
|
|
||||||
// Plugins models.
|
|
||||||
Object.keys(strapi.plugins).forEach(plugin => {
|
|
||||||
Object.keys(strapi.plugins[plugin].models).forEach(model =>
|
|
||||||
match(model, plugin)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return matchs;
|
|
||||||
},
|
|
||||||
|
|
||||||
filteredModels(matchs) {
|
|
||||||
return matchs.reduce((acc, match, index) => {
|
|
||||||
const attributes = match.plugin
|
|
||||||
? strapi.plugins[match.plugin].models[match.model].attributes
|
|
||||||
: strapi.models[match.model].attributes;
|
|
||||||
|
|
||||||
// Filtered model which have more than 50% of the attributes
|
|
||||||
// in common with the original model.
|
|
||||||
if (match.intersection >= Object.keys(attributes).length / 2) {
|
|
||||||
acc[index] = match;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Loading…
x
Reference in New Issue
Block a user