Remove multipart

Signed-off-by: Alexandre Bodin <bodin.alex@gmail.com>
This commit is contained in:
Alexandre Bodin 2020-11-03 10:00:50 +01:00
parent f1789cc1b9
commit 02c7d97ffc
8 changed files with 41 additions and 192 deletions

View File

@ -2,9 +2,6 @@
const _ = require('lodash');
const parseMultipartBody = require('../../utils/parse-multipart');
const uploadFiles = require('../../utils/upload-files');
module.exports = async (ctx, next) => {
const { model } = ctx.params;
@ -22,24 +19,6 @@ module.exports = async (ctx, next) => {
const [controller, action] = _.get(target, actionPath, []).split('.');
if (controller && action) {
if (ctx.is('multipart')) {
const { data, files } = parseMultipartBody(ctx);
ctx.request.body = data;
ctx.request.files = {};
await target.controllers[controller.toLowerCase()][action](ctx);
const resBody = ctx.body;
if (ctx.status >= 300) return;
await uploadFiles(resBody, files, {
model: ct.modelName,
source: ct.plugin,
});
return ctx.send(resBody);
}
return await target.controllers[controller.toLowerCase()][action](ctx);
}
}

View File

@ -5,7 +5,6 @@ const { has, pipe } = require('lodash/fp');
const {
getService,
wrapBadRequest,
parseBody,
setCreatorFields,
pickWritableAttributes,
} = require('../utils');
@ -16,6 +15,7 @@ module.exports = {
const { model } = ctx.params;
const { query } = ctx.request;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.read()) {
@ -26,10 +26,7 @@ module.exports = {
const permissionQuery = permissionChecker.buildPermissionQuery(query);
const { results, pagination } = await getService('entity-manager')[method](
permissionQuery,
model
);
const { results, pagination } = await entityManager[method](permissionQuery, model);
ctx.body = {
results: results.map(entity => permissionChecker.sanitizeOutput(entity)),
@ -41,13 +38,14 @@ module.exports = {
const { userAbility } = ctx.state;
const { model, id } = ctx.params;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.read()) {
return ctx.forbidden();
}
const entity = await getService('entity-manager').findOneWithCreatorRoles(id, model);
const entity = await entityManager.findOneWithCreatorRoles(id, model);
if (!entity) {
return ctx.notFound();
@ -63,8 +61,9 @@ module.exports = {
async create(ctx) {
const { userAbility, user } = ctx.state;
const { model } = ctx.params;
const { files, data } = parseBody(ctx);
const { body } = ctx.request;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.create()) {
@ -78,10 +77,7 @@ module.exports = {
const sanitizeFn = pipe([pickWritables, pickPermittedFields, setCreator]);
await wrapBadRequest(async () => {
const entity = await getService('entity-manager').create(
{ data: sanitizeFn(data), files },
model
);
const entity = await entityManager.create(sanitizeFn(body), model);
ctx.body = permissionChecker.sanitizeOutput(entity);
await strapi.telemetry.send('didCreateFirstContentTypeEntry', { model });
@ -91,15 +87,16 @@ module.exports = {
async update(ctx) {
const { userAbility, user } = ctx.state;
const { id, model } = ctx.params;
const { files, data } = parseBody(ctx);
const { body } = ctx.request;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.update()) {
return ctx.forbidden();
}
const entity = await getService('entity-manager').findOneWithCreatorRoles(id, model);
const entity = await entityManager.findOneWithCreatorRoles(id, model);
if (!entity) {
return ctx.notFound();
@ -116,11 +113,7 @@ module.exports = {
const sanitizeFn = pipe([pickWritables, pickPermittedFields, setCreator]);
await wrapBadRequest(async () => {
const updatedEntity = await getService('entity-manager').update(
entity,
{ data: sanitizeFn(data), files },
model
);
const updatedEntity = await entityManager.update(entity, sanitizeFn(body), model);
ctx.body = permissionChecker.sanitizeOutput(updatedEntity);
})();
@ -130,13 +123,14 @@ module.exports = {
const { userAbility } = ctx.state;
const { id, model } = ctx.params;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.delete()) {
return ctx.forbidden();
}
const entity = await getService('entity-manager').findOneWithCreatorRoles(id, model);
const entity = await entityManager.findOneWithCreatorRoles(id, model);
if (!entity) {
return ctx.notFound();
@ -146,7 +140,7 @@ module.exports = {
return ctx.forbidden();
}
const result = await getService('entity-manager').delete(entity, model);
const result = await entityManager.delete(entity, model);
ctx.body = permissionChecker.sanitizeOutput(result);
},
@ -155,13 +149,14 @@ module.exports = {
const { userAbility } = ctx.state;
const { id, model } = ctx.params;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.publish()) {
return ctx.forbidden();
}
const entity = await getService('entity-manager').findOneWithCreatorRoles(id, model);
const entity = await entityManager.findOneWithCreatorRoles(id, model);
if (!entity) {
return ctx.notFound();
@ -171,7 +166,7 @@ module.exports = {
return ctx.forbidden();
}
const result = await getService('entity-manager').publish(entity, model);
const result = await entityManager.publish(entity, model);
ctx.body = permissionChecker.sanitizeOutput(result);
},
@ -180,13 +175,14 @@ module.exports = {
const { userAbility } = ctx.state;
const { id, model } = ctx.params;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.unpublish()) {
return ctx.forbidden();
}
const entity = await getService('entity-manager').findOneWithCreatorRoles(id, model);
const entity = await entityManager.findOneWithCreatorRoles(id, model);
if (!entity) {
return ctx.notFound();
@ -196,7 +192,7 @@ module.exports = {
return ctx.forbidden();
}
const result = await getService('entity-manager').unpublish(entity, model);
const result = await entityManager.unpublish(entity, model);
ctx.body = permissionChecker.sanitizeOutput(result);
},
@ -207,6 +203,7 @@ module.exports = {
const { query, body } = ctx.request;
const { ids } = body;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.delete()) {
@ -222,7 +219,7 @@ module.exports = {
_where: [idsWhereClause].concat(permissionQuery._where || {}),
};
const results = await strapi.entityService.delete({ params }, { model });
const results = await entityManager.findAndDelete(params, model);
ctx.body = results.map(result => permissionChecker.sanitizeOutput(result));
},

View File

@ -4,7 +4,6 @@ const { pipe } = require('lodash/fp');
const {
getService,
wrapBadRequest,
parseBody,
setCreatorFields,
pickWritableAttributes,
} = require('../utils');
@ -48,9 +47,9 @@ module.exports = {
async createOrUpdate(ctx) {
const { user, userAbility } = ctx.state;
const { model } = ctx.params;
const { body } = ctx.request;
const { data, files } = parseBody(ctx);
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.create() && permissionChecker.cannot.update()) {
@ -73,11 +72,7 @@ module.exports = {
await wrapBadRequest(async () => {
if (!entity) {
const entity = await getService('entity-manager').create(
{ data: sanitizeFn(data), files },
model
);
const entity = await entityManager.create(sanitizeFn(body), model);
ctx.body = permissionChecker.sanitizeOutput(entity);
await strapi.telemetry.send('didCreateFirstContentTypeEntry', { model });
@ -88,12 +83,7 @@ module.exports = {
return ctx.forbidden();
}
const updatedEntity = await getService('entity-manager').update(
entity,
{ data: sanitizeFn(data), files },
model
);
const updatedEntity = await entityManager.update(entity, sanitizeFn(body), model);
ctx.body = permissionChecker.sanitizeOutput(updatedEntity);
})();
},
@ -102,6 +92,7 @@ module.exports = {
const { userAbility } = ctx.state;
const { model } = ctx.params;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.delete()) {
@ -118,7 +109,7 @@ module.exports = {
return ctx.forbidden();
}
const deletedEntity = await getService('entity-manager').delete(entity, model);
const deletedEntity = await entityManager.delete(entity, model);
ctx.body = permissionChecker.sanitizeOutput(deletedEntity);
},
@ -127,6 +118,7 @@ module.exports = {
const { userAbility } = ctx.state;
const { model } = ctx.params;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.publish()) {
@ -143,7 +135,7 @@ module.exports = {
return ctx.forbidden();
}
const publishedEntity = await getService('entity-manager').publish(entity, model);
const publishedEntity = await entityManager.publish(entity, model);
ctx.body = permissionChecker.sanitizeOutput(publishedEntity);
},
@ -152,6 +144,7 @@ module.exports = {
const { userAbility } = ctx.state;
const { model } = ctx.params;
const entityManager = getService('entity-manager');
const permissionChecker = getService('permission-checker').create({ userAbility, model });
if (permissionChecker.cannot.unpublish()) {
@ -168,7 +161,7 @@ module.exports = {
return ctx.forbidden();
}
const unpublishedEntity = await getService('entity-manager').unpublish(entity, model);
const unpublishedEntity = await entityManager.unpublish(entity, model);
ctx.body = permissionChecker.sanitizeOutput(unpublishedEntity);
},

View File

@ -79,23 +79,21 @@ module.exports = {
},
async create(body, model) {
const { data, files } = body;
const modelDef = strapi.getModel(model);
const publishData = { ...data };
const publishData = { ...body };
if (hasDraftAndPublish(modelDef)) {
publishData[PUBLISHED_AT_ATTRIBUTE] = null;
}
return strapi.entityService.create({ data: publishData, files }, { model });
return strapi.entityService.create({ data: publishData }, { model });
},
update(entity, { data, files }, model) {
update(entity, body, model) {
const params = { id: entity.id };
const publishData = omitPublishedAtField(data);
const publishData = omitPublishedAtField(body);
return strapi.entityService.update({ params, data: publishData, files }, { model });
return strapi.entityService.update({ params, data: publishData }, { model });
},
delete(entity, model) {
@ -103,6 +101,10 @@ module.exports = {
return strapi.entityService.delete({ params }, { model });
},
findAnddelete(params, model) {
return strapi.entityService.delete({ params }, { model });
},
publish: emitEvent(ENTRY_PUBLISH, async (entity, model) => {
if (entity[PUBLISHED_AT_ATTRIBUTE]) {
throw strapi.errors.badRequest('already.published');

View File

@ -1,7 +1,6 @@
'use strict';
const { prop } = require('lodash/fp');
const parseBody = require('./parse-body');
const wrapBadRequest = require('./wrap-bad-request');
const setCreatorFields = require('./set-creator-fields');
const pickWritableAttributes = require('./pick-writable-attributes');
@ -13,7 +12,6 @@ const getService = name => {
module.exports = {
getService,
parseBody,
wrapBadRequest,
setCreatorFields,
pickWritableAttributes,

View File

@ -1,8 +0,0 @@
'use strict';
const parseMultipartBody = require('./parse-multipart');
module.exports = ctx => {
const { body } = ctx.request;
return ctx.is('multipart') ? parseMultipartBody(ctx) : { data: body };
};

View File

@ -1,41 +0,0 @@
'use strict';
const _ = require('lodash');
module.exports = ctx => {
const { body = {}, files = {} } = ctx.request;
if (!body.data) {
throw strapi.errors.badRequest(
`When using multipart/form-data you need to provide your data in a JSON 'data' field.`
);
}
let data;
try {
data = JSON.parse(body.data);
} catch (error) {
throw strapi.errors.badRequest(
`Invalid 'data' field. 'data' should be a valid JSON.`
);
}
const filesToUpload = Object.keys(files).reduce((acc, key) => {
const fullPath = _.toPath(key);
if (fullPath.length <= 1 || fullPath[0] !== 'files') {
throw strapi.errors.badRequest(
`When using multipart/form-data you need to provide your files by prefixing them witht the 'files'.`
);
}
const path = _.tail(fullPath);
acc[path.join('.')] = files[key];
return acc;
}, {});
return {
data,
files: filesToUpload,
};
};

View File

@ -1,71 +0,0 @@
'use strict';
const _ = require('lodash');
module.exports = async (entry, files, { model, source }) => {
const entity = strapi.getModel(model, source);
if (!_.has(strapi.plugins, 'upload')) return entry;
const uploadService = strapi.plugins.upload.services.upload;
const findModelFromUploadPath = path => {
if (path.length === 0) return { model, source };
let currentPath = [];
let tmpModel = entity;
let modelName = model;
let sourceName;
for (let i = 0; i < path.length; i++) {
if (!tmpModel) return {};
const part = path[i];
const attr = tmpModel.attributes[part];
currentPath.push(part);
// ignore array indexes => handled in the dynamic zone section
if (_.isFinite(_.toNumber(path[i]))) {
continue;
}
if (!attr) return {};
if (attr.type === 'component') {
modelName = attr.component;
tmpModel = strapi.components[attr.component];
} else if (attr.type === 'dynamiczone') {
const entryIdx = path[i + 1]; // get component index
const value = _.get(entry, [...currentPath, entryIdx]);
if (!value) return {};
modelName = value.__component; // get component type
tmpModel = strapi.components[modelName];
} else if (_.has(attr, 'model') || _.has(attr, 'collection')) {
sourceName = attr.plugin;
modelName = attr.model || attr.collection;
tmpModel = strapi.getModel(attr.model || attr.collection, source);
} else {
return {};
}
}
return { model: modelName, source: sourceName };
};
const doUpload = async (key, files) => {
const parts = key.split('.');
const [path, field] = [_.initial(parts), _.last(parts)];
const { model, source } = findModelFromUploadPath(path);
if (model) {
const id = _.get(entry, path.concat('id'));
return uploadService.uploadToEntity({ id, model, field }, files, source);
}
};
await Promise.all(Object.keys(files).map(key => doUpload(key, files[key])));
};