mirror of
https://github.com/strapi/strapi.git
synced 2025-10-28 16:39:37 +00:00
Fix input payload validation
This commit is contained in:
parent
023e95b482
commit
90a86f595c
89
api-tests/core/strapi/api/validate-body.test.api.js
Normal file
89
api-tests/core/strapi/api/validate-body.test.api.js
Normal file
@ -0,0 +1,89 @@
|
||||
'use strict';
|
||||
|
||||
const { createStrapiInstance } = require('api-tests/strapi');
|
||||
const { createTestBuilder } = require('api-tests/builder');
|
||||
const { createContentAPIRequest } = require('api-tests/request');
|
||||
|
||||
const builder = createTestBuilder();
|
||||
let strapi;
|
||||
let rq;
|
||||
let data;
|
||||
|
||||
const productFixtures = [
|
||||
{
|
||||
name: 'foo',
|
||||
description: 'first product',
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
description: 'second product',
|
||||
},
|
||||
];
|
||||
|
||||
const product = {
|
||||
attributes: {
|
||||
name: { type: 'string' },
|
||||
description: { type: 'text' },
|
||||
},
|
||||
displayName: 'product',
|
||||
singularName: 'product',
|
||||
pluralName: 'products',
|
||||
description: '',
|
||||
collectionName: '',
|
||||
};
|
||||
|
||||
describe('Validate Body', () => {
|
||||
beforeAll(async () => {
|
||||
await builder
|
||||
.addContentType(product)
|
||||
.addFixtures(product.singularName, productFixtures)
|
||||
.build();
|
||||
|
||||
data = builder.fixturesFor(product.singularName);
|
||||
|
||||
strapi = await createStrapiInstance();
|
||||
rq = await createContentAPIRequest({ strapi });
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await strapi.destroy();
|
||||
await builder.cleanup();
|
||||
});
|
||||
|
||||
describe('Create', () => {
|
||||
test('Cannot specify the ID during entity creation', async () => {
|
||||
const createPayload = { data: { id: -1, name: 'baz', description: 'third product' } };
|
||||
|
||||
const response = await rq.post('/products', { body: createPayload });
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const { id, attributes } = response.body.data;
|
||||
|
||||
expect(id).not.toBe(createPayload.data.id);
|
||||
|
||||
expect(attributes).toHaveProperty('name', createPayload.data.name);
|
||||
expect(attributes).toHaveProperty('description', createPayload.data.description);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Update', () => {
|
||||
test('ID cannot be updated, but allowed fields can', async () => {
|
||||
const target = data[0];
|
||||
|
||||
const updatePayload = { data: { id: -1, name: 'baz' } };
|
||||
|
||||
const response = await rq.put(`/products/${target.id}`, {
|
||||
body: updatePayload,
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const { id, attributes } = response.body.data;
|
||||
|
||||
expect(id).toBe(target.id);
|
||||
expect(attributes).toHaveProperty('name', updatePayload.data.name);
|
||||
expect(attributes).toHaveProperty('description', target.description);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -241,12 +241,7 @@ export default ({ action, ability, model }: any) => {
|
||||
|
||||
const nonVisibleWritableAttributes = intersection(nonVisibleAttributes, writableAttributes);
|
||||
|
||||
return uniq([
|
||||
...fields,
|
||||
...STATIC_FIELDS,
|
||||
...COMPONENT_FIELDS,
|
||||
...nonVisibleWritableAttributes,
|
||||
]);
|
||||
return uniq([...fields, ...COMPONENT_FIELDS, ...nonVisibleWritableAttributes]);
|
||||
};
|
||||
|
||||
const getOutputFields = (fields = []) => {
|
||||
|
||||
@ -118,7 +118,7 @@ export default ({ action, ability, model }: any) => {
|
||||
const wrapValidate = (createValidateFunction: any) => {
|
||||
// TODO
|
||||
// @ts-expect-error define the correct return type
|
||||
const wrappedValidate = async (data, options = {}) => {
|
||||
const wrappedValidate = async (data, options = {}): Promise<unknown> => {
|
||||
if (isArray(data)) {
|
||||
return Promise.all(data.map((entity: unknown) => wrappedValidate(entity, options)));
|
||||
}
|
||||
@ -187,12 +187,7 @@ export default ({ action, ability, model }: any) => {
|
||||
|
||||
const nonVisibleWritableAttributes = intersection(nonVisibleAttributes, writableAttributes);
|
||||
|
||||
return uniq([
|
||||
...fields,
|
||||
...STATIC_FIELDS,
|
||||
...COMPONENT_FIELDS,
|
||||
...nonVisibleWritableAttributes,
|
||||
]);
|
||||
return uniq([...fields, ...COMPONENT_FIELDS, ...nonVisibleWritableAttributes]);
|
||||
};
|
||||
|
||||
const getQueryFields = (fields = []) => {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { CurriedFunction1 } from 'lodash';
|
||||
import { isArray, cloneDeep } from 'lodash/fp';
|
||||
import { isArray, cloneDeep, omit } from 'lodash/fp';
|
||||
|
||||
import { getNonWritableAttributes } from '../content-types';
|
||||
import { pipeAsync } from '../async';
|
||||
@ -34,7 +34,9 @@ const createContentAPISanitizers = () => {
|
||||
const nonWritableAttributes = getNonWritableAttributes(schema);
|
||||
|
||||
const transforms = [
|
||||
// Remove non writable attributes
|
||||
// Remove first level ID in inputs
|
||||
omit('id'),
|
||||
// Remove non-writable attributes
|
||||
traverseEntity(visitors.removeRestrictedFields(nonWritableAttributes), { schema }),
|
||||
];
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { CurriedFunction1 } from 'lodash';
|
||||
import { isArray } from 'lodash/fp';
|
||||
import { isArray, isObject } from 'lodash/fp';
|
||||
|
||||
import { getNonWritableAttributes } from '../content-types';
|
||||
import { pipeAsync } from '../async';
|
||||
import { throwInvalidParam } from './utils';
|
||||
|
||||
import * as visitors from './visitors';
|
||||
import * as validators from './validators';
|
||||
@ -37,7 +38,12 @@ const createContentAPIValidators = () => {
|
||||
const nonWritableAttributes = getNonWritableAttributes(schema);
|
||||
|
||||
const transforms = [
|
||||
// non writable attributes
|
||||
(data: unknown) => {
|
||||
if (isObject(data) && 'id' in data) {
|
||||
throwInvalidParam({ key: 'id' });
|
||||
}
|
||||
},
|
||||
// non-writable attributes
|
||||
traverseEntity(visitors.throwRestrictedFields(nonWritableAttributes), { schema }),
|
||||
];
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user