use transformParamsToQuery

This commit is contained in:
Pierre Noël 2022-08-16 19:36:10 +02:00
parent 796350533e
commit 9d23799b5d
4 changed files with 114 additions and 111 deletions

View File

@ -1,13 +1,22 @@
'use strict';
const { prop, isEmpty, isNil } = require('lodash/fp');
const { convertFiltersQueryParams } = require('@strapi/utils/lib/convert-query-params');
const { prop, isEmpty, defaultsDeep } = require('lodash/fp');
const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
const { PUBLISHED_AT_ATTRIBUTE } = require('@strapi/utils').contentTypes.constants;
const { transformParamsToQuery } = require('@strapi/utils/lib/convert-query-params');
const { getService } = require('../utils');
const { validateFindAvailable } = require('./validation/relations');
const addWhereClause = (params, whereClause) => {
params.where = params.where || {};
if (Array.isArray(params.where)) {
params.where.push(whereClause);
} else {
params.where = [params.where, whereClause];
}
};
module.exports = {
async findAvailable(ctx) {
const { userAbility } = ctx.state;
@ -15,7 +24,7 @@ module.exports = {
await validateFindAvailable(ctx.request.query);
const { component, entityId, idsToOmit, page = 1, pageSize = 10, _q } = ctx.request.query;
const { component, entityId, idsToOmit, ...query } = ctx.request.query;
const sourceModelUid = component || model;
@ -64,26 +73,18 @@ module.exports = {
fieldsToSelect.push(PUBLISHED_AT_ATTRIBUTE);
}
const queryParams = {
where: { $and: [] },
select: fieldsToSelect,
orderBy: mainField,
page,
pageSize,
};
if (!isNil(_q)) {
queryParams._q = _q;
}
if (!isNil(ctx.request.query.filters)) {
queryParams.where.$and.push(
convertFiltersQueryParams(ctx.request.query.filters, targetedModel).filters
);
}
const queryParams = defaultsDeep(
{
orderBy: mainField,
},
{
...transformParamsToQuery(targetedModel.uid, query), // ⚠️ Mmmh should not be able to filter for RBAC reasons
select: fieldsToSelect, // cannot select other fields as the user may not have the permissions
}
);
if (!isEmpty(idsToOmit)) {
queryParams.where.$and.push({ id: { $notIn: idsToOmit } });
addWhereClause(queryParams, { id: { $notIn: idsToOmit } });
}
if (entityId) {
@ -97,7 +98,7 @@ module.exports = {
.select(`${alias}.id`)
.getKnexQuery();
queryParams.where.$and.push({ id: { $notIn: knexSubQuery } });
addWhereClause(queryParams, { id: { $notIn: knexSubQuery } });
}
const results = await strapi.query(targetedModel.uid).findPage(queryParams);

View File

@ -10,6 +10,7 @@ const {
sanitize,
} = require('@strapi/utils');
const { ValidationError } = require('@strapi/utils').errors;
const { transformParamsToQuery } = require('@strapi/utils/lib/convert-query-params');
const uploadFiles = require('../utils/upload-files');
const {
@ -18,7 +19,7 @@ const {
updateComponents,
deleteComponents,
} = require('./components');
const { transformParamsToQuery, pickSelectionParams } = require('./params');
const { pickSelectionParams } = require('./params');
const { applyTransforms } = require('./attributes');
// TODO: those should be strapi events used by the webhooks not the other way arround

View File

@ -1,95 +1,9 @@
'use strict';
const { pick, isNil, toNumber, isInteger } = require('lodash/fp');
const { PaginationError } = require('@strapi/utils').errors;
const {
convertSortQueryParams,
convertLimitQueryParams,
convertStartQueryParams,
convertPopulateQueryParams,
convertFiltersQueryParams,
convertFieldsQueryParams,
convertPublicationStateParams,
} = require('@strapi/utils/lib/convert-query-params');
const { pick } = require('lodash/fp');
const pickSelectionParams = pick(['fields', 'populate']);
const transformParamsToQuery = (uid, params) => {
// NOTE: can be a CT, a Compo or nothing in the case of polymorphism (DZ & morph relations)
const schema = strapi.getModel(uid);
const query = {};
const { _q, sort, filters, fields, populate, page, pageSize, start, limit } = params;
if (!isNil(_q)) {
query._q = _q;
}
if (!isNil(sort)) {
query.orderBy = convertSortQueryParams(sort);
}
if (!isNil(filters)) {
query.where = convertFiltersQueryParams(filters, schema);
}
if (!isNil(fields)) {
query.select = convertFieldsQueryParams(fields);
}
if (!isNil(populate)) {
query.populate = convertPopulateQueryParams(populate, schema);
}
const isPagePagination = !isNil(page) || !isNil(pageSize);
const isOffsetPagination = !isNil(start) || !isNil(limit);
if (isPagePagination && isOffsetPagination) {
throw new PaginationError(
'Invalid pagination attributes. You cannot use page and offset pagination in the same query'
);
}
if (!isNil(page)) {
const pageVal = toNumber(page);
if (!isInteger(pageVal) || pageVal <= 0) {
throw new PaginationError(
`Invalid 'page' parameter. Expected an integer > 0, received: ${page}`
);
}
query.page = pageVal;
}
if (!isNil(pageSize)) {
const pageSizeVal = toNumber(pageSize);
if (!isInteger(pageSizeVal) || pageSizeVal <= 0) {
throw new PaginationError(
`Invalid 'pageSize' parameter. Expected an integer > 0, received: ${page}`
);
}
query.pageSize = pageSizeVal;
}
if (!isNil(start)) {
query.offset = convertStartQueryParams(start);
}
if (!isNil(limit)) {
query.limit = convertLimitQueryParams(limit);
}
convertPublicationStateParams(schema, params, query);
return query;
};
module.exports = {
transformParamsToQuery,
pickSelectionParams,
};

View File

@ -6,10 +6,22 @@
* Converts the standard Strapi REST query params to a more usable format for querying
* You can read more here: https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#filters
*/
const { has, isEmpty, isObject, isPlainObject, cloneDeep, get, mergeAll } = require('lodash/fp');
const {
has,
isEmpty,
isObject,
isPlainObject,
cloneDeep,
get,
mergeAll,
isNil,
toNumber,
isInteger,
} = require('lodash/fp');
const _ = require('lodash');
const parseType = require('./parse-type');
const contentTypesUtils = require('./content-types');
const { PaginationError } = require('./errors');
const { PUBLISHED_AT_ATTRIBUTE } = contentTypesUtils.constants;
@ -389,6 +401,80 @@ const convertPublicationStateParams = (type, params = {}, query = {}) => {
}
};
const transformParamsToQuery = (uid, params) => {
// NOTE: can be a CT, a Compo or nothing in the case of polymorphism (DZ & morph relations)
const schema = strapi.getModel(uid);
const query = {};
const { _q, sort, filters, fields, populate, page, pageSize, start, limit } = params;
if (!isNil(_q)) {
query._q = _q;
}
if (!isNil(sort)) {
query.orderBy = convertSortQueryParams(sort);
}
if (!isNil(filters)) {
query.where = convertFiltersQueryParams(filters, schema);
}
if (!isNil(fields)) {
query.select = convertFieldsQueryParams(fields);
}
if (!isNil(populate)) {
query.populate = convertPopulateQueryParams(populate, schema);
}
const isPagePagination = !isNil(page) || !isNil(pageSize);
const isOffsetPagination = !isNil(start) || !isNil(limit);
if (isPagePagination && isOffsetPagination) {
throw new PaginationError(
'Invalid pagination attributes. You cannot use page and offset pagination in the same query'
);
}
if (!isNil(page)) {
const pageVal = toNumber(page);
if (!isInteger(pageVal) || pageVal <= 0) {
throw new PaginationError(
`Invalid 'page' parameter. Expected an integer > 0, received: ${page}`
);
}
query.page = pageVal;
}
if (!isNil(pageSize)) {
const pageSizeVal = toNumber(pageSize);
if (!isInteger(pageSizeVal) || pageSizeVal <= 0) {
throw new PaginationError(
`Invalid 'pageSize' parameter. Expected an integer > 0, received: ${page}`
);
}
query.pageSize = pageSizeVal;
}
if (!isNil(start)) {
query.offset = convertStartQueryParams(start);
}
if (!isNil(limit)) {
query.limit = convertLimitQueryParams(limit);
}
convertPublicationStateParams(schema, params, query);
return query;
};
module.exports = {
convertSortQueryParams,
convertStartQueryParams,
@ -397,4 +483,5 @@ module.exports = {
convertFiltersQueryParams,
convertFieldsQueryParams,
convertPublicationStateParams,
transformParamsToQuery,
};