Enforce new collections to have PK field

Fixes #5512
This commit is contained in:
rijkvanzanten
2021-05-06 11:18:50 -04:00
parent 4217ace3b4
commit ae1e22d116
2 changed files with 29 additions and 8 deletions

View File

@@ -7,7 +7,7 @@ import { systemCollectionRows } from '../database/system-data/collections';
import env from '../env';
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
import logger from '../logger';
import { FieldsService } from '../services/fields';
import { FieldsService, RawField } from '../services/fields';
import { ItemsService, MutationOptions } from '../services/items';
import {
AbstractServiceOptions,
@@ -18,6 +18,12 @@ import {
SchemaOverview,
} from '../types';
export type RawCollection = {
collection: string;
fields?: RawField[];
meta?: Partial<CollectionMeta>;
};
export class CollectionsService {
knex: Knex;
accountability: Accountability | null;
@@ -34,14 +40,32 @@ export class CollectionsService {
/**
* Create a single new collection
*/
async createOne(payload: Partial<Collection> & { collection: string }, opts?: MutationOptions): Promise<string> {
async createOne(payload: RawCollection, opts?: MutationOptions): Promise<string> {
if (this.accountability && this.accountability.admin !== true) {
throw new ForbiddenException();
}
if (!payload.collection) throw new InvalidPayloadException(`"collection" is required`);
if (!payload.fields) payload.fields = [];
// Directus heavily relies on the primary key of a collection, so we have to make sure that
// every collection that is created has a primary key. If no primary key field is created
// while making the collection, we default to an auto incremented id named `id`
if (!payload.fields)
payload.fields = [
{
field: 'id',
type: 'integer',
meta: {
hidden: true,
interface: 'numeric',
readonly: true,
},
schema: {
is_primary_key: true,
has_auto_increment: true,
},
},
];
// Ensure that every field meta has the field/collection fields filled correctly
payload.fields = payload.fields.map((field) => {
@@ -114,10 +138,7 @@ export class CollectionsService {
/**
* Create multiple new collections
*/
async createMany(
payloads: Partial<Collection> & { collection: string }[],
opts?: MutationOptions
): Promise<string[]> {
async createMany(payloads: RawCollection[], opts?: MutationOptions): Promise<string[]> {
const collections = await this.knex.transaction(async (trx) => {
const service = new CollectionsService({
schema: this.schema,

View File

@@ -17,7 +17,7 @@ import getDefaultValue from '../utils/get-default-value';
import getLocalType from '../utils/get-local-type';
import { toArray } from '../utils/to-array';
type RawField = Partial<Field> & { field: string; type: typeof types[number] };
export type RawField = DeepPartial<Field> & { field: string; type: typeof types[number] };
export class FieldsService {
knex: Knex;