mirror of
https://github.com/directus/directus.git
synced 2026-02-10 18:34:58 -05:00
Add query validator to check for field existence
This commit is contained in:
@@ -3,11 +3,13 @@ import logger from './logger';
|
||||
|
||||
export enum ErrorCode {
|
||||
NOT_FOUND = 'NOT_FOUND',
|
||||
FIELD_NOT_FOUND = 'FIELD_NOT_FOUND',
|
||||
INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR',
|
||||
}
|
||||
|
||||
enum HTTPStatus {
|
||||
NOT_FOUND = 404,
|
||||
FIELD_NOT_FOUND = 400,
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import pino from "pino";
|
||||
import pino from 'pino';
|
||||
|
||||
const logger = pino();
|
||||
const logger = pino({ level: process.env.LOG_LEVEL || 'info' });
|
||||
|
||||
export default logger;
|
||||
|
||||
@@ -8,7 +8,10 @@ const collectionExists: RequestHandler = asyncHandler(async (req, res, next) =>
|
||||
|
||||
const exists = await database.schema.hasTable(req.params.collection);
|
||||
|
||||
if (exists) return next();
|
||||
if (exists) {
|
||||
res.locals.collection = req.params.collection;
|
||||
return next();
|
||||
}
|
||||
|
||||
throw new APIError(ErrorCode.NOT_FOUND, `Collection "${req.params.collection}" doesn't exist.`);
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import { RequestHandler } from 'express';
|
||||
import { Query } from '../types/query';
|
||||
import logger from '../logger';
|
||||
|
||||
const sanitizeQuery: RequestHandler = (req, res, next) => {
|
||||
if (!req.query) return;
|
||||
|
||||
47
src/middleware/validate-query.ts
Normal file
47
src/middleware/validate-query.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Validates query parameters.
|
||||
* We'll check if all fields you're trying to access exist
|
||||
*
|
||||
* This has to be run after sanitizeQuery
|
||||
*/
|
||||
|
||||
import { RequestHandler } from 'express';
|
||||
import { Query } from '../types/query';
|
||||
import { hasField } from '../services/schema';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
import APIError, { ErrorCode } from '../error';
|
||||
|
||||
const validateQuery: RequestHandler = asyncHandler(async (req, res, next) => {
|
||||
if (!res.locals.collection) return next();
|
||||
if (!res.locals.query) return next();
|
||||
|
||||
const query: Query = res.locals.query;
|
||||
|
||||
const fieldsToCheck = new Set<string>();
|
||||
|
||||
if (query.fields) {
|
||||
query.fields.forEach((field) => fieldsToCheck.add(field));
|
||||
}
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
Array.from(fieldsToCheck).map(
|
||||
(field) =>
|
||||
new Promise(async (resolve, reject) => {
|
||||
const exists = await hasField(res.locals.collection, field);
|
||||
if (exists) return resolve();
|
||||
return reject({ collection: res.locals.collection, field: field });
|
||||
})
|
||||
)
|
||||
);
|
||||
} catch ({ collection, field }) {
|
||||
throw new APIError(
|
||||
ErrorCode.FIELD_NOT_FOUND,
|
||||
`Field "${field}" doesn't exist in "${collection}"`
|
||||
);
|
||||
}
|
||||
|
||||
return next();
|
||||
});
|
||||
|
||||
export default validateQuery;
|
||||
@@ -3,6 +3,7 @@ import asyncHandler from 'express-async-handler';
|
||||
import { createItem, readItems, readItem, updateItem, deleteItem } from '../services/items';
|
||||
import sanitizeQuery from '../middleware/sanitize-query';
|
||||
import collectionExists from '../middleware/collection-exists';
|
||||
import validateQuery from '../middleware/validate-query';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -19,6 +20,7 @@ router.get(
|
||||
'/:collection',
|
||||
collectionExists,
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
const records = await readItems(req.params.collection, res.locals.query);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import database from '../database';
|
||||
import { Query } from '../types/query';
|
||||
import logger from '../logger';
|
||||
|
||||
export const createItem = async (
|
||||
collection: string,
|
||||
|
||||
@@ -3,3 +3,7 @@ import database from '../database';
|
||||
export const hasCollection = async (collection: string) => {
|
||||
return await database.schema.hasTable(collection);
|
||||
};
|
||||
|
||||
export const hasField = async (collection: string, field: string) => {
|
||||
return await database.schema.hasColumn(collection, field);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user