diff --git a/packages/strapi-database/lib/constants/index.js b/packages/strapi-database/lib/constants/index.js index 0e0bffa897..68c7f54687 100644 --- a/packages/strapi-database/lib/constants/index.js +++ b/packages/strapi-database/lib/constants/index.js @@ -24,8 +24,6 @@ const RESERVED_ATTRIBUTE_NAMES = [ 'attributes', 'relations', 'changed', - 'page', - 'pageSize', // list found here https://mongoosejs.com/docs/api.html#schema_Schema.reserved '_posts', diff --git a/packages/strapi-database/lib/queries/paginated-queries.js b/packages/strapi-database/lib/queries/paginated-queries.js index 34c30d0308..eff74597e9 100644 --- a/packages/strapi-database/lib/queries/paginated-queries.js +++ b/packages/strapi-database/lib/queries/paginated-queries.js @@ -35,8 +35,8 @@ const withDefaultPagination = params => { const { page = 1, pageSize = 100, ...rest } = params; return { - page: Math.max(1, parseInt(page)) || 1, - pageSize: Math.max(1, parseInt(pageSize)) || 100, + page: parseInt(page), + pageSize: parseInt(pageSize), ...rest, }; }; diff --git a/packages/strapi-plugin-content-manager/controllers/collection-types.js b/packages/strapi-plugin-content-manager/controllers/collection-types.js index 101d112f49..23cab14fe1 100644 --- a/packages/strapi-plugin-content-manager/controllers/collection-types.js +++ b/packages/strapi-plugin-content-manager/controllers/collection-types.js @@ -9,7 +9,7 @@ const { pickWritableAttributes, } = require('../utils'); const { MANY_RELATIONS } = require('../services/constants'); -const { validateBulkDeleteInput } = require('./validation'); +const { validateBulkDeleteInput, validatePagination } = require('./validation'); module.exports = { async find(ctx) { @@ -232,6 +232,8 @@ module.exports = { const { model, id, targetField } = ctx.params; const { pageSize = 10, page = 1 } = ctx.request.query; + validatePagination({ page, pageSize }); + const contentTypeService = getService('content-types'); const entityManager = getService('entity-manager'); const permissionChecker = getService('permission-checker').create({ userAbility, model }); @@ -276,7 +278,7 @@ module.exports = { ctx.body = { pagination: relationList.pagination, - results: relationList.results.map(pick(['id', 'ids', settings.mainField])), + results: relationList.results.map(pick(['id', modelDef.primaryKey, settings.mainField])), }; }, }; diff --git a/packages/strapi-plugin-content-manager/controllers/validation/index.js b/packages/strapi-plugin-content-manager/controllers/validation/index.js index 5f73c094c6..2f4bae8a1a 100644 --- a/packages/strapi-plugin-content-manager/controllers/validation/index.js +++ b/packages/strapi-plugin-content-manager/controllers/validation/index.js @@ -88,6 +88,18 @@ const validateUIDField = (contentTypeUID, field) => { } }; +const validatePagination = ({ page, pageSize }) => { + const pageNumber = parseInt(page); + const pageSizeNumber = parseInt(pageSize); + + if (isNaN(pageNumber) || pageNumber < 1) { + throw strapi.errors.badRequest('invalid pageNumber param'); + } + if (isNaN(pageSizeNumber) || pageSizeNumber < 1) { + throw strapi.errors.badRequest('invalid pageSize param'); + } +}; + module.exports = { createModelConfigurationSchema, validateKind, @@ -95,4 +107,5 @@ module.exports = { validateGenerateUIDInput, validateCheckUIDAvailabilityInput, validateUIDField, + validatePagination, }; diff --git a/packages/strapi-plugin-content-manager/test/api/x-to-many-rf-preview.test.e2e.js b/packages/strapi-plugin-content-manager/test/api/x-to-many-rf-preview.test.e2e.js index 91eb8f6f53..5050a7a164 100644 --- a/packages/strapi-plugin-content-manager/test/api/x-to-many-rf-preview.test.e2e.js +++ b/packages/strapi-plugin-content-manager/test/api/x-to-many-rf-preview.test.e2e.js @@ -5,6 +5,9 @@ const { registerAndLogin } = require('../../../../test/helpers/auth'); const createModelsUtils = require('../../../../test/helpers/models'); const { createAuthRequest } = require('../../../../test/helpers/request'); +const toIds = arr => uniq(map(prop('id'))(arr)); +const getFrom = model => (start, end) => fixtures[model].map(prop('name')).slice(start, end); + let rq; let modelsUtils; const data = { @@ -88,8 +91,6 @@ const fixtures = { product: () => { const { shop, category } = data; - const getFrom = model => (start, end) => fixtures[model].map(prop('name')).slice(start, end); - const items = [ { name: 'PD.A', categories: getFrom('category')(0, 5), shops: getFrom('shop')(0, 12) }, ]; @@ -176,12 +177,11 @@ describe('x-to-many RF Preview', () => { }); describe('Default Behavior', () => { - test.each(['shops', 'categories'])('Should returns a preview for the %s field', async field => { + test.each(['shops', 'categories'])('Should return a preview for the %s field', async field => { const product = data.product[0]; const { body, statusCode } = await rq.get(`${cmProductUrl}/${product.id}/${field}`); - const toIds = arr => uniq(map(prop('id'))(arr)); const expected = product[field].slice(0, 10); expect(statusCode).toBe(200);