'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 sanitizeOuput = (data, schema, { auth } = {}) => { if (isArray(data)) { return Promise.all(data.map((entry) => sanitizeOuput(entry, schema, { auth }))); } const transforms = [sanitizers.defaultSanitizeOutput(schema)]; 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: sanitizeOuput, query: sanitizeQuery, filters: sanitizeFilters, sort: sanitizeSort, fields: sanitizeFields, populate: sanitizePopulate, }; }; module.exports = { contentAPI: createContentAPISanitizers(), sanitizers, visitors, };