Fix 500 on singleton retrieval

Fixes #418
This commit is contained in:
rijkvanzanten
2020-09-24 14:10:20 -04:00
parent e7489abfa6
commit 2af75e3cfb
7 changed files with 25 additions and 13 deletions

View File

@@ -113,7 +113,7 @@ router.post(
try {
const record = await service.readByKey(keys as any, req.sanitizedQuery);
res.locals.payload = {
data: res.locals.savedFiles.length === 1 ? record[0] : record || null,
data: res.locals.savedFiles.length === 1 ? record![0] : record || null,
};
} catch (error) {
if (error instanceof ForbiddenException) {

View File

@@ -13,7 +13,7 @@ type RunASTOptions = {
child?: boolean;
};
export default async function runAST(originalAST: AST, options?: RunASTOptions): Promise<Item | Item[]> {
export default async function runAST(originalAST: AST, options?: RunASTOptions): Promise<null | Item | Item[]> {
const ast = cloneDeep(originalAST);
const query = options?.query || ast.query;
@@ -27,6 +27,8 @@ export default async function runAST(originalAST: AST, options?: RunASTOptions):
const rawItems: Item | Item[] = await dbQuery;
if (!rawItems || (Array.isArray(rawItems) && rawItems.length === 0)) return null;
// Run the items through the special transforms
const payloadService = new PayloadService(ast.name, { knex });
let items = await payloadService.processValues('read', rawItems);
@@ -48,8 +50,10 @@ export default async function runAST(originalAST: AST, options?: RunASTOptions):
let nestedItems = await runAST(nestedAST, { knex, child: true });
// Merge all fetched nested records with the parent items
items = mergeWithParentItems(nestedItems, items, nestedAST, tempLimit);
if (nestedItems) {
// Merge all fetched nested records with the parent items
items = mergeWithParentItems(nestedItems, items, nestedAST, tempLimit);
}
}
// During the fetching of data, we have to inject a couple of required fields for the child nesting

View File

@@ -1,7 +1,7 @@
import { BaseException } from './base';
export class ItemNotFoundException extends BaseException {
constructor(id: string | number, collection: string) {
constructor(id: string | number | (string | number)[], collection: string) {
super(`Item "${id}" doesn't exist in "${collection}".`, 404, 'ITEM_NOT_FOUND');
}
}

View File

@@ -8,6 +8,8 @@ import path from 'path';
import { AbstractServiceOptions, File, PrimaryKey } from '../types';
import { clone } from 'lodash';
import cache from '../cache';
import notFound from '../controllers/not-found';
import { ItemNotFoundException } from '../exceptions';
export class FilesService extends ItemsService {
constructor(options?: AbstractServiceOptions) {
@@ -91,6 +93,10 @@ export class FilesService extends ItemsService {
const keys = Array.isArray(key) ? key : [key];
const files = await super.readByKey(keys, { fields: ['id', 'storage'] });
if (!files) {
throw new ItemNotFoundException(key, 'directus_files');
}
for (const file of files) {
const disk = storage.disk(file.storage);

View File

@@ -188,10 +188,11 @@ export class ItemsService implements AbstractService {
return Array.isArray(data) ? savedPrimaryKeys : savedPrimaryKeys[0];
}
async readByQuery(query: Query): Promise<Item | Item[]> {
async readByQuery(query: Query): Promise<null | Item | Item[]> {
const authorizationService = new AuthorizationService({
accountability: this.accountability,
});
let ast = await getASTFromQuery(this.collection, query, {
accountability: this.accountability,
knex: this.knex,
@@ -205,13 +206,13 @@ export class ItemsService implements AbstractService {
return records;
}
readByKey(keys: PrimaryKey[], query?: Query, action?: PermissionsAction): Promise<Item[]>;
readByKey(key: PrimaryKey, query?: Query, action?: PermissionsAction): Promise<Item>;
readByKey(keys: PrimaryKey[], query?: Query, action?: PermissionsAction): Promise<null | Item[]>;
readByKey(key: PrimaryKey, query?: Query, action?: PermissionsAction): Promise<null | Item>;
async readByKey(
key: PrimaryKey | PrimaryKey[],
query: Query = {},
action: PermissionsAction = 'read'
): Promise<Item | Item[]> {
): Promise<null | Item | Item[]> {
query = clone(query);
const schemaInspector = SchemaInspector(this.knex);
const primaryKeyField = await schemaInspector.primary(this.collection);
@@ -354,7 +355,7 @@ export class ItemsService implements AbstractService {
activity: key,
collection: this.collection,
item: keys[index],
data: JSON.stringify(snapshots[index]),
data: JSON.stringify(snapshots?.[index]),
delta: JSON.stringify(payloadWithoutAliases),
}));

View File

@@ -16,10 +16,10 @@ export interface AbstractService {
create(data: Partial<Item>[]): Promise<PrimaryKey[]>;
create(data: Partial<Item>): Promise<PrimaryKey>;
readByQuery(query: Query): Promise<Item | Item[]>;
readByQuery(query: Query): Promise<null | Item | Item[]>;
readByKey(keys: PrimaryKey[], query: Query, action: PermissionsAction): Promise<Item[]>;
readByKey(key: PrimaryKey, query: Query, action: PermissionsAction): Promise<Item>;
readByKey(keys: PrimaryKey[], query: Query, action: PermissionsAction): Promise<null | Item[]>;
readByKey(key: PrimaryKey, query: Query, action: PermissionsAction): Promise<null | Item>;
update(data: Partial<Item>, keys: PrimaryKey[]): Promise<PrimaryKey[]>;
update(data: Partial<Item>, key: PrimaryKey): Promise<PrimaryKey>;