directus 9.7.0 → 9.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__mocks__/cache.d.ts +5 -0
- package/dist/__mocks__/cache.js +7 -0
- package/dist/auth/drivers/ldap.js +10 -11
- package/dist/auth/drivers/oauth2.js +9 -4
- package/dist/auth/drivers/openid.js +7 -4
- package/dist/cache.js +2 -2
- package/dist/cli/commands/schema/apply.js +9 -3
- package/dist/controllers/assets.js +5 -0
- package/dist/controllers/files.d.ts +2 -0
- package/dist/controllers/files.js +10 -5
- package/dist/database/helpers/date/dialects/default.d.ts +3 -0
- package/dist/database/helpers/date/dialects/default.js +7 -0
- package/dist/database/helpers/date/dialects/mssql.d.ts +1 -9
- package/dist/database/helpers/date/dialects/mssql.js +4 -23
- package/dist/database/helpers/date/dialects/mysql.d.ts +2 -9
- package/dist/database/helpers/date/dialects/mysql.js +7 -22
- package/dist/database/helpers/date/dialects/oracle.d.ts +1 -9
- package/dist/database/helpers/date/dialects/oracle.js +7 -23
- package/dist/database/helpers/date/dialects/sqlite.d.ts +1 -9
- package/dist/database/helpers/date/dialects/sqlite.js +8 -24
- package/dist/database/helpers/date/index.d.ts +4 -4
- package/dist/database/helpers/date/index.js +9 -9
- package/dist/database/helpers/date/types.d.ts +3 -9
- package/dist/database/helpers/date/types.js +10 -0
- package/dist/database/helpers/fn/dialects/mssql.d.ts +13 -0
- package/dist/database/helpers/fn/dialects/mssql.js +42 -0
- package/dist/database/helpers/{date/dialects/postgres.d.ts → fn/dialects/mysql.d.ts} +3 -2
- package/dist/database/helpers/fn/dialects/mysql.js +42 -0
- package/dist/database/helpers/fn/dialects/oracle.d.ts +13 -0
- package/dist/database/helpers/fn/dialects/oracle.js +42 -0
- package/dist/database/helpers/fn/dialects/postgres.d.ts +13 -0
- package/dist/database/helpers/{date → fn}/dialects/postgres.js +14 -3
- package/dist/database/helpers/fn/dialects/sqlite.d.ts +13 -0
- package/dist/database/helpers/fn/dialects/sqlite.js +42 -0
- package/dist/database/helpers/fn/index.d.ts +7 -0
- package/dist/database/helpers/fn/index.js +17 -0
- package/dist/database/helpers/fn/types.d.ts +18 -0
- package/dist/database/helpers/fn/types.js +27 -0
- package/dist/database/helpers/index.d.ts +4 -1
- package/dist/database/helpers/index.js +7 -1
- package/dist/database/index.js +0 -3
- package/dist/database/migrations/20220308A-add-bookmark-icon-and-color.d.ts +3 -0
- package/dist/database/migrations/20220308A-add-bookmark-icon-and-color.js +17 -0
- package/dist/database/migrations/20220314A-add-translation-strings.d.ts +3 -0
- package/dist/database/migrations/20220314A-add-translation-strings.js +15 -0
- package/dist/database/migrations/20220322A-rename-field-typecast-flags.d.ts +3 -0
- package/dist/database/migrations/20220322A-rename-field-typecast-flags.js +77 -0
- package/dist/database/migrations/20220323A-add-field-validation.d.ts +3 -0
- package/dist/database/migrations/20220323A-add-field-validation.js +17 -0
- package/dist/database/migrations/20220325A-fix-typecast-flags.d.ts +3 -0
- package/dist/database/migrations/20220325A-fix-typecast-flags.js +49 -0
- package/dist/database/migrations/20220325B-add-default-language.d.ts +3 -0
- package/dist/database/migrations/20220325B-add-default-language.js +28 -0
- package/dist/database/migrations/20220402A-remove-default-value-panel-icon.d.ts +3 -0
- package/dist/database/migrations/20220402A-remove-default-value-panel-icon.js +22 -0
- package/dist/database/migrations/run.js +1 -1
- package/dist/database/run-ast.js +4 -2
- package/dist/database/system-data/fields/activity.yaml +4 -4
- package/dist/database/system-data/fields/collections.yaml +4 -4
- package/dist/database/system-data/fields/fields.yaml +17 -8
- package/dist/database/system-data/fields/files.yaml +2 -2
- package/dist/database/system-data/fields/panels.yaml +2 -2
- package/dist/database/system-data/fields/permissions.yaml +4 -4
- package/dist/database/system-data/fields/presets.yaml +17 -3
- package/dist/database/system-data/fields/relations.yaml +1 -1
- package/dist/database/system-data/fields/revisions.yaml +2 -2
- package/dist/database/system-data/fields/roles.yaml +4 -4
- package/dist/database/system-data/fields/settings.yaml +18 -4
- package/dist/database/system-data/fields/users.yaml +5 -2
- package/dist/database/system-data/fields/webhooks.yaml +4 -4
- package/dist/env.js +4 -1
- package/dist/exceptions/index.d.ts +1 -0
- package/dist/exceptions/index.js +1 -0
- package/dist/exceptions/token-expired.d.ts +4 -0
- package/dist/exceptions/token-expired.js +10 -0
- package/dist/logger.js +2 -1
- package/dist/middleware/cache.js +10 -0
- package/dist/services/activity.js +4 -1
- package/dist/services/authorization.d.ts +1 -1
- package/dist/services/authorization.js +198 -14
- package/dist/services/collections.d.ts +2 -0
- package/dist/services/collections.js +230 -198
- package/dist/services/fields.js +208 -174
- package/dist/services/files.d.ts +5 -1
- package/dist/services/files.js +59 -40
- package/dist/services/graphql.d.ts +2 -3
- package/dist/services/graphql.js +39 -9
- package/dist/services/items.js +1 -0
- package/dist/services/payload.d.ts +1 -0
- package/dist/services/payload.js +29 -24
- package/dist/services/relations.js +93 -81
- package/dist/services/server.js +1 -0
- package/dist/services/shares.js +2 -1
- package/dist/services/users.js +3 -1
- package/dist/types/files.d.ts +8 -0
- package/dist/utils/apply-query.js +38 -10
- package/dist/utils/apply-snapshot.d.ts +3 -1
- package/dist/utils/apply-snapshot.js +34 -5
- package/dist/utils/get-column.d.ts +6 -5
- package/dist/utils/get-column.js +16 -8
- package/dist/utils/get-graphql-type.js +1 -0
- package/dist/utils/get-local-type.js +7 -2
- package/dist/utils/get-schema.d.ts +1 -1
- package/dist/utils/get-schema.js +15 -10
- package/dist/utils/jwt.js +1 -1
- package/dist/utils/track.js +3 -2
- package/dist/utils/url.d.ts +1 -1
- package/dist/utils/url.js +1 -1
- package/dist/utils/validate-query.js +19 -15
- package/dist/utils/validate-storage.js +3 -1
- package/example.env +4 -0
- package/package.json +14 -13
|
@@ -32,9 +32,12 @@ const env_1 = __importDefault(require("../env"));
|
|
|
32
32
|
const exceptions_1 = require("../exceptions");
|
|
33
33
|
const fields_1 = require("../services/fields");
|
|
34
34
|
const items_1 = require("../services/items");
|
|
35
|
+
const utils_1 = require("@directus/shared/utils");
|
|
36
|
+
const helpers_1 = require("../database/helpers");
|
|
35
37
|
class CollectionsService {
|
|
36
38
|
constructor(options) {
|
|
37
39
|
this.knex = options.knex || (0, database_1.default)();
|
|
40
|
+
this.helpers = (0, helpers_1.getHelpers)(this.knex);
|
|
38
41
|
this.accountability = options.accountability || null;
|
|
39
42
|
this.schemaInspector = options.knex ? (0, schema_1.default)(options.knex) : (0, database_1.getSchemaInspector)();
|
|
40
43
|
this.schema = options.schema;
|
|
@@ -55,105 +58,118 @@ class CollectionsService {
|
|
|
55
58
|
if (payload.collection.startsWith('directus_')) {
|
|
56
59
|
throw new exceptions_1.InvalidPayloadException(`Collections can't start with "directus_"`);
|
|
57
60
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
payload.fields
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
61
|
+
try {
|
|
62
|
+
const existingCollections = [
|
|
63
|
+
...((_b = (_a = (await this.knex.select('collection').from('directus_collections'))) === null || _a === void 0 ? void 0 : _a.map(({ collection }) => collection)) !== null && _b !== void 0 ? _b : []),
|
|
64
|
+
...Object.keys(this.schema.collections),
|
|
65
|
+
];
|
|
66
|
+
if (existingCollections.includes(payload.collection)) {
|
|
67
|
+
throw new exceptions_1.InvalidPayloadException(`Collection "${payload.collection}" already exists.`);
|
|
68
|
+
}
|
|
69
|
+
// Create the collection/fields in a transaction so it'll be reverted in case of errors or
|
|
70
|
+
// permission problems. This might not work reliably in MySQL, as it doesn't support DDL in
|
|
71
|
+
// transactions.
|
|
72
|
+
await this.knex.transaction(async (trx) => {
|
|
73
|
+
if (payload.schema) {
|
|
74
|
+
// Directus heavily relies on the primary key of a collection, so we have to make sure that
|
|
75
|
+
// every collection that is created has a primary key. If no primary key field is created
|
|
76
|
+
// while making the collection, we default to an auto incremented id named `id`
|
|
77
|
+
if (!payload.fields)
|
|
78
|
+
payload.fields = [
|
|
79
|
+
{
|
|
80
|
+
field: 'id',
|
|
81
|
+
type: 'integer',
|
|
82
|
+
meta: {
|
|
83
|
+
hidden: true,
|
|
84
|
+
interface: 'numeric',
|
|
85
|
+
readonly: true,
|
|
86
|
+
},
|
|
87
|
+
schema: {
|
|
88
|
+
is_primary_key: true,
|
|
89
|
+
has_auto_increment: true,
|
|
90
|
+
},
|
|
86
91
|
},
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
return field;
|
|
99
|
-
});
|
|
100
|
-
const fieldsService = new fields_1.FieldsService({ knex: trx, schema: this.schema });
|
|
101
|
-
await trx.schema.createTable(payload.collection, (table) => {
|
|
102
|
-
for (const field of payload.fields) {
|
|
103
|
-
if (field.type && constants_1.ALIAS_TYPES.includes(field.type) === false) {
|
|
104
|
-
fieldsService.addColumnToTable(table, field);
|
|
92
|
+
];
|
|
93
|
+
// Ensure that every field meta has the field/collection fields filled correctly
|
|
94
|
+
payload.fields = payload.fields.map((field) => {
|
|
95
|
+
if (field.meta) {
|
|
96
|
+
field.meta = {
|
|
97
|
+
...field.meta,
|
|
98
|
+
field: field.field,
|
|
99
|
+
collection: payload.collection,
|
|
100
|
+
};
|
|
105
101
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
102
|
+
// Add flag for specific database type overrides
|
|
103
|
+
const flagToAdd = this.helpers.date.fieldFlagForField(field.type);
|
|
104
|
+
if (flagToAdd) {
|
|
105
|
+
(0, utils_1.addFieldFlag)(field, flagToAdd);
|
|
106
|
+
}
|
|
107
|
+
return field;
|
|
108
|
+
});
|
|
109
|
+
const fieldsService = new fields_1.FieldsService({ knex: trx, schema: this.schema });
|
|
110
|
+
await trx.schema.createTable(payload.collection, (table) => {
|
|
111
|
+
for (const field of payload.fields) {
|
|
112
|
+
if (field.type && constants_1.ALIAS_TYPES.includes(field.type) === false) {
|
|
113
|
+
fieldsService.addColumnToTable(table, field);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
const fieldItemsService = new items_1.ItemsService('directus_fields', {
|
|
118
|
+
knex: trx,
|
|
119
|
+
accountability: this.accountability,
|
|
120
|
+
schema: this.schema,
|
|
121
|
+
});
|
|
122
|
+
const fieldPayloads = payload.fields.filter((field) => field.meta).map((field) => field.meta);
|
|
123
|
+
await fieldItemsService.createMany(fieldPayloads);
|
|
124
|
+
}
|
|
125
|
+
if (payload.meta) {
|
|
126
|
+
const collectionItemsService = new items_1.ItemsService('directus_collections', {
|
|
127
|
+
knex: trx,
|
|
128
|
+
accountability: this.accountability,
|
|
129
|
+
schema: this.schema,
|
|
130
|
+
});
|
|
131
|
+
await collectionItemsService.createOne({
|
|
132
|
+
...payload.meta,
|
|
133
|
+
collection: payload.collection,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return payload.collection;
|
|
137
|
+
});
|
|
127
138
|
return payload.collection;
|
|
128
|
-
});
|
|
129
|
-
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
130
|
-
await this.cache.clear();
|
|
131
139
|
}
|
|
132
|
-
|
|
133
|
-
|
|
140
|
+
finally {
|
|
141
|
+
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
142
|
+
await this.cache.clear();
|
|
143
|
+
}
|
|
144
|
+
await (0, cache_1.clearSystemCache)();
|
|
145
|
+
}
|
|
134
146
|
}
|
|
135
147
|
/**
|
|
136
148
|
* Create multiple new collections
|
|
137
149
|
*/
|
|
138
150
|
async createMany(payloads, opts) {
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
151
|
+
try {
|
|
152
|
+
const collections = await this.knex.transaction(async (trx) => {
|
|
153
|
+
const service = new CollectionsService({
|
|
154
|
+
schema: this.schema,
|
|
155
|
+
accountability: this.accountability,
|
|
156
|
+
knex: trx,
|
|
157
|
+
});
|
|
158
|
+
const collectionNames = [];
|
|
159
|
+
for (const payload of payloads) {
|
|
160
|
+
const name = await service.createOne(payload, { autoPurgeCache: false });
|
|
161
|
+
collectionNames.push(name);
|
|
162
|
+
}
|
|
163
|
+
return collectionNames;
|
|
144
164
|
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
165
|
+
return collections;
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
169
|
+
await this.cache.clear();
|
|
149
170
|
}
|
|
150
|
-
|
|
151
|
-
});
|
|
152
|
-
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
153
|
-
await this.cache.clear();
|
|
171
|
+
await (0, cache_1.clearSystemCache)();
|
|
154
172
|
}
|
|
155
|
-
await (0, cache_1.clearSystemCache)();
|
|
156
|
-
return collections;
|
|
157
173
|
}
|
|
158
174
|
/**
|
|
159
175
|
* Read all collections. Currently doesn't support any query.
|
|
@@ -252,31 +268,35 @@ class CollectionsService {
|
|
|
252
268
|
if (this.accountability && this.accountability.admin !== true) {
|
|
253
269
|
throw new exceptions_1.ForbiddenException();
|
|
254
270
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
271
|
+
try {
|
|
272
|
+
const collectionItemsService = new items_1.ItemsService('directus_collections', {
|
|
273
|
+
knex: this.knex,
|
|
274
|
+
accountability: this.accountability,
|
|
275
|
+
schema: this.schema,
|
|
276
|
+
});
|
|
277
|
+
const payload = data;
|
|
278
|
+
if (!payload.meta) {
|
|
279
|
+
return collectionKey;
|
|
280
|
+
}
|
|
281
|
+
const exists = !!(await this.knex
|
|
282
|
+
.select('collection')
|
|
283
|
+
.from('directus_collections')
|
|
284
|
+
.where({ collection: collectionKey })
|
|
285
|
+
.first());
|
|
286
|
+
if (exists) {
|
|
287
|
+
await collectionItemsService.updateOne(collectionKey, payload.meta, opts);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
await collectionItemsService.createOne({ ...payload.meta, collection: collectionKey }, opts);
|
|
291
|
+
}
|
|
262
292
|
return collectionKey;
|
|
263
293
|
}
|
|
264
|
-
|
|
265
|
-
.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
.
|
|
269
|
-
if (exists) {
|
|
270
|
-
await collectionItemsService.updateOne(collectionKey, payload.meta, opts);
|
|
271
|
-
}
|
|
272
|
-
else {
|
|
273
|
-
await collectionItemsService.createOne({ ...payload.meta, collection: collectionKey }, opts);
|
|
274
|
-
}
|
|
275
|
-
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
276
|
-
await this.cache.clear();
|
|
294
|
+
finally {
|
|
295
|
+
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
296
|
+
await this.cache.clear();
|
|
297
|
+
}
|
|
298
|
+
await (0, cache_1.clearSystemCache)();
|
|
277
299
|
}
|
|
278
|
-
await (0, cache_1.clearSystemCache)();
|
|
279
|
-
return collectionKey;
|
|
280
300
|
}
|
|
281
301
|
/**
|
|
282
302
|
* Update multiple collections by name
|
|
@@ -285,21 +305,25 @@ class CollectionsService {
|
|
|
285
305
|
if (this.accountability && this.accountability.admin !== true) {
|
|
286
306
|
throw new exceptions_1.ForbiddenException();
|
|
287
307
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
308
|
+
try {
|
|
309
|
+
await this.knex.transaction(async (trx) => {
|
|
310
|
+
const service = new CollectionsService({
|
|
311
|
+
schema: this.schema,
|
|
312
|
+
accountability: this.accountability,
|
|
313
|
+
knex: trx,
|
|
314
|
+
});
|
|
315
|
+
for (const collectionKey of collectionKeys) {
|
|
316
|
+
await service.updateOne(collectionKey, data, { autoPurgeCache: false });
|
|
317
|
+
}
|
|
293
318
|
});
|
|
294
|
-
|
|
295
|
-
|
|
319
|
+
return collectionKeys;
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
323
|
+
await this.cache.clear();
|
|
296
324
|
}
|
|
297
|
-
|
|
298
|
-
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
299
|
-
await this.cache.clear();
|
|
325
|
+
await (0, cache_1.clearSystemCache)();
|
|
300
326
|
}
|
|
301
|
-
await (0, cache_1.clearSystemCache)();
|
|
302
|
-
return collectionKeys;
|
|
303
327
|
}
|
|
304
328
|
/**
|
|
305
329
|
* Delete a single collection This will delete the table and all records within. It'll also
|
|
@@ -309,78 +333,82 @@ class CollectionsService {
|
|
|
309
333
|
if (this.accountability && this.accountability.admin !== true) {
|
|
310
334
|
throw new exceptions_1.ForbiddenException();
|
|
311
335
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
await this.knex.transaction(async (trx) => {
|
|
318
|
-
var _a;
|
|
319
|
-
if (collectionToBeDeleted.schema) {
|
|
320
|
-
await trx.schema.dropTable(collectionKey);
|
|
336
|
+
try {
|
|
337
|
+
const collections = await this.readByQuery();
|
|
338
|
+
const collectionToBeDeleted = collections.find((collection) => collection.collection === collectionKey);
|
|
339
|
+
if (!!collectionToBeDeleted === false) {
|
|
340
|
+
throw new exceptions_1.ForbiddenException();
|
|
321
341
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
knex: trx,
|
|
327
|
-
accountability: this.accountability,
|
|
328
|
-
schema: this.schema,
|
|
329
|
-
});
|
|
330
|
-
await collectionItemsService.deleteOne(collectionKey);
|
|
331
|
-
}
|
|
332
|
-
if (collectionToBeDeleted.schema) {
|
|
333
|
-
const fieldsService = new fields_1.FieldsService({
|
|
334
|
-
knex: trx,
|
|
335
|
-
accountability: this.accountability,
|
|
336
|
-
schema: this.schema,
|
|
337
|
-
});
|
|
338
|
-
await trx('directus_fields').delete().where('collection', '=', collectionKey);
|
|
339
|
-
await trx('directus_presets').delete().where('collection', '=', collectionKey);
|
|
340
|
-
const revisionsToDelete = await trx
|
|
341
|
-
.select('id')
|
|
342
|
-
.from('directus_revisions')
|
|
343
|
-
.where({ collection: collectionKey });
|
|
344
|
-
if (revisionsToDelete.length > 0) {
|
|
345
|
-
const keys = revisionsToDelete.map((record) => record.id);
|
|
346
|
-
await trx('directus_revisions').update({ parent: null }).whereIn('parent', keys);
|
|
342
|
+
await this.knex.transaction(async (trx) => {
|
|
343
|
+
var _a;
|
|
344
|
+
if (collectionToBeDeleted.schema) {
|
|
345
|
+
await trx.schema.dropTable(collectionKey);
|
|
347
346
|
}
|
|
348
|
-
|
|
349
|
-
await trx('
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
347
|
+
// Make sure this collection isn't used as a group in any other collections
|
|
348
|
+
await trx('directus_collections').update({ group: null }).where({ group: collectionKey });
|
|
349
|
+
if (collectionToBeDeleted.meta) {
|
|
350
|
+
const collectionItemsService = new items_1.ItemsService('directus_collections', {
|
|
351
|
+
knex: trx,
|
|
352
|
+
accountability: this.accountability,
|
|
353
|
+
schema: this.schema,
|
|
354
|
+
});
|
|
355
|
+
await collectionItemsService.deleteOne(collectionKey);
|
|
356
|
+
}
|
|
357
|
+
if (collectionToBeDeleted.schema) {
|
|
358
|
+
const fieldsService = new fields_1.FieldsService({
|
|
359
|
+
knex: trx,
|
|
360
|
+
accountability: this.accountability,
|
|
361
|
+
schema: this.schema,
|
|
362
|
+
});
|
|
363
|
+
await trx('directus_fields').delete().where('collection', '=', collectionKey);
|
|
364
|
+
await trx('directus_presets').delete().where('collection', '=', collectionKey);
|
|
365
|
+
const revisionsToDelete = await trx
|
|
366
|
+
.select('id')
|
|
367
|
+
.from('directus_revisions')
|
|
368
|
+
.where({ collection: collectionKey });
|
|
369
|
+
if (revisionsToDelete.length > 0) {
|
|
370
|
+
const keys = revisionsToDelete.map((record) => record.id);
|
|
371
|
+
await trx('directus_revisions').update({ parent: null }).whereIn('parent', keys);
|
|
372
|
+
}
|
|
373
|
+
await trx('directus_revisions').delete().where('collection', '=', collectionKey);
|
|
374
|
+
await trx('directus_activity').delete().where('collection', '=', collectionKey);
|
|
375
|
+
await trx('directus_permissions').delete().where('collection', '=', collectionKey);
|
|
376
|
+
await trx('directus_relations').delete().where({ many_collection: collectionKey });
|
|
377
|
+
const relations = this.schema.relations.filter((relation) => {
|
|
378
|
+
return relation.collection === collectionKey || relation.related_collection === collectionKey;
|
|
379
|
+
});
|
|
380
|
+
for (const relation of relations) {
|
|
381
|
+
// Delete related o2m fields that point to current collection
|
|
382
|
+
if (relation.related_collection && ((_a = relation.meta) === null || _a === void 0 ? void 0 : _a.one_field)) {
|
|
383
|
+
await fieldsService.deleteField(relation.related_collection, relation.meta.one_field);
|
|
384
|
+
}
|
|
385
|
+
// Delete related m2o fields that point to current collection
|
|
386
|
+
if (relation.related_collection === collectionKey) {
|
|
387
|
+
await fieldsService.deleteField(relation.collection, relation.field);
|
|
388
|
+
}
|
|
359
389
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
390
|
+
const a2oRelationsThatIncludeThisCollection = this.schema.relations.filter((relation) => {
|
|
391
|
+
var _a, _b;
|
|
392
|
+
return (_b = (_a = relation.meta) === null || _a === void 0 ? void 0 : _a.one_allowed_collections) === null || _b === void 0 ? void 0 : _b.includes(collectionKey);
|
|
393
|
+
});
|
|
394
|
+
for (const relation of a2oRelationsThatIncludeThisCollection) {
|
|
395
|
+
const newAllowedCollections = relation
|
|
396
|
+
.meta.one_allowed_collections.filter((collection) => collectionKey !== collection)
|
|
397
|
+
.join(',');
|
|
398
|
+
await trx('directus_relations')
|
|
399
|
+
.update({ one_allowed_collections: newAllowedCollections })
|
|
400
|
+
.where({ id: relation.meta.id });
|
|
363
401
|
}
|
|
364
402
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
.meta.one_allowed_collections.filter((collection) => collectionKey !== collection)
|
|
372
|
-
.join(',');
|
|
373
|
-
await trx('directus_relations')
|
|
374
|
-
.update({ one_allowed_collections: newAllowedCollections })
|
|
375
|
-
.where({ id: relation.meta.id });
|
|
376
|
-
}
|
|
403
|
+
});
|
|
404
|
+
return collectionKey;
|
|
405
|
+
}
|
|
406
|
+
finally {
|
|
407
|
+
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
408
|
+
await this.cache.clear();
|
|
377
409
|
}
|
|
378
|
-
|
|
379
|
-
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
380
|
-
await this.cache.clear();
|
|
410
|
+
await (0, cache_1.clearSystemCache)();
|
|
381
411
|
}
|
|
382
|
-
await (0, cache_1.clearSystemCache)();
|
|
383
|
-
return collectionKey;
|
|
384
412
|
}
|
|
385
413
|
/**
|
|
386
414
|
* Delete multiple collections by key
|
|
@@ -389,21 +417,25 @@ class CollectionsService {
|
|
|
389
417
|
if (this.accountability && this.accountability.admin !== true) {
|
|
390
418
|
throw new exceptions_1.ForbiddenException();
|
|
391
419
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
420
|
+
try {
|
|
421
|
+
await this.knex.transaction(async (trx) => {
|
|
422
|
+
const service = new CollectionsService({
|
|
423
|
+
schema: this.schema,
|
|
424
|
+
accountability: this.accountability,
|
|
425
|
+
knex: trx,
|
|
426
|
+
});
|
|
427
|
+
for (const collectionKey of collectionKeys) {
|
|
428
|
+
await service.deleteOne(collectionKey, { autoPurgeCache: false });
|
|
429
|
+
}
|
|
397
430
|
});
|
|
398
|
-
|
|
399
|
-
|
|
431
|
+
return collectionKeys;
|
|
432
|
+
}
|
|
433
|
+
finally {
|
|
434
|
+
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
435
|
+
await this.cache.clear();
|
|
400
436
|
}
|
|
401
|
-
|
|
402
|
-
if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
|
|
403
|
-
await this.cache.clear();
|
|
437
|
+
await (0, cache_1.clearSystemCache)();
|
|
404
438
|
}
|
|
405
|
-
await (0, cache_1.clearSystemCache)();
|
|
406
|
-
return collectionKeys;
|
|
407
439
|
}
|
|
408
440
|
}
|
|
409
441
|
exports.CollectionsService = CollectionsService;
|