From 2b50baa13de53b07d16b85810e316084342b4acf Mon Sep 17 00:00:00 2001 From: rijkvanzanten Date: Fri, 3 Jul 2020 16:41:53 -0400 Subject: [PATCH] Various fixes to address issues in app --- src/database/run-ast.ts | 144 +++---------------------------- src/middleware/validate-query.ts | 4 +- src/routes/auth.ts | 1 + src/routes/users.ts | 42 ++++++++- src/services/auth.ts | 2 +- src/services/items.ts | 2 +- src/services/settings.ts | 8 +- src/utils/get-ast.ts | 2 + 8 files changed, 66 insertions(+), 139 deletions(-) diff --git a/src/database/run-ast.ts b/src/database/run-ast.ts index 4682c96b6d..d0b58000c4 100644 --- a/src/database/run-ast.ts +++ b/src/database/run-ast.ts @@ -3,133 +3,6 @@ import { uniq } from 'lodash'; import database from './index'; import { Query } from '../types/query'; -// const testAST: AST = { -// type: 'collection', -// name: 'articles', -// query: {}, -// children: [ -// { -// type: 'field', -// name: 'id' -// }, -// { -// type: 'field', -// name: 'title', -// }, -// { -// type: 'collection', -// name: 'authors', -// fieldKey: 'author_id', -// parentKey: 'id', -// relation: { -// id: 2, -// collection_many: 'articles', -// field_many: 'author_id', -// collection_one: 'authors', -// primary_one: 'id', -// field_one: null -// }, -// query: {}, -// children: [ -// { -// type: 'field', -// name: 'id' -// }, -// { -// type: 'field', -// name: 'name' -// }, -// { -// type: 'collection', -// name: 'movies', -// fieldKey: 'movies', -// parentKey: 'id', -// relation: { -// id: 3, -// collection_many: 'movies', -// field_many: 'author_id', -// collection_one: 'authors', -// primary_one: 'id', -// field_one: 'movies' -// }, -// query: {}, -// children: [ -// { -// type: 'field', -// name: 'id', -// }, -// { -// type: 'field', -// name: 'title' -// }, -// { -// type: 'collection', -// name: 'authors', -// fieldKey: 'author_id', -// parentKey: 'id', -// relation: { -// id: 4, -// collection_many: 'movies', -// field_many: 'author_id', -// collection_one: 'authors', -// primary_one: 'id', -// field_one: 'movies', -// }, -// query: {}, -// children: [ -// { -// type: 'field', -// name: 'id', -// }, -// { -// type: 'field', -// name: 'name', -// }, -// { -// type: 'collection', -// name: 'movies', -// fieldKey: 'movies', -// parentKey: 'id', -// relation: { -// id: 6, -// collection_many: 'movies', -// field_many: 'author_id', -// collection_one: 'authors', -// primary_one: 'id', -// field_one: 'movies' -// }, -// query: { -// sort: [ -// { -// column: 'title', -// order: 'asc' -// } -// ] -// }, -// children: [ -// { -// type: 'field', -// name: 'id' -// }, -// { -// type: 'field', -// name: 'title' -// }, -// { -// type: 'field', -// name: 'author_id' -// } -// ] -// } -// ] -// } -// ] -// } -// ] -// } -// ] -// } - export default async function runAST(ast: AST, query = ast.query) { const toplevelFields: string[] = []; const nestedCollections: NestedCollectionAST[] = []; @@ -210,7 +83,10 @@ export default async function runAST(ast: AST, query = ast.query) { { column: 'id', operator: 'in', - value: uniq(results.map((res) => res[batch.relation.field_many])), + // filter removes null / undefined + value: uniq(results.map((res) => res[batch.relation.field_many])).filter( + (id) => id + ), }, ], }; @@ -222,7 +98,8 @@ export default async function runAST(ast: AST, query = ast.query) { { column: batch.relation.field_many, operator: 'in', - value: uniq(results.map((res) => res[batch.parentKey])), + // filter removes null / undefined + value: uniq(results.map((res) => res[batch.parentKey])).filter((id) => id), }, ], }; @@ -234,9 +111,12 @@ export default async function runAST(ast: AST, query = ast.query) { if (m2o) { return { ...record, - [batch.fieldKey]: nestedResults.find((nestedRecord) => { - return nestedRecord[batch.relation.primary_one] === record[batch.fieldKey]; - }), + [batch.fieldKey]: + nestedResults.find((nestedRecord) => { + return ( + nestedRecord[batch.relation.primary_one] === record[batch.fieldKey] + ); + }) || null, }; } diff --git a/src/middleware/validate-query.ts b/src/middleware/validate-query.ts index 08e2c53400..7d3fb7a0d2 100644 --- a/src/middleware/validate-query.ts +++ b/src/middleware/validate-query.ts @@ -18,8 +18,8 @@ const validateQuery: RequestHandler = asyncHandler(async (req, res, next) => { const query: Query = req.sanitizedQuery; await Promise.all([ - validateParams(req.params.collection, query), - validateFields(req.params.collection, query), + validateParams(req.collection, query), + validateFields(req.collection, query), validateMeta(query), ]); diff --git a/src/routes/auth.ts b/src/routes/auth.ts index b2182fda43..a2fae60114 100644 --- a/src/routes/auth.ts +++ b/src/routes/auth.ts @@ -14,6 +14,7 @@ const router = Router(); const loginSchema = Joi.object({ email: Joi.string().email().required(), password: Joi.string().required(), + mode: Joi.string().valid('cookie', 'json'), }); router.post( diff --git a/src/routes/users.ts b/src/routes/users.ts index 25de21627e..bc1b8bc8a0 100644 --- a/src/routes/users.ts +++ b/src/routes/users.ts @@ -4,7 +4,7 @@ import sanitizeQuery from '../middleware/sanitize-query'; import validateQuery from '../middleware/validate-query'; import * as UsersService from '../services/users'; import Joi from '@hapi/joi'; -import { InvalidPayloadException } from '../exceptions'; +import { InvalidPayloadException, InvalidCredentialsException } from '../exceptions'; import useCollection from '../middleware/use-collection'; import * as ActivityService from '../services/activity'; @@ -41,6 +41,21 @@ router.get( }) ); +router.get( + '/me', + useCollection('directus_users'), + sanitizeQuery, + validateQuery, + asyncHandler(async (req, res) => { + if (!req.user) { + throw new InvalidCredentialsException(); + } + + const item = await UsersService.readUser(req.user, req.sanitizedQuery); + return res.json({ data: item }); + }) +); + router.get( '/:pk', useCollection('directus_users'), @@ -52,6 +67,31 @@ router.get( }) ); +router.patch( + '/me', + useCollection('directus_users'), + sanitizeQuery, + validateQuery, + asyncHandler(async (req, res) => { + if (!req.user) { + throw new InvalidCredentialsException(); + } + + const item = await UsersService.updateUser(req.user, req.body, req.sanitizedQuery); + + 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 }); + }) +); + router.patch( '/:pk', useCollection('directus_users'), diff --git a/src/services/auth.ts b/src/services/auth.ts index 31325ee1d5..b631ef29ab 100644 --- a/src/services/auth.ts +++ b/src/services/auth.ts @@ -21,7 +21,7 @@ export const authenticate = async (email: string, password?: string) => { * email to leak anywhere else.. We might have to make a dedicated "copy" of this function to * signal the difference */ - if (password !== undefined && (await argon2.verify(password, user.password)) === false) { + if (password !== undefined && (await argon2.verify(user.password, password)) === false) { throw new InvalidCredentialsException(); } diff --git a/src/services/items.ts b/src/services/items.ts index ca961624b6..1e0ca03fc8 100644 --- a/src/services/items.ts +++ b/src/services/items.ts @@ -32,7 +32,7 @@ export const readItem = async ( query = { ...query, filter: [ - ...query.filter, + ...(query.filter || []), { column: primaryKeyField, operator: 'eq', diff --git a/src/services/settings.ts b/src/services/settings.ts index e1c450ed8a..60fa30f46e 100644 --- a/src/services/settings.ts +++ b/src/services/settings.ts @@ -2,8 +2,12 @@ import { Query } from '../types/query'; import * as ItemsService from './items'; export const readSettings = async (pk: string | number, query: Query) => { - /** @TODO only fetch the one item that exists, or default to default values if it doesn't */ - return await ItemsService.readItem('directus_settings', pk, query); + const settings = await ItemsService.readItems('directus_settings', { + ...query, + limit: 1, + }); + + return settings[0]; }; export const updateSettings = async ( diff --git a/src/utils/get-ast.ts b/src/utils/get-ast.ts index 132b69746b..eb8e52230d 100644 --- a/src/utils/get-ast.ts +++ b/src/utils/get-ast.ts @@ -117,6 +117,8 @@ export default async function getAST(collection: string, query: Query): Promise< function getRelatedCollection(collection: string, field: string) { const relation = getRelation(collection, field); + if (!relation) return null; + if (relation.collection_many === collection && relation.field_many === field) { return relation.collection_one; }