parse boolean in convertQueryParam instead of parsing in database

This commit is contained in:
Pierre Noël 2022-02-10 13:12:16 +01:00
parent 7a21beefcd
commit c2b8a4ee98
4 changed files with 42 additions and 39 deletions

View File

@ -3,7 +3,6 @@
const _ = require('lodash/fp'); const _ = require('lodash/fp');
const dateFns = require('date-fns'); const dateFns = require('date-fns');
const { InvalidTimeError, InvalidDateError, InvalidDateTimeError } = require('./errors'); const { InvalidTimeError, InvalidDateError, InvalidDateTimeError } = require('./errors');
const { parseBoolean } = require('./utils/boolean');
class Field { class Field {
constructor(config) { constructor(config) {
@ -42,7 +41,17 @@ class JSONField extends Field {
class BooleanField extends Field { class BooleanField extends Field {
toDB(value) { toDB(value) {
return parseBoolean(value); if (typeof value === 'boolean') return value;
if (['true', 't', '1', 1].includes(value)) {
return true;
}
if (['false', 'f', '0', 0].includes(value)) {
return false;
}
return Boolean(value);
} }
fromDB(value) { fromDB(value) {

View File

@ -3,7 +3,6 @@
const _ = require('lodash/fp'); const _ = require('lodash/fp');
const types = require('../../types'); const types = require('../../types');
const { parseBoolean } = require('../../utils/boolean');
const { createField } = require('../../fields'); const { createField } = require('../../fields');
const { createJoin } = require('./join'); const { createJoin } = require('./join');
const { toColumnName } = require('./transform'); const { toColumnName } = require('./transform');
@ -248,7 +247,7 @@ const applyOperator = (qb, column, operator, value) => {
break; break;
} }
case '$null': { case '$null': {
if (parseBoolean(value)) { if (value) {
qb.whereNull(column); qb.whereNull(column);
} else { } else {
qb.whereNotNull(column); qb.whereNotNull(column);
@ -256,7 +255,7 @@ const applyOperator = (qb, column, operator, value) => {
break; break;
} }
case '$notNull': { case '$notNull': {
if (parseBoolean(value)) { if (value) {
qb.whereNotNull(column); qb.whereNotNull(column);
} else { } else {
qb.whereNull(column); qb.whereNull(column);

View File

@ -1,19 +0,0 @@
'use strict';
const parseBoolean = value => {
if (typeof value === 'boolean') return value;
if (['true', 't', '1', 1].includes(value)) {
return true;
}
if (['false', 'f', '0', 0].includes(value)) {
return false;
}
return Boolean(value);
};
module.exports = {
parseBoolean,
};

View File

@ -4,10 +4,11 @@
* Converts the standard Strapi REST query params to a more usable format for querying * 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 * 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, cloneDeep } = require('lodash/fp'); const { has, isEmpty, isObject, cloneDeep, get } = require('lodash/fp');
const _ = require('lodash'); const _ = require('lodash');
const parseType = require('./parse-type'); const parseType = require('./parse-type');
const contentTypesUtils = require('./content-types'); const contentTypesUtils = require('./content-types');
const { ApplicationError } = require('./errors');
const { PUBLISHED_AT_ATTRIBUTE } = contentTypesUtils.constants; const { PUBLISHED_AT_ATTRIBUTE } = contentTypesUtils.constants;
@ -228,10 +229,10 @@ const convertFiltersQueryParams = (filters, schema) => {
// Don't mutate the original object // Don't mutate the original object
const filtersCopy = cloneDeep(filters); const filtersCopy = cloneDeep(filters);
return sanitizeFilters(filtersCopy, schema); return convertAndSanitizeFilters(filtersCopy, schema);
}; };
const sanitizeFilters = (filters, schema) => { const convertAndSanitizeFilters = (filters, schema) => {
if (!isObject(filters)) { if (!isObject(filters)) {
return filters; return filters;
} }
@ -240,7 +241,7 @@ const sanitizeFilters = (filters, schema) => {
return ( return (
filters filters
// Sanitize each filter // Sanitize each filter
.map(filter => sanitizeFilters(filter, schema)) .map(filter => convertAndSanitizeFilters(filter, schema))
// Filter out empty filters // Filter out empty filters
.filter(filter => !isObject(filter) || !isEmpty(filter)) .filter(filter => !isObject(filter) || !isEmpty(filter))
); );
@ -250,39 +251,52 @@ const sanitizeFilters = (filters, schema) => {
// Here, `key` can either be an operator or an attribute name // Here, `key` can either be an operator or an attribute name
for (const [key, value] of Object.entries(filters)) { for (const [key, value] of Object.entries(filters)) {
const attribute = schema.attributes[key]; const attribute = get('key', schema.attributes);
// Handle attributes // Handle attributes
if (attribute) { if (attribute) {
// Always remove password attributes from filters object
if (attribute.type === 'password') {
removeOperator(key);
}
// Relations // Relations
if (attribute.type === 'relation') { if (attribute.type === 'relation') {
filters[key] = sanitizeFilters(value, strapi.getModel(attribute.target)); filters[key] = convertAndSanitizeFilters(value, strapi.getModel(attribute.target));
} }
// Components // Components
else if (attribute.type === 'component') { else if (attribute.type === 'component') {
filters[key] = sanitizeFilters(value, strapi.getModel(attribute.component)); filters[key] = convertAndSanitizeFilters(value, strapi.getModel(attribute.component));
} }
// Media // Media
else if (attribute.type === 'media') { else if (attribute.type === 'media') {
filters[key] = sanitizeFilters(value, strapi.getModel('plugin::upload.file')); filters[key] = convertAndSanitizeFilters(value, strapi.getModel('plugin::upload.file'));
} }
// Dynamic Zones // Dynamic Zones
else if (attribute.type === 'dynamiczone') { else if (attribute.type === 'dynamiczone') {
removeOperator(key); removeOperator(key);
} }
// Scalar attributes
else {
// Always remove password attributes from filters object
if (attribute.type === 'password') {
removeOperator(key);
} else {
filters[key] = convertAndSanitizeFilters(value);
}
}
} }
// Handle operators // Handle operators
else if (isObject(value)) { else {
filters[key] = sanitizeFilters(value, schema); if (isObject(value)) {
filters[key] = convertAndSanitizeFilters(value, schema);
} else if (['$null', '$notNull'].includes(key)) {
try {
filters[key] = parseType({ type: 'boolean', value: filters[key], forceCast: true });
} catch (e) {
throw new ApplicationError(e.message);
}
}
} }
// Remove empty objects & arrays // Remove empty objects & arrays