Alexandre BODIN 942e646d28
Perf optimizations (#16117)
Co-authored-by: Marc-Roig <marc12info@gmail.com>
2023-03-21 18:37:21 +01:00

144 lines
4.0 KiB
JavaScript

'use strict';
const { isArray, cloneDeep } = require('lodash/fp');
const { getNonWritableAttributes } = require('../content-types');
const { pipeAsync } = require('../async');
const visitors = require('./visitors');
const sanitizers = require('./sanitizers');
const traverseEntity = require('../traverse-entity');
const { traverseQueryFilters, traverseQuerySort, traverseQueryPopulate } = require('../traverse');
const createContentAPISanitizers = () => {
const sanitizeInput = (data, schema, { auth } = {}) => {
if (isArray(data)) {
return Promise.all(data.map((entry) => sanitizeInput(entry, schema, { auth })));
}
const nonWritableAttributes = getNonWritableAttributes(schema);
const transforms = [
// Remove non writable attributes
traverseEntity(visitors.restrictedFields(nonWritableAttributes), { schema }),
];
if (auth) {
// Remove restricted relations
transforms.push(traverseEntity(visitors.removeRestrictedRelations(auth), { schema }));
}
// Apply sanitizers from registry if exists
strapi.sanitizers
.get('content-api.input')
.forEach((sanitizer) => transforms.push(sanitizer(schema)));
return pipeAsync(...transforms)(data);
};
const sanitizeOutput = async (data, schema, { auth } = {}) => {
if (isArray(data)) {
const res = new Array(data.length);
for (let i = 0; i < data.length; i += 1) {
res[i] = await sanitizeOutput(data[i], schema, { auth });
}
return res;
}
const transforms = [(data) => sanitizers.defaultSanitizeOutput(schema, data)];
if (auth) {
transforms.push(traverseEntity(visitors.removeRestrictedRelations(auth), { schema }));
}
// Apply sanitizers from registry if exists
strapi.sanitizers
.get('content-api.output')
.forEach((sanitizer) => transforms.push(sanitizer(schema)));
return pipeAsync(...transforms)(data);
};
const sanitizeQuery = async (query, schema, { auth } = {}) => {
const { filters, sort, fields, populate } = query;
const sanitizedQuery = cloneDeep(query);
if (filters) {
Object.assign(sanitizedQuery, { filters: await sanitizeFilters(filters, schema, { auth }) });
}
if (sort) {
Object.assign(sanitizedQuery, { sort: await sanitizeSort(sort, schema, { auth }) });
}
if (fields) {
Object.assign(sanitizedQuery, { fields: await sanitizeFields(fields, schema) });
}
if (populate) {
Object.assign(sanitizedQuery, { populate: await sanitizePopulate(populate, schema) });
}
return sanitizedQuery;
};
const sanitizeFilters = (filters, schema, { auth } = {}) => {
if (isArray(filters)) {
return Promise.all(filters.map((filter) => sanitizeFilters(filter, schema, { auth })));
}
const transforms = [sanitizers.defaultSanitizeFilters(schema)];
if (auth) {
transforms.push(traverseQueryFilters(visitors.removeRestrictedRelations(auth), { schema }));
}
return pipeAsync(...transforms)(filters);
};
const sanitizeSort = (sort, schema, { auth } = {}) => {
const transforms = [sanitizers.defaultSanitizeSort(schema)];
if (auth) {
transforms.push(traverseQuerySort(visitors.removeRestrictedRelations(auth), { schema }));
}
return pipeAsync(...transforms)(sort);
};
const sanitizeFields = (fields, schema) => {
const transforms = [sanitizers.defaultSanitizeFields(schema)];
return pipeAsync(...transforms)(fields);
};
const sanitizePopulate = (populate, schema, { auth } = {}) => {
const transforms = [sanitizers.defaultSanitizePopulate(schema)];
if (auth) {
transforms.push(traverseQueryPopulate(visitors.removeRestrictedRelations(auth), { schema }));
}
return pipeAsync(...transforms)(populate);
};
return {
input: sanitizeInput,
output: sanitizeOutput,
query: sanitizeQuery,
filters: sanitizeFilters,
sort: sanitizeSort,
fields: sanitizeFields,
populate: sanitizePopulate,
};
};
module.exports = {
contentAPI: createContentAPISanitizers(),
sanitizers,
visitors,
};