From c00645f259e28175ee3de775feb51d902c30e45c Mon Sep 17 00:00:00 2001 From: rijkvanzanten Date: Tue, 30 Jun 2020 14:45:54 -0400 Subject: [PATCH] Add GET /collections endpoint --- src/app.ts | 2 ++ src/database.ts | 4 ++++ src/middleware/sanitize-query.ts | 2 +- src/middleware/validate-query.ts | 4 ++-- src/routes/collections.ts | 41 ++++++++++++++++++++++++++++++++ src/routes/users.ts | 27 +++++++++++---------- src/routes/webhooks.ts | 12 ++++++---- src/services/items.ts | 5 +++- src/types/collection.ts | 8 +++++++ src/types/express.d.ts | 1 + 10 files changed, 85 insertions(+), 21 deletions(-) create mode 100644 src/routes/collections.ts create mode 100644 src/types/collection.ts diff --git a/src/app.ts b/src/app.ts index 15a16bff60..6caf032162 100644 --- a/src/app.ts +++ b/src/app.ts @@ -13,6 +13,7 @@ import authenticate from './middleware/authenticate'; import activityRouter from './routes/activity'; import assetsRouter from './routes/assets'; import authRouter from './routes/auth'; +import collectionsRouter from './routes/collections'; import collectionPresetsRouter from './routes/collection-presets'; import extensionsRouter from './routes/extensions'; import filesRouter from './routes/files'; @@ -39,6 +40,7 @@ const app = express() .use('/activity', activityRouter) .use('/assets', assetsRouter) .use('/auth', authRouter) + .use('/collections', collectionsRouter) .use('/collection_presets', collectionPresetsRouter) .use('/extensions', extensionsRouter) .use('/files', filesRouter) diff --git a/src/database.ts b/src/database.ts index 0832c4cc8d..8f7ea4e148 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,6 +1,8 @@ import knex from 'knex'; import logger from './logger'; +import SchemaInspector from '../../../knex-schema-inspector/lib/index'; + const log = logger.child({ module: 'sql' }); const database = knex({ @@ -16,4 +18,6 @@ const database = knex({ database.on('query', (data) => log.trace(data.sql)); +export const schemaInspector = SchemaInspector(database); + export default database; diff --git a/src/middleware/sanitize-query.ts b/src/middleware/sanitize-query.ts index e82cb0c119..1c332c6b10 100644 --- a/src/middleware/sanitize-query.ts +++ b/src/middleware/sanitize-query.ts @@ -44,7 +44,7 @@ const sanitizeQuery: RequestHandler = (req, res, next) => { query.meta = sanitizeMeta(req.query.meta); } - res.locals.query = query; + req.sanitizedQuery = query; return next(); }; diff --git a/src/middleware/validate-query.ts b/src/middleware/validate-query.ts index 51dd85d2ce..5689b52057 100644 --- a/src/middleware/validate-query.ts +++ b/src/middleware/validate-query.ts @@ -13,9 +13,9 @@ import { InvalidQueryException } from '../exceptions'; const validateQuery: RequestHandler = asyncHandler(async (req, res, next) => { if (!req.collection) return next(); - if (!req.query) return next(); + if (!req.sanitizedQuery) return next(); - const query: Query = req.query; + const query: Query = req.sanitizedQuery; await Promise.all([ validateParams(req.params.collection, query), diff --git a/src/routes/collections.ts b/src/routes/collections.ts new file mode 100644 index 0000000000..6212d2fdf9 --- /dev/null +++ b/src/routes/collections.ts @@ -0,0 +1,41 @@ +import { Router } from 'express'; +import asyncHandler from 'express-async-handler'; +import database, { schemaInspector } from '../database'; +import * as ItemsService from '../services/items'; +import sanitizeQuery from '../middleware/sanitize-query'; +import validateQuery from '../middleware/validate-query'; +import { Table } from '../../../../knex-schema-inspector/lib/types/table'; +import { Collection } from '../types/collection'; + +const router = Router(); + +router.get( + '/', + sanitizeQuery, + validateQuery, + asyncHandler(async (req, res) => { + const [tables, collections] = await Promise.all([ + schemaInspector.tables(), + ItemsService.readItems('directus_collections', req.sanitizedQuery), + ]); + + const data = (tables as Table[]).map((table) => { + const collectionInfo = collections.find((collection) => { + return collection.collection === table.name; + }); + + return { + collection: table.name, + note: table.comment, + hidden: collectionInfo?.hidden || false, + single: collectionInfo?.single || false, + icon: collectionInfo?.icon || null, + translation: collectionInfo?.translation || null, + }; + }); + + res.json({ data }); + }) +); + +export default router; diff --git a/src/routes/users.ts b/src/routes/users.ts index 3957276c08..d6ff89ea39 100644 --- a/src/routes/users.ts +++ b/src/routes/users.ts @@ -37,15 +37,6 @@ router.get( asyncHandler(async (req, res) => { const item = await UsersService.readUsers(res.locals.query); - ActivityService.createActivity({ - action: ActivityService.Action.UPDATE, - collection: req.collection, - item: item.id, - ip: req.ip, - user_agent: req.get('user-agent'), - action_by: req.user, - }); - return res.json({ data: item }); }) ); @@ -56,8 +47,8 @@ router.get( sanitizeQuery, validateQuery, asyncHandler(async (req, res) => { - const record = await UsersService.readUser(req.params.pk, res.locals.query); - return res.json({ data: record }); + const items = await UsersService.readUser(req.params.pk, res.locals.query); + return res.json({ data: items }); }) ); @@ -65,8 +56,18 @@ router.patch( '/:pk', useCollection('directus_users'), asyncHandler(async (req, res) => { - const records = await UsersService.updateUser(req.params.pk, req.body, res.locals.query); - return res.json({ data: records }); + const item = await UsersService.updateUser(req.params.pk, req.body, res.locals.query); + + ActivityService.createActivity({ + action: ActivityService.Action.UPDATE, + collection: req.collection, + item: item.id, + ip: req.ip, + user_agent: req.get('user-agent'), + action_by: req.user, + }); + + return res.json({ data: item }); }) ); diff --git a/src/routes/webhooks.ts b/src/routes/webhooks.ts index 4c93138906..6689630378 100644 --- a/src/routes/webhooks.ts +++ b/src/routes/webhooks.ts @@ -12,7 +12,7 @@ router.post( '/', useCollection('directus_webhooks'), asyncHandler(async (req, res) => { - const item = await WebhooksService.createWebhook(req.body, req.query); + const item = await WebhooksService.createWebhook(req.body, req.sanitizedQuery); ActivityService.createActivity({ action: ActivityService.Action.CREATE, @@ -33,7 +33,7 @@ router.get( sanitizeQuery, validateQuery, asyncHandler(async (req, res) => { - const records = await WebhooksService.readWebhooks(req.query); + const records = await WebhooksService.readWebhooks(req.sanitizedQuery); return res.json({ data: records }); }) ); @@ -44,7 +44,7 @@ router.get( sanitizeQuery, validateQuery, asyncHandler(async (req, res) => { - const record = await WebhooksService.readWebhook(req.params.pk, req.query); + const record = await WebhooksService.readWebhook(req.params.pk, req.sanitizedQuery); return res.json({ data: record }); }) ); @@ -53,7 +53,11 @@ router.patch( '/:pk', useCollection('directus_webhooks'), asyncHandler(async (req, res) => { - const item = await WebhooksService.updateWebhook(req.params.pk, req.body, req.query); + const item = await WebhooksService.updateWebhook( + req.params.pk, + req.body, + req.sanitizedQuery + ); ActivityService.createActivity({ action: ActivityService.Action.UPDATE, diff --git a/src/services/items.ts b/src/services/items.ts index 25ba488f04..79333bb4bb 100644 --- a/src/services/items.ts +++ b/src/services/items.ts @@ -10,7 +10,10 @@ export const createItem = async ( return readItem(collection, result[0], query); }; -export const readItems = async (collection: string, query: Query = {}) => { +export const readItems = async >( + collection: string, + query: Query = {} +): Promise => { const dbQuery = database.select(query?.fields || '*').from(collection); if (query.sort) { diff --git a/src/types/collection.ts b/src/types/collection.ts new file mode 100644 index 0000000000..929320fd72 --- /dev/null +++ b/src/types/collection.ts @@ -0,0 +1,8 @@ +export type Collection = { + collection: string; + note: string | null; + hidden: boolean; + single: boolean; + icon: string | null; + translation: Record; +}; diff --git a/src/types/express.d.ts b/src/types/express.d.ts index 392b1aabd4..01ba743a4e 100644 --- a/src/types/express.d.ts +++ b/src/types/express.d.ts @@ -11,6 +11,7 @@ declare global { user?: string; role?: string; collection?: string; + sanitizedQuery?: Record; } } }