diff --git a/README.md b/README.md index 58a055d333..d897513555 100644 --- a/README.md +++ b/README.md @@ -97,11 +97,11 @@ This project is currently in **Beta**. Significant breaking changes are unlikely ## Features -- **Modern Admin Panel:** Elegant, entirely customizable, and a fully extensible admin panel. -- **Secure by default:** Reusable policies, CSRF, CORS, P3P, Xframe, XSS, and more. -- **Plugins Oriented:** Install auth systems, content management, custom plugins, and more, in seconds. -- **Blazing Fast:** Built on top of Node.js, Strapi delivers impressive performance. -- **Front-end Agnostic:** Use any front-end framework, for example, React, Vue, Angular, mobile apps, or even IoT. +- **Modern Admin Panel:** Elegant, entirely customizable and a fully extensible admin panel. +- **Secure by default:** Reusable policies, CORS, CSP, P3P, Xframe, XSS, and more. +- **Plugins Oriented:** Install auth system, content management, custom plugins, and more, in seconds. +- **Blazing Fast:** Built on top of Node.js, Strapi delivers amazing performance. +- **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. - **SQL & NoSQL databases:** Works with MongoDB, PostgreSQL, MySQL, MariaDB, and SQLite. diff --git a/docs/3.0.0-beta.x/advanced/middlewares.md b/docs/3.0.0-beta.x/advanced/middlewares.md index 1119e38146..9db2b7b514 100644 --- a/docs/3.0.0-beta.x/advanced/middlewares.md +++ b/docs/3.0.0-beta.x/advanced/middlewares.md @@ -44,7 +44,6 @@ The core of Strapi embraces a small list of middlewares for performances, securi - cors - cron - csp -- csrf - favicon - gzip - hsts diff --git a/docs/3.0.0-beta.x/configurations/configurations.md b/docs/3.0.0-beta.x/configurations/configurations.md index 2bf143c9cb..6aa2a7b062 100644 --- a/docs/3.0.0-beta.x/configurations/configurations.md +++ b/docs/3.0.0-beta.x/configurations/configurations.md @@ -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`. -- [`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) - `enabled` (boolean): Enable or disable CSP to avoid Cross Site Scripting (XSS) and data injection attacks. - [`p3p`](https://en.wikipedia.org/wiki/P3P) diff --git a/docs/3.0.0-beta.x/guides/controllers.md b/docs/3.0.0-beta.x/guides/controllers.md index 19e974407e..789c65cd1b 100644 --- a/docs/3.0.0-beta.x/guides/controllers.md +++ b/docs/3.0.0-beta.x/guides/controllers.md @@ -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` ::: +#### 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` ```js @@ -25,11 +36,15 @@ module.exports = { * @return {Array} */ - find(ctx) { + async find(ctx) { + let entities; 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} */ - findOne(ctx) { - return strapi.services.product.findOne(ctx.params); + async findOne(ctx) { + const entity = await service.findOne(ctx.params); + return sanitizeEntity(entity, { model }); }, }; ``` @@ -62,9 +78,9 @@ module.exports = { count(ctx) { 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} */ - create(ctx) { + async create(ctx) { + let entity; if (ctx.is('multipart')) { - // Parses strapi's formData format - const { data, files } = this.parseMultipartData(ctx); - return service.create(data, { files }); + const { data, files } = parseMultipartData(ctx); + entity = await service.create(data, { files }); + } else { + entity = await service.create(ctx.request.body); } - - return service.create(ctx.request.body); + return sanitizeEntity(entity, { model }); }, }; ``` @@ -101,14 +118,16 @@ module.exports = { * @return {Object} */ - update(ctx) { + async update(ctx) { + let entity; if (ctx.is('multipart')) { - // Parses strapi's formData format - const { data, files } = this.parseMultipartData(ctx); - return service.update(ctx.params, data, { files }); + const { data, files } = parseMultipartData(ctx); + 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 }); }, }; ``` @@ -123,8 +142,9 @@ module.exports = { * @return {Object} */ - delete(ctx) { - return strapi.services.product.delete(ctx.params); + async delete(ctx) { + const entity = await service.delete(ctx.params); + return sanitizeEntity(entity, { model }); }, }; ``` diff --git a/examples/getstarted/config/environments/development/security.json b/examples/getstarted/config/environments/development/security.json index c7af37b8e6..5f20791e63 100644 --- a/examples/getstarted/config/environments/development/security.json +++ b/examples/getstarted/config/environments/development/security.json @@ -1,30 +1,28 @@ { - "csrf": { - "enabled": false, - "key": "_csrf", - "secret": "_csrfSecret" - }, "csp": { - "enabled": false, - "policy": { - "default-src": "'self'" - } + "enabled": true, + "policy": [ + { + "img-src": "'self' http:" + }, + "block-all-mixed-content" + ] }, "p3p": { "enabled": false, "value": "" }, "hsts": { - "enabled": false, + "enabled": true, "maxAge": 31536000, "includeSubDomains": true }, "xframe": { - "enabled": false, + "enabled": true, "value": "SAMEORIGIN" }, "xss": { - "enabled": false, + "enabled": true, "mode": "block" }, "cors": { diff --git a/examples/getstarted/config/environments/production/security.json b/examples/getstarted/config/environments/production/security.json index 9d0441d26f..860df3d5f8 100644 --- a/examples/getstarted/config/environments/production/security.json +++ b/examples/getstarted/config/environments/production/security.json @@ -1,9 +1,4 @@ { - "csrf": { - "enabled": false, - "key": "_csrf", - "secret": "_csrfSecret" - }, "csp": { "enabled": true, "policy": [ diff --git a/examples/getstarted/config/environments/staging/security.json b/examples/getstarted/config/environments/staging/security.json index 9d0441d26f..860df3d5f8 100644 --- a/examples/getstarted/config/environments/staging/security.json +++ b/examples/getstarted/config/environments/staging/security.json @@ -1,9 +1,4 @@ { - "csrf": { - "enabled": false, - "key": "_csrf", - "secret": "_csrfSecret" - }, "csp": { "enabled": true, "policy": [ diff --git a/packages/strapi-admin/controllers/Admin.js b/packages/strapi-admin/controllers/Admin.js index fd247cf5d0..c6bbd5edf3 100644 --- a/packages/strapi-admin/controllers/Admin.js +++ b/packages/strapi-admin/controllers/Admin.js @@ -3,6 +3,10 @@ const execa = require('execa'); const _ = require('lodash'); +const formatError = error => [ + { messages: [{ id: error.id, message: error.message, field: error.field }] }, +]; + /** * A set of functions called "actions" for `Admin` */ @@ -121,9 +125,38 @@ module.exports = { async create(ctx) { const { email, username, password, blocked } = ctx.request.body; - if (!email) return ctx.badRequest('missing.email'); - if (!username) return ctx.badRequest('missing.username'); - if (!password) return ctx.badRequest('missing.password'); + if (!email) { + return ctx.badRequest( + 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 .query('administrator', 'admin') @@ -136,33 +169,22 @@ module.exports = { if (adminsWithSameEmail) { return ctx.badRequest( null, - ctx.request.admin - ? [ - { - messages: [ - { id: 'Auth.form.error.email.taken', field: ['email'] }, - ], - }, - ] - : 'email.alreadyTaken' + formatError({ + id: 'Auth.form.error.email.taken', + message: 'Email already taken', + field: ['email'], + }) ); } if (adminsWithSameUsername) { return ctx.badRequest( null, - ctx.request.admin - ? [ - { - messages: [ - { - id: 'Auth.form.error.username.taken', - field: ['username'], - }, - ], - }, - ] - : 'username.alreadyTaken.' + formatError({ + id: 'Auth.form.error.username.taken', + message: 'Username already taken', + field: ['username'], + }) ); } @@ -189,10 +211,38 @@ module.exports = { const { id } = ctx.params; const { email, username, password, blocked } = ctx.request.body; - if (!email) return ctx.badRequest('Missing email'); - if (!username) return ctx.badRequest('Missing username'); - if (!password) return ctx.badRequest('Missing password'); + if (!email) { + return ctx.badRequest( + 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 .query('administrator', 'admin') .findOne(ctx.params); @@ -209,15 +259,11 @@ module.exports = { if (adminsWithSameEmail && adminsWithSameEmail.id !== admin.id) { return ctx.badRequest( null, - ctx.request.admin - ? [ - { - messages: [ - { id: 'Auth.form.error.email.taken', field: ['email'] }, - ], - }, - ] - : 'Email is already taken.' + formatError({ + id: 'Auth.form.error.email.taken', + message: 'Email already taken', + field: ['email'], + }) ); } } @@ -231,18 +277,11 @@ module.exports = { if (adminsWithSameUsername && adminsWithSameUsername.id !== admin.id) { return ctx.badRequest( null, - ctx.request.admin - ? [ - { - messages: [ - { - id: 'Auth.form.error.username.taken', - field: ['username'], - }, - ], - }, - ] - : 'Username is already taken.' + formatError({ + id: 'Auth.form.error.username.taken', + message: 'Username already taken', + field: ['username'], + }) ); } } diff --git a/packages/strapi-admin/controllers/Auth.js b/packages/strapi-admin/controllers/Auth.js index 381ff816f2..82d24f01e6 100644 --- a/packages/strapi-admin/controllers/Auth.js +++ b/packages/strapi-admin/controllers/Auth.js @@ -11,6 +11,9 @@ const crypto = require('crypto'); const _ = require('lodash'); const emailRegExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; +const formatError = error => [ + { messages: [{ id: error.id, message: error.message, field: error.field }] }, +]; module.exports = { async callback(ctx) { @@ -20,9 +23,10 @@ module.exports = { if (!params.identifier) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }] - : 'Please provide your username or your e-mail.' + formatError({ + id: 'Auth.form.error.email.provide', + message: 'Please provide your username or your e-mail.', + }) ); } @@ -30,9 +34,10 @@ module.exports = { if (!params.password) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.password.provide' }] }] - : 'Please provide your password.' + formatError({ + id: 'Auth.form.error.password.provide', + message: 'Please provide your password.', + }) ); } @@ -54,18 +59,20 @@ module.exports = { if (!admin) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.invalid' }] }] - : 'Identifier or password invalid.' + formatError({ + id: 'Auth.form.error.invalid', + message: 'Identifier or password invalid.', + }) ); } if (admin.blocked === true) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.blocked' }] }] - : 'Your account has been blocked by the administrator.' + formatError({ + id: 'Auth.form.error.blocked', + message: 'Your account has been blocked by the administrator.', + }) ); } @@ -77,9 +84,10 @@ module.exports = { if (!validPassword) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.invalid' }] }] - : 'Identifier or password invalid.' + formatError({ + id: 'Auth.form.error.invalid', + message: 'Identifier or password invalid.', + }) ); } else { admin.isAdmin = true; @@ -98,9 +106,10 @@ module.exports = { if (!params.username) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.username.provide' }] }] - : 'Please provide your username.' + formatError({ + id: 'Auth.form.error.username.provide', + message: 'Please provide your username.', + }) ); } @@ -108,9 +117,10 @@ module.exports = { if (!params.email) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }] - : 'Please provide your email.' + formatError({ + id: 'Auth.form.error.email.provide', + message: 'Please provide your email.', + }) ); } @@ -127,9 +137,10 @@ module.exports = { if (!params.password) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.password.provide' }] }] - : 'Please provide your password.' + formatError({ + id: 'Auth.form.error.password.provide', + message: 'Please provide your password.', + }) ); } @@ -141,9 +152,10 @@ module.exports = { if (admins.length > 0) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.admin.exist' }] }] - : "You can't register a new admin." + formatError({ + id: 'Auth.form.error.admin.exist', + message: "You can't register a new admin", + }) ); } @@ -158,9 +170,10 @@ module.exports = { if (admin) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.email.taken' }] }] - : 'Email is already taken.' + formatError({ + id: 'Auth.form.error.email.taken', + message: 'Email is already taken', + }) ); } @@ -180,13 +193,13 @@ module.exports = { } catch (err) { strapi.log.error(err); 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( - null, - ctx.request.admin ? [{ messages: [{ id: adminError }] }] : err.message - ); + ctx.badRequest(null, formatError(adminError)); } }, @@ -196,17 +209,42 @@ module.exports = { ...ctx.params, }; - if (!password) return ctx.badRequest('Missing password'); - if (!passwordConfirmation) - return ctx.badRequest('Missing passwordConfirmation'); - if (!code) return ctx.badRequest('Missing code'); + if (!password) { + return ctx.badRequest( + null, + 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) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.password.matching' }] }] - : 'Passwords do not match.' + formatError({ + id: 'Auth.form.error.password.matching', + message: 'Passwords do not match.', + }) ); } @@ -217,9 +255,10 @@ module.exports = { if (!admin) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.code.provide' }] }] - : 'Incorrect code provided.' + formatError({ + id: 'Auth.form.error.code.provide', + message: 'Incorrect code provided.', + }) ); } @@ -241,8 +280,24 @@ module.exports = { async forgotPassword(ctx) { const { email, url } = ctx.request.body; - if (!email) return ctx.badRequest('Missing email'); - if (!url) return ctx.badRequest('Missing url'); + if (!email) { + 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. const admin = await strapi @@ -253,9 +308,10 @@ module.exports = { if (!admin) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.user.not-exist' }] }] - : 'This email does not exist.' + formatError({ + id: 'Auth.form.error.user.not-exist', + message: 'This email does not exit', + }) ); } diff --git a/packages/strapi-generate-new/lib/resources/files/config/environments/development/security.json b/packages/strapi-generate-new/lib/resources/files/config/environments/development/security.json index c7af37b8e6..5f20791e63 100644 --- a/packages/strapi-generate-new/lib/resources/files/config/environments/development/security.json +++ b/packages/strapi-generate-new/lib/resources/files/config/environments/development/security.json @@ -1,30 +1,28 @@ { - "csrf": { - "enabled": false, - "key": "_csrf", - "secret": "_csrfSecret" - }, "csp": { - "enabled": false, - "policy": { - "default-src": "'self'" - } + "enabled": true, + "policy": [ + { + "img-src": "'self' http:" + }, + "block-all-mixed-content" + ] }, "p3p": { "enabled": false, "value": "" }, "hsts": { - "enabled": false, + "enabled": true, "maxAge": 31536000, "includeSubDomains": true }, "xframe": { - "enabled": false, + "enabled": true, "value": "SAMEORIGIN" }, "xss": { - "enabled": false, + "enabled": true, "mode": "block" }, "cors": { diff --git a/packages/strapi-generate-new/lib/resources/files/config/environments/production/security.json b/packages/strapi-generate-new/lib/resources/files/config/environments/production/security.json index 9d0441d26f..860df3d5f8 100644 --- a/packages/strapi-generate-new/lib/resources/files/config/environments/production/security.json +++ b/packages/strapi-generate-new/lib/resources/files/config/environments/production/security.json @@ -1,9 +1,4 @@ { - "csrf": { - "enabled": false, - "key": "_csrf", - "secret": "_csrfSecret" - }, "csp": { "enabled": true, "policy": [ diff --git a/packages/strapi-generate-new/lib/resources/files/config/environments/staging/security.json b/packages/strapi-generate-new/lib/resources/files/config/environments/staging/security.json index 9d0441d26f..860df3d5f8 100644 --- a/packages/strapi-generate-new/lib/resources/files/config/environments/staging/security.json +++ b/packages/strapi-generate-new/lib/resources/files/config/environments/staging/security.json @@ -1,9 +1,4 @@ { - "csrf": { - "enabled": false, - "key": "_csrf", - "secret": "_csrfSecret" - }, "csp": { "enabled": true, "policy": [ diff --git a/packages/strapi-helper-plugin/lib/src/utils/request.js b/packages/strapi-helper-plugin/lib/src/utils/request.js index 04e0b89942..bc22bc3360 100644 --- a/packages/strapi-helper-plugin/lib/src/utils/request.js +++ b/packages/strapi-helper-plugin/lib/src/utils/request.js @@ -135,10 +135,7 @@ export default function request(...args) { { 'Content-Type': 'application/json', }, - options.headers, - { - 'X-Forwarded-Host': 'strapi', - } + options.headers ); } diff --git a/packages/strapi-hook-bookshelf/lib/queries.js b/packages/strapi-hook-bookshelf/lib/queries.js index 4df9998295..cad6b08f1d 100644 --- a/packages/strapi-hook-bookshelf/lib/queries.js +++ b/packages/strapi-hook-bookshelf/lib/queries.js @@ -178,7 +178,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) { const runDelete = async trx => { await deleteGroups(entry, { transacting: trx }); await model.forge(params).destroy({ transacting: trx, require: false }); - return entry; + return entry.toJSON(); }; return wrapTransaction(runDelete, { transacting }); @@ -217,7 +217,8 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) { }) .fetchAll({ withRelated: populate, - }); + }) + .then(results => results.toJSON()); } function countSearch(params) { diff --git a/packages/strapi-hook-mongoose/lib/queries.js b/packages/strapi-hook-mongoose/lib/queries.js index 9279fac51b..283e2f2981 100644 --- a/packages/strapi-hook-mongoose/lib/queries.js +++ b/packages/strapi-hook-mongoose/lib/queries.js @@ -199,9 +199,9 @@ module.exports = ({ model, modelKey, strapi }) => { model, filters, populate: populateOpt, - }).then(results => { - return results.map(result => (result ? result.toObject() : null)); - }); + }).then(results => + results.map(result => (result ? result.toObject() : null)) + ); } 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) { @@ -340,7 +340,10 @@ module.exports = ({ model, modelKey, strapi }) => { .sort(filters.sort) .skip(filters.start) .limit(filters.limit) - .populate(populate || defaultPopulate); + .populate(populate || defaultPopulate) + .then(results => + results.map(result => (result ? result.toObject() : null)) + ); } function countSearch(params) { diff --git a/packages/strapi-plugin-content-manager/admin/src/components/Wysiwyg/index.js b/packages/strapi-plugin-content-manager/admin/src/components/Wysiwyg/index.js index 4399f60669..a4c98faf1c 100644 --- a/packages/strapi-plugin-content-manager/admin/src/components/Wysiwyg/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/components/Wysiwyg/index.js @@ -673,9 +673,7 @@ class Wysiwyg extends React.Component { uploadFile = files => { const formData = new FormData(); formData.append('files', files[0]); - const headers = { - 'X-Forwarded-Host': 'strapi', - }; + const headers = {}; let newEditorState = this.getEditorState(); diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/EditView/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/EditView/index.js index 1b5ef6d5e5..522537a067 100644 --- a/packages/strapi-plugin-content-manager/admin/src/containers/EditView/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/EditView/index.js @@ -265,7 +265,7 @@ function EditView({ }); // 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 endPoint = isCreatingEntry ? slug : `${slug}/${id}`; diff --git a/packages/strapi-plugin-content-manager/controllers/ContentManager.js b/packages/strapi-plugin-content-manager/controllers/ContentManager.js index 1fe153dd5c..d0ed6c40b3 100644 --- a/packages/strapi-plugin-content-manager/controllers/ContentManager.js +++ b/packages/strapi-plugin-content-manager/controllers/ContentManager.js @@ -95,12 +95,13 @@ module.exports = { strapi.emit('didCreateFirstContentTypeEntry', ctx.params, source); } catch (error) { strapi.log.error(error); - ctx.badRequest( - null, - ctx.request.admin - ? [{ messages: [{ id: error.message, field: error.field }] }] - : error.message - ); + ctx.badRequest(null, [ + { + messages: [ + { id: error.message, message: error.message, field: error.field }, + ], + }, + ]); } }, @@ -131,12 +132,13 @@ module.exports = { } } catch (error) { strapi.log.error(error); - ctx.badRequest( - null, - ctx.request.admin - ? [{ messages: [{ id: error.message, field: error.field }] }] - : error.message - ); + ctx.badRequest(null, [ + { + messages: [ + { id: error.message, message: error.message, field: error.field }, + ], + }, + ]); } }, diff --git a/packages/strapi-plugin-email/controllers/Email.js b/packages/strapi-plugin-email/controllers/Email.js index baf3e588fb..ebdd0ae731 100644 --- a/packages/strapi-plugin-email/controllers/Email.js +++ b/packages/strapi-plugin-email/controllers/Email.js @@ -9,18 +9,26 @@ const _ = require('lodash'); module.exports = { - send: async (ctx) => { + send: async ctx => { // Retrieve provider configuration. - const config = await strapi.store({ - environment: strapi.config.environment, - type: 'plugin', - name: 'email' - }).get({ key: 'provider' }); + const config = await strapi + .store({ + environment: strapi.config.environment, + type: 'plugin', + name: 'email', + }) + .get({ key: 'provider' }); // Verify if the file email is enable. if (config.enabled === false) { 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 @@ -36,33 +44,40 @@ module.exports = { ctx.send({}); }, - getEnvironments: async (ctx) => { - const environments = _.map(_.keys(strapi.config.environments), environment => { - return { - name: environment, - active: (strapi.config.environment === environment) - }; - }); + getEnvironments: async ctx => { + const environments = _.map( + _.keys(strapi.config.environments), + environment => { + return { + name: environment, + active: strapi.config.environment === environment, + }; + } + ); ctx.send({ environments }); }, - getSettings: async (ctx) => { - let config = await strapi.plugins.email.services.email.getProviderConfig(ctx.params.environment); + getSettings: async ctx => { + let config = await strapi.plugins.email.services.email.getProviderConfig( + ctx.params.environment + ); ctx.send({ providers: strapi.plugins.email.config.providers, - config + config, }); }, - updateSettings: async (ctx) => { - await strapi.store({ - environment: ctx.params.environment, - type: 'plugin', - name: 'email' - }).set({key: 'provider', value: ctx.request.body}); + updateSettings: async ctx => { + await strapi + .store({ + environment: ctx.params.environment, + type: 'plugin', + name: 'email', + }) + .set({ key: 'provider', value: ctx.request.body }); - ctx.send({ok: true}); + ctx.send({ ok: true }); }, }; diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/ar.json b/packages/strapi-plugin-settings-manager/admin/src/translations/ar.json index a11dc0c92f..74d52fbe29 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/ar.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/ar.json @@ -54,11 +54,6 @@ "form.security.description": "تكوين إعدادات الأمان الخاصة بك.", "form.security.item.cors": "Cors", "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.includeSubDomains": "تضمين المجال الفرعي", "form.security.item.hsts.maxAge": "أقصى عمر", @@ -629,4 +624,4 @@ "strapi.notification.success.languageAdd": "تمت إضافة اللغة بنجاح.", "strapi.notification.success.languageDelete": "تم حذف اللغة بنجاح.", "strapi.notification.success.settingsEdit": "تم تحديث الإعدادات بنجاح." -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/de.json b/packages/strapi-plugin-settings-manager/admin/src/translations/de.json index 2a9237dca2..adc439a09d 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/de.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/de.json @@ -54,11 +54,6 @@ "form.security.description": "Verwalte deine Sicherheitseinstellungen.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Subdomain mit einschließen", "form.security.item.hsts.maxAge": "Max Age", diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/en.json b/packages/strapi-plugin-settings-manager/admin/src/translations/en.json index c59ea32c8d..7a7484ba73 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/en.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/en.json @@ -54,11 +54,6 @@ "form.security.description": "Configure your security settings.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Include Sub Domain", "form.security.item.hsts.maxAge": "Max Age", diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/es.json b/packages/strapi-plugin-settings-manager/admin/src/translations/es.json index 317e05d386..e345e84ee7 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/es.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/es.json @@ -54,11 +54,6 @@ "form.security.description": "Configurar las opciones de seguridad.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Incluir Sub Dominio", "form.security.item.hsts.maxAge": "Edad Máxima", diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/fr.json b/packages/strapi-plugin-settings-manager/admin/src/translations/fr.json index 432e13dca1..13655c4cfb 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/fr.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/fr.json @@ -54,12 +54,6 @@ "form.security.description": "Configurations de sécurité.", "form.security.item.cors": "Cors", "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.maxAge": "Max Age", "form.security.item.hsts.preload": "Preload", diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/it.json b/packages/strapi-plugin-settings-manager/admin/src/translations/it.json index d95c60bb28..ec9a07699d 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/it.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/it.json @@ -54,11 +54,6 @@ "form.security.description": "Configurare le impostazioni di sicurezza.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Includi domini secondari", "form.security.item.hsts.maxAge": "Età Max", @@ -629,4 +624,4 @@ "strapi.notification.success.languageAdd": "Il linguaggio è stato aggiunto con successo.", "strapi.notification.success.languageDelete": "Il linguaggio è stato eliminato con successo.", "strapi.notification.success.settingsEdit": "Le impostazioni sono state aggiornate con successo." -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/ja.json b/packages/strapi-plugin-settings-manager/admin/src/translations/ja.json index f325087887..43af9fd02e 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/ja.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/ja.json @@ -54,11 +54,6 @@ "form.security.description": "セキュリティ設定を構成します。", "form.security.item.cors": "Cors", "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.includeSubDomains": "サブドメインを含める", "form.security.item.hsts.maxAge": "Max Age", diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/ko.json b/packages/strapi-plugin-settings-manager/admin/src/translations/ko.json index 3b77193a83..10d120ccb3 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/ko.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/ko.json @@ -54,11 +54,6 @@ "form.security.description": "보안 환경을 설정하세요.", "form.security.item.cors": "Cors", "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.includeSubDomains": "서브 도메인 포함", "form.security.item.hsts.maxAge": "만료 (Max Age)", @@ -629,4 +624,4 @@ "strapi.notification.success.languageAdd": "언어를 추가했습니다.", "strapi.notification.success.languageDelete": "언어를 제거했습니다.", "strapi.notification.success.settingsEdit": "설정을 업데이트했습니다." -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/nl.json b/packages/strapi-plugin-settings-manager/admin/src/translations/nl.json index 5872072788..aead8c3681 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/nl.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/nl.json @@ -54,11 +54,6 @@ "form.security.description": "Configureer je beveiliging instellingen.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Inclusief Sub Domain", "form.security.item.hsts.maxAge": "Max Leeftijd", @@ -634,4 +629,4 @@ "strapi.notification.success.languageAdd": "De taal is succesvol toegevoegd.", "strapi.notification.success.languageDelete": "De taal is succesvol verwijderd.", "strapi.notification.success.settingsEdit": "De instellingen zijn succesvol geüpdatet" -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/pl.json b/packages/strapi-plugin-settings-manager/admin/src/translations/pl.json index 35394ad06f..0585255319 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/pl.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/pl.json @@ -54,11 +54,6 @@ "form.security.description": "Konfiguruj ustawienia bezpieczeństwa.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Subdomeny", "form.security.item.hsts.maxAge": "Max Age", @@ -634,4 +629,4 @@ "strapi.notification.success.languageAdd": "Język został pomyślnie dodany.", "strapi.notification.success.languageDelete": "Język został pomyślnie usunięty.", "strapi.notification.success.settingsEdit": "Ustawienia zostały pomyślnie zmienione." -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/pt-BR.json b/packages/strapi-plugin-settings-manager/admin/src/translations/pt-BR.json index a23e16c0c2..1fb495bfcb 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/pt-BR.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/pt-BR.json @@ -54,11 +54,6 @@ "form.security.description": "Defina as suas configurações de segurança.", "form.security.item.cors": "CORS", "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.includeSubDomains": "Incluir Sub Domínio", "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.languageDelete": "O idioma foi removido com sucesso.", "strapi.notification.success.settingsEdit": "As configurações foram atualizadas com sucesso." -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/pt.json b/packages/strapi-plugin-settings-manager/admin/src/translations/pt.json index 4fa3edd182..a49e132492 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/pt.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/pt.json @@ -54,11 +54,6 @@ "form.security.description": "Configure as suas definições de segurança.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Incluir Sub Domínio", "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.languageDelete": "O idioma foi excluido com sucesso.", "strapi.notification.success.settingsEdit": "As configurações foram actualizadas com sucesso." -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/ru.json b/packages/strapi-plugin-settings-manager/admin/src/translations/ru.json index fe26ab9afc..fdc33f2777 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/ru.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/ru.json @@ -54,11 +54,6 @@ "form.security.description": "Задайте настройки безопасности.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Include Sub Domain", "form.security.item.hsts.maxAge": "Max Age", diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/tr.json b/packages/strapi-plugin-settings-manager/admin/src/translations/tr.json index 46564bcfe9..0490858e2c 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/tr.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/tr.json @@ -54,11 +54,6 @@ "form.security.description": "Güvenlik ayarlarınızı yapılandırın.", "form.security.item.cors": "Cors", "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.includeSubDomains": "Alt Etki Alanını Dahil Et", "form.security.item.hsts.maxAge": "Max Age", @@ -634,4 +629,4 @@ "strapi.notification.success.languageAdd": "Dil başarıyla eklendi.", "strapi.notification.success.languageDelete": "Dil başarıyla silindi.", "strapi.notification.success.settingsEdit": "Ayarlar başarıyla güncellendi." -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/zh-Hans.json b/packages/strapi-plugin-settings-manager/admin/src/translations/zh-Hans.json index 5d52299471..c342a64d68 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/zh-Hans.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/zh-Hans.json @@ -53,11 +53,6 @@ "form.security.description": "配置安全设置。", "form.security.item.cors": "Cors", "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.includeSubDomains": "包括子域", "form.security.item.hsts.maxAge": "Max Age", @@ -628,4 +623,4 @@ "strapi.notification.success.languageAdd": "该语言已成功添加。", "strapi.notification.success.languageDelete": "数据库已被成功删除。", "strapi.notification.success.settingsEdit": "设置已成功更新。" -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/admin/src/translations/zh.json b/packages/strapi-plugin-settings-manager/admin/src/translations/zh.json index fe357d7ae2..3fa69bb4ff 100644 --- a/packages/strapi-plugin-settings-manager/admin/src/translations/zh.json +++ b/packages/strapi-plugin-settings-manager/admin/src/translations/zh.json @@ -54,11 +54,6 @@ "form.security.description": "調整安全性設定", "form.security.item.cors": "跨域資源共享 (Cors)", "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.includeSubDomains": "包含子域名", "form.security.item.hsts.maxAge": "作用期", diff --git a/packages/strapi-plugin-settings-manager/services/SettingsManager.js b/packages/strapi-plugin-settings-manager/services/SettingsManager.js index 7a4e49ab96..95887f82c0 100644 --- a/packages/strapi-plugin-settings-manager/services/SettingsManager.js +++ b/packages/strapi-plugin-settings-manager/services/SettingsManager.js @@ -285,70 +285,6 @@ module.exports = { name: 'form.security.name', description: 'form.security.description', 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', items: [ diff --git a/packages/strapi-plugin-upload/admin/src/containers/HomePage/saga.js b/packages/strapi-plugin-upload/admin/src/containers/HomePage/saga.js index 18bcb171cb..5a7c5e0738 100644 --- a/packages/strapi-plugin-upload/admin/src/containers/HomePage/saga.js +++ b/packages/strapi-plugin-upload/admin/src/containers/HomePage/saga.js @@ -51,9 +51,7 @@ function* dataGet() { function* uploadFiles(action) { try { yield put(setLoading()); - const headers = { - 'X-Forwarded-Host': 'strapi', - }; + const headers = {}; const response = yield call( request, '/upload', diff --git a/packages/strapi-plugin-upload/controllers/Upload.js b/packages/strapi-plugin-upload/controllers/Upload.js index a3040d9a14..f3e68f2fb9 100644 --- a/packages/strapi-plugin-upload/controllers/Upload.js +++ b/packages/strapi-plugin-upload/controllers/Upload.js @@ -25,9 +25,17 @@ module.exports = { if (config.enabled === false) { return ctx.badRequest( 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 || {}; if (_.isEmpty(files)) { - return ctx.badRequest( - null, - ctx.request.admin - ? [{ messages: [{ id: 'Upload.status.empty' }] }] - : 'Files are empty' - ); + return ctx.badRequest(null, [ + { + messages: [{ id: 'Upload.status.empty', message: 'Files are empty' }], + }, + ]); } // Transform stream files to buffer @@ -49,21 +56,17 @@ module.exports = { const enhancedFiles = buffers.map(file => { if (file.size > config.sizeLimit) { - return ctx.badRequest( - null, - ctx.request.admin - ? [ - { - messages: [ - { - id: 'Upload.status.sizeLimit', - values: { file: file.name }, - }, - ], - }, - ] - : `${file.name} file is bigger than limit size!` - ); + return ctx.badRequest(null, [ + { + messages: [ + { + id: 'Upload.status.sizeLimit', + message: `${file.name} file is bigger than limit size!`, + values: { file: file.name }, + }, + ], + }, + ]); } // Add details to the file to be able to create the relationships. diff --git a/packages/strapi-plugin-upload/test/upload.test.e2e.js b/packages/strapi-plugin-upload/test/upload.test.e2e.js index e38e327cfb..aedeaa1271 100644 --- a/packages/strapi-plugin-upload/test/upload.test.e2e.js +++ b/packages/strapi-plugin-upload/test/upload.test.e2e.js @@ -153,7 +153,7 @@ describe('Upload plugin end to end tests', () => { expect(res.statusCode).toBe(400); 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.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.body).toMatchObject({ - message: 'rec.jpg file is bigger than limit size!', + message: [ + { + messages: [{ message: 'rec.jpg file is bigger than limit size!' }], + }, + ], }); }); }); diff --git a/packages/strapi-plugin-users-permissions/config/policies/rateLimit.js b/packages/strapi-plugin-users-permissions/config/policies/rateLimit.js index 3728b4f00e..92a0d20b1f 100644 --- a/packages/strapi-plugin-users-permissions/config/policies/rateLimit.js +++ b/packages/strapi-plugin-users-permissions/config/policies/rateLimit.js @@ -5,9 +5,16 @@ const lazyRateLimit = { }; module.exports = async (ctx, next) => { - const message = ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.ratelimit' }] }] - : 'Too many attempts, please try again in a minute.'; + const message = [ + { + messages: [ + { + id: 'Auth.form.error.ratelimit', + message: 'Too many attempts, please try again in a minute.', + }, + ], + }, + ]; return lazyRateLimit.RateLimit.middleware( Object.assign( diff --git a/packages/strapi-plugin-users-permissions/controllers/Auth.js b/packages/strapi-plugin-users-permissions/controllers/Auth.js index 02f726833a..6866343385 100644 --- a/packages/strapi-plugin-users-permissions/controllers/Auth.js +++ b/packages/strapi-plugin-users-permissions/controllers/Auth.js @@ -10,8 +10,12 @@ const crypto = require('crypto'); const _ = require('lodash'); 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 formatError = error => [ + { messages: [{ id: error.id, message: error.message, field: error.field }] }, +]; module.exports = { async callback(ctx) { @@ -25,10 +29,7 @@ module.exports = { }); if (provider === 'local') { - if ( - !_.get(await store.get({ key: 'grant' }), 'email.enabled') && - !ctx.request.admin - ) { + if (!_.get(await store.get({ key: 'grant' }), 'email.enabled')) { return ctx.badRequest(null, 'This provider is disabled.'); } @@ -36,9 +37,10 @@ module.exports = { if (!params.identifier) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }] - : 'Please provide your username or your e-mail.' + formatError({ + id: 'Auth.form.error.email.provide', + message: 'Please provide your username or your e-mail.', + }) ); } @@ -46,9 +48,10 @@ module.exports = { if (!params.password) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.password.provide' }] }] - : 'Please provide your password.' + formatError({ + id: 'Auth.form.error.password.provide', + message: 'Please provide your password.', + }) ); } @@ -72,9 +75,10 @@ module.exports = { if (!user) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.invalid' }] }] - : 'Identifier or password invalid.' + formatError({ + id: 'Auth.form.error.invalid', + message: 'Identifier or password invalid.', + }) ); } @@ -84,18 +88,20 @@ module.exports = { ) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.confirmed' }] }] - : 'Your account email is not confirmed.' + formatError({ + id: 'Auth.form.error.confirmed', + message: 'Your account email is not confirmed', + }) ); } if (user.blocked === true) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.blocked' }] }] - : 'Your account has been blocked by the administrator.' + formatError({ + id: 'Auth.form.error.blocked', + message: 'Your account has been blocked by an administrator', + }) ); } @@ -103,9 +109,11 @@ module.exports = { if (!user.password) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.password.local' }] }] - : 'This user never set a local password, please login thanks to the provider used during account creation.' + formatError({ + id: 'Auth.form.error.password.local', + 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) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.invalid' }] }] - : 'Identifier or password invalid.' + formatError({ + id: 'Auth.form.error.invalid', + message: 'Identifier or password invalid.', + }) ); } else { ctx.send({ jwt: strapi.plugins['users-permissions'].services.jwt.issue({ id: user.id, }), - user: _.omit(user.toJSON ? user.toJSON() : user, [ - 'password', - 'resetPasswordToken', - ]), + user: sanitizeEntity(user.toJSON ? user.toJSON() : user, { + model: strapi.query('user', 'users-permissions').model, + }), }); } } else { 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. @@ -143,27 +157,20 @@ module.exports = { 'users-permissions' ].services.providers.connect(provider, ctx.query); } catch ([user, error]) { - return ctx.badRequest( - null, - error === 'array' ? (ctx.request.admin ? error[0] : error[1]) : error - ); + return ctx.badRequest(null, error === 'array' ? error[0] : error); } if (!user) { - return ctx.badRequest( - null, - error === 'array' ? (ctx.request.admin ? error[0] : error[1]) : error - ); + return ctx.badRequest(null, error === 'array' ? error[0] : error); } ctx.send({ jwt: strapi.plugins['users-permissions'].services.jwt.issue({ id: user.id, }), - user: _.omit(user.toJSON ? user.toJSON() : user, [ - 'password', - 'resetPasswordToken', - ]), + user: sanitizeEntity(user.toJSON ? user.toJSON() : user, { + model: strapi.query('user', 'users-permissions').model, + }), }); } }, @@ -184,9 +191,10 @@ module.exports = { if (!user) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.code.provide' }] }] - : 'Incorrect code provided.' + formatError({ + id: 'Auth.form.error.code.provide', + message: 'Incorrect code provided.', + }) ); } @@ -206,10 +214,9 @@ module.exports = { jwt: strapi.plugins['users-permissions'].services.jwt.issue({ id: user.id, }), - user: _.omit(user.toJSON ? user.toJSON() : user, [ - 'password', - 'resetPasswordToken', - ]), + user: sanitizeEntity(user.toJSON ? user.toJSON() : user, { + model: strapi.query('user', 'users-permissions').model, + }), }); } else if ( params.password && @@ -218,16 +225,18 @@ module.exports = { ) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.password.matching' }] }] - : 'Passwords do not match.' + formatError({ + id: 'Auth.form.error.password.matching', + message: 'Passwords do not match.', + }) ); } else { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.params.provide' }] }] - : 'Incorrect params provided.' + formatError({ + id: 'Auth.form.error.params.provide', + message: 'Incorrect params provided.', + }) ); } }, @@ -270,9 +279,10 @@ module.exports = { if (!user) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.user.not-exist' }] }] - : 'This email does not exist.' + formatError({ + id: 'Auth.form.error.user.not-exist', + message: 'This email does not exist.', + }) ); } @@ -353,9 +363,10 @@ module.exports = { if (!settings.allow_register) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.advanced.allow_register' }] }] - : 'Register action is currently disabled.' + formatError({ + id: 'Auth.advanced.allow_register', + message: 'Register action is currently disabled.', + }) ); } @@ -367,9 +378,10 @@ module.exports = { if (!params.password) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.password.provide' }] }] - : 'Please provide your password.' + formatError({ + id: 'Auth.form.error.password.provide', + message: 'Please provide your password.', + }) ); } @@ -377,9 +389,10 @@ module.exports = { if (!params.email) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }] - : 'Please provide your email.' + formatError({ + id: 'Auth.form.error.email.provide', + message: 'Please provide your email.', + }) ); } @@ -392,9 +405,11 @@ module.exports = { ) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.password.format' }] }] - : 'Your password cannot contain more than three times the symbol `$`.' + formatError({ + id: 'Auth.form.error.password.format', + message: + 'Your password cannot contain more than three times the symbol `$`.', + }) ); } @@ -405,9 +420,10 @@ module.exports = { if (!role) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.role.notFound' }] }] - : 'Impossible to find the default role.' + formatError({ + id: 'Auth.form.error.role.notFound', + message: 'Impossible to find the default role.', + }) ); } @@ -430,18 +446,20 @@ module.exports = { if (user && user.provider === params.provider) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.email.taken' }] }] - : 'Email is already taken.' + formatError({ + id: 'Auth.form.error.email.taken', + message: 'Email is already taken.', + }) ); } if (user && user.provider !== params.provider && settings.unique_email) { return ctx.badRequest( null, - ctx.request.admin - ? [{ messages: [{ id: 'Auth.form.error.email.taken' }] }] - : 'Email is already taken.' + formatError({ + id: 'Auth.form.error.email.taken', + message: 'Email is already taken.', + }) ); } @@ -515,20 +533,19 @@ module.exports = { ctx.send({ jwt, - user: _.omit(user.toJSON ? user.toJSON() : user, [ - 'password', - 'resetPasswordToken', - ]), + user: sanitizeEntity(user.toJSON ? user.toJSON() : user, { + model: strapi.query('user', 'users-permissions').model, + }), }); } catch (err) { 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( - null, - ctx.request.admin ? [{ messages: [{ id: adminError }] }] : err.message - ); + ctx.badRequest(null, formatError(adminError)); } }, diff --git a/packages/strapi-plugin-users-permissions/controllers/User.js b/packages/strapi-plugin-users-permissions/controllers/User.js index 0307887aed..ef4d0770e1 100644 --- a/packages/strapi-plugin-users-permissions/controllers/User.js +++ b/packages/strapi-plugin-users-permissions/controllers/User.js @@ -7,10 +7,15 @@ */ const _ = require('lodash'); +const { sanitizeEntity } = require('strapi-utils'); -const sanitizeUser = user => _.omit(user, ['password', 'resetPasswordToken']); -const adminError = error => [ - { messages: [{ id: error.message, field: error.field }] }, +const sanitizeUser = user => + sanitizeEntity(user, { + model: strapi.query('user', 'users-permissions').model, + }); + +const formatError = error => [ + { messages: [{ id: error.id, message: error.message, field: error.field }] }, ]; module.exports = { @@ -99,12 +104,11 @@ module.exports = { if (userWithSameUsername) { return ctx.badRequest( null, - ctx.request.admin - ? adminError({ - message: 'Auth.form.error.username.taken', - field: ['username'], - }) - : 'username.alreadyTaken.' + formatError({ + id: 'Auth.form.error.username.taken', + message: 'Username already taken.', + field: ['username'], + }) ); } @@ -116,12 +120,12 @@ module.exports = { if (userWithSameEmail) { return ctx.badRequest( null, - ctx.request.admin - ? adminError({ - message: 'Auth.form.error.email.taken', - field: ['email'], - }) - : 'email.alreadyTaken' + + formatError({ + id: 'Auth.form.error.email.taken', + message: 'Email already taken.', + field: ['email'], + }) ); } } @@ -146,10 +150,7 @@ module.exports = { ctx.created(data); } catch (error) { - ctx.badRequest( - null, - ctx.request.admin ? adminError(error) : error.message - ); + ctx.badRequest(null, formatError(error)); } }, @@ -190,12 +191,11 @@ module.exports = { if (userWithSameUsername && userWithSameUsername.id != id) { return ctx.badRequest( null, - ctx.request.admin - ? adminError({ - message: 'Auth.form.error.username.taken', - field: ['username'], - }) - : 'username.alreadyTaken.' + formatError({ + id: 'Auth.form.error.username.taken', + message: 'username.alreadyTaken.', + field: ['username'], + }) ); } } @@ -208,12 +208,11 @@ module.exports = { if (userWithSameEmail && userWithSameEmail.id != id) { return ctx.badRequest( null, - ctx.request.admin - ? adminError({ - message: 'Auth.form.error.email.taken', - field: ['email'], - }) - : 'email.alreadyTaken' + formatError({ + id: 'Auth.form.error.email.taken', + message: 'Eamil already taken', + field: ['email'], + }) ); } } diff --git a/packages/strapi-utils/lib/index.js b/packages/strapi-utils/lib/index.js index 2e90089708..8e2c773dc7 100644 --- a/packages/strapi-utils/lib/index.js +++ b/packages/strapi-utils/lib/index.js @@ -6,6 +6,8 @@ const convertRestQueryParams = require('./convertRestQueryParams'); const buildQuery = require('./buildQuery'); +const parseMultipartData = require('./parse-multipart'); +const sanitizeEntity = require('./sanitize-entity'); module.exports = { cli: require('./cli'), @@ -21,4 +23,6 @@ module.exports = { templateConfiguration: require('./templateConfiguration'), convertRestQueryParams, buildQuery, + parseMultipartData, + sanitizeEntity, }; diff --git a/packages/strapi/lib/core-api/utils/parse-multipart.js b/packages/strapi-utils/lib/parse-multipart.js similarity index 100% rename from packages/strapi/lib/core-api/utils/parse-multipart.js rename to packages/strapi-utils/lib/parse-multipart.js diff --git a/packages/strapi-utils/lib/sanitize-entity.js b/packages/strapi-utils/lib/sanitize-entity.js new file mode 100644 index 0000000000..13deacabe7 --- /dev/null +++ b/packages/strapi-utils/lib/sanitize-entity.js @@ -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; + }, {}); +}; diff --git a/packages/strapi/lib/core-api/controller.js b/packages/strapi/lib/core-api/controller.js index 58cb33245f..ccb7f590ee 100644 --- a/packages/strapi/lib/core-api/controller.js +++ b/packages/strapi/lib/core-api/controller.js @@ -1,17 +1,13 @@ 'use strict'; -const parseMultipartData = require('./utils/parse-multipart'); - -const proto = { - parseMultipartData, -}; +const { parseMultipartData, sanitizeEntity } = require('strapi-utils'); /** * default bookshelf controller * */ -module.exports = ({ service }) => { - return Object.assign(Object.create(proto), { +module.exports = ({ service, model }) => { + return { /** * expose some utils so the end users can use them */ @@ -22,11 +18,15 @@ module.exports = ({ service }) => { * @return {Object|Array} */ - find(ctx) { + async find(ctx) { + let entities; 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} */ - findOne(ctx) { - return service.findOne(ctx.params); + async findOne(ctx) { + const entity = await service.findOne(ctx.params); + return sanitizeEntity(entity, { model }); }, /** @@ -58,13 +59,15 @@ module.exports = ({ service }) => { * @return {Object} */ - create(ctx) { + async create(ctx) { + let entity; if (ctx.is('multipart')) { - const { data, files } = this.parseMultipartData(ctx); - return service.create(data, { files }); + const { data, files } = parseMultipartData(ctx); + entity = await service.create(data, { files }); + } else { + entity = await service.create(ctx.request.body); } - - return service.create(ctx.request.body); + return sanitizeEntity(entity, { model }); }, /** @@ -73,13 +76,16 @@ module.exports = ({ service }) => { * @return {Object} */ - update(ctx) { + async update(ctx) { + let entity; if (ctx.is('multipart')) { - const { data, files } = this.parseMultipartData(ctx); - return service.update(ctx.params, data, { files }); + const { data, files } = parseMultipartData(ctx); + 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} */ - delete(ctx) { - return service.delete(ctx.params); + async delete(ctx) { + const entity = await service.delete(ctx.params); + return sanitizeEntity(entity, { model }); }, - }); + }; }; diff --git a/packages/strapi/lib/core/bootstrap.js b/packages/strapi/lib/core/bootstrap.js index 0247fdef08..3c346147ec 100644 --- a/packages/strapi/lib/core/bootstrap.js +++ b/packages/strapi/lib/core/bootstrap.js @@ -77,7 +77,7 @@ module.exports = function(strapi) { ); const controller = Object.assign( - createController({ service }), + createController({ service, model }), userController, { identity: userController.identity || _.upperFirst(index) } ); @@ -209,10 +209,6 @@ module.exports = function(strapi) { boom: { enabled: true, }, - mask: { - enabled: true, - }, - // Necessary middlewares for the administration panel. cors: { enabled: true, }, diff --git a/packages/strapi/lib/middlewares/cors/index.js b/packages/strapi/lib/middlewares/cors/index.js index 1a9a14ef9e..5dfad254fc 100644 --- a/packages/strapi/lib/middlewares/cors/index.js +++ b/packages/strapi/lib/middlewares/cors/index.js @@ -10,13 +10,7 @@ const defaults = { maxAge: 31536000, credentials: true, methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], - headers: [ - 'Content-Type', - 'Authorization', - 'Origin', - 'Accept', - 'X-Forwarded-Host', - ], + headers: ['Content-Type', 'Authorization', 'Origin', 'Accept'], keepHeadersOnError: false, }; diff --git a/packages/strapi/lib/middlewares/csrf/defaults.json b/packages/strapi/lib/middlewares/csrf/defaults.json deleted file mode 100644 index ac18fd4561..0000000000 --- a/packages/strapi/lib/middlewares/csrf/defaults.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "csrf": { - "enabled": false, - "key": "_csrf", - "secret": "_csrfSecret" - } -} diff --git a/packages/strapi/lib/middlewares/csrf/index.js b/packages/strapi/lib/middlewares/csrf/index.js deleted file mode 100644 index 0438d362ee..0000000000 --- a/packages/strapi/lib/middlewares/csrf/index.js +++ /dev/null @@ -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 - ); - }); - }, - }; -}; diff --git a/packages/strapi/lib/middlewares/index.js b/packages/strapi/lib/middlewares/index.js index 535332ab9e..1bb4a93e82 100644 --- a/packages/strapi/lib/middlewares/index.js +++ b/packages/strapi/lib/middlewares/index.js @@ -3,17 +3,6 @@ const { uniq, difference, get, isUndefined, merge } = require('lodash'); 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 */ const middlewareConfig = this.config.middleware; diff --git a/packages/strapi/lib/middlewares/mask/defaults.json b/packages/strapi/lib/middlewares/mask/defaults.json deleted file mode 100644 index 8fc1f914ab..0000000000 --- a/packages/strapi/lib/middlewares/mask/defaults.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "mask": { - "enabled": false - } -} diff --git a/packages/strapi/lib/middlewares/mask/index.js b/packages/strapi/lib/middlewares/mask/index.js deleted file mode 100644 index bdf880084a..0000000000 --- a/packages/strapi/lib/middlewares/mask/index.js +++ /dev/null @@ -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; - }, []); - }, - }; -};