mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Allow deep query
This commit is contained in:
@@ -4,15 +4,13 @@
|
||||
*/
|
||||
|
||||
import { RequestHandler } from 'express';
|
||||
import { Accountability, Query, Sort, Filter, Meta } from '../types';
|
||||
import logger from '../logger';
|
||||
import { parseFilter } from '../utils/parse-filter';
|
||||
import { sanitizeQuery } from '../utils/sanitize-query';
|
||||
|
||||
const sanitizeQuery: RequestHandler = (req, res, next) => {
|
||||
const sanitizeQueryMiddleware: RequestHandler = (req, res, next) => {
|
||||
req.sanitizedQuery = {};
|
||||
if (!req.query) return;
|
||||
|
||||
req.sanitizedQuery = sanitize(
|
||||
req.sanitizedQuery = sanitizeQuery(
|
||||
{
|
||||
fields: req.query.fields || '*',
|
||||
...req.query
|
||||
@@ -25,143 +23,5 @@ const sanitizeQuery: RequestHandler = (req, res, next) => {
|
||||
return next();
|
||||
};
|
||||
|
||||
function sanitize(rawQuery: Record<string, any>, accountability: Accountability | null) {
|
||||
const query: Query = {};
|
||||
export default sanitizeQueryMiddleware;
|
||||
|
||||
if (rawQuery.limit !== undefined) {
|
||||
const limit = sanitizeLimit(rawQuery.limit);
|
||||
|
||||
if (typeof limit === 'number') {
|
||||
query.limit = limit;
|
||||
}
|
||||
}
|
||||
|
||||
if (rawQuery.fields) {
|
||||
query.fields = sanitizeFields(rawQuery.fields);
|
||||
}
|
||||
|
||||
if (rawQuery.sort) {
|
||||
query.sort = sanitizeSort(rawQuery.sort);
|
||||
}
|
||||
|
||||
if (rawQuery.filter) {
|
||||
query.filter = sanitizeFilter(rawQuery.filter, accountability || null);
|
||||
}
|
||||
|
||||
if (rawQuery.limit == '-1') {
|
||||
delete query.limit;
|
||||
}
|
||||
|
||||
if (rawQuery.offset) {
|
||||
query.offset = sanitizeOffset(rawQuery.offset);
|
||||
}
|
||||
|
||||
if (rawQuery.page) {
|
||||
query.page = sanitizePage(rawQuery.page);
|
||||
}
|
||||
|
||||
if (rawQuery.single) {
|
||||
query.single = sanitizeSingle(rawQuery.single);
|
||||
}
|
||||
|
||||
if (rawQuery.meta) {
|
||||
query.meta = sanitizeMeta(rawQuery.meta);
|
||||
}
|
||||
|
||||
if (rawQuery.search && typeof rawQuery.search === 'string') {
|
||||
query.search = rawQuery.search;
|
||||
}
|
||||
|
||||
if (
|
||||
rawQuery.export &&
|
||||
typeof rawQuery.export === 'string' &&
|
||||
['json', 'csv'].includes(rawQuery.export)
|
||||
) {
|
||||
query.export = rawQuery.export as 'json' | 'csv';
|
||||
}
|
||||
|
||||
if (rawQuery.deep as Record<string, any>) {
|
||||
if (!query.deep) query.deep = {};
|
||||
|
||||
for (const [field, deepRawQuery] of Object.entries(rawQuery.deep)) {
|
||||
query.deep[field] = sanitize(deepRawQuery as any, accountability);
|
||||
}
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
export default sanitizeQuery;
|
||||
|
||||
function sanitizeFields(rawFields: any) {
|
||||
if (!rawFields) return;
|
||||
|
||||
let fields: string[] = [];
|
||||
|
||||
if (typeof rawFields === 'string') fields = rawFields.split(',');
|
||||
else if (Array.isArray(rawFields)) fields = rawFields as string[];
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
function sanitizeSort(rawSort: any) {
|
||||
let fields: string[] = [];
|
||||
|
||||
if (typeof rawSort === 'string') fields = rawSort.split(',');
|
||||
else if (Array.isArray(rawSort)) fields = rawSort as string[];
|
||||
|
||||
return fields.map((field) => {
|
||||
const order = field.startsWith('-') ? 'desc' : 'asc';
|
||||
const column = field.startsWith('-') ? field.substring(1) : field;
|
||||
return { column, order } as Sort;
|
||||
});
|
||||
}
|
||||
|
||||
function sanitizeFilter(rawFilter: any, accountability: Accountability | null) {
|
||||
let filters: Filter = rawFilter;
|
||||
|
||||
if (typeof rawFilter === 'string') {
|
||||
try {
|
||||
filters = JSON.parse(rawFilter);
|
||||
} catch {
|
||||
logger.warn('Invalid value passed for filter query parameter.');
|
||||
}
|
||||
}
|
||||
|
||||
filters = parseFilter(filters, accountability);
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
function sanitizeLimit(rawLimit: any) {
|
||||
if (rawLimit === undefined || rawLimit === null) return null;
|
||||
return Number(rawLimit);
|
||||
}
|
||||
|
||||
function sanitizeOffset(rawOffset: any) {
|
||||
return Number(rawOffset);
|
||||
}
|
||||
|
||||
function sanitizePage(rawPage: any) {
|
||||
return Number(rawPage);
|
||||
}
|
||||
|
||||
function sanitizeSingle(rawSingle: any) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function sanitizeMeta(rawMeta: any) {
|
||||
if (rawMeta === '*') {
|
||||
return Object.values(Meta);
|
||||
}
|
||||
|
||||
if (rawMeta.includes(',')) {
|
||||
return rawMeta.split(',');
|
||||
}
|
||||
|
||||
if (Array.isArray(rawMeta)) {
|
||||
return rawMeta;
|
||||
}
|
||||
|
||||
return [rawMeta];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user