directus 9.21.0 → 9.22.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.
Files changed (117) hide show
  1. package/dist/app.js +9 -5
  2. package/dist/app.test.d.ts +1 -0
  3. package/dist/auth/drivers/openid.js +3 -1
  4. package/dist/cli/commands/bootstrap/index.js +2 -2
  5. package/dist/cli/commands/schema/apply.js +0 -2
  6. package/dist/cli/commands/schema/snapshot.js +0 -2
  7. package/dist/cli/commands/security/secret.js +2 -2
  8. package/dist/cli/utils/create-env/env-stub.liquid +3 -3
  9. package/dist/cli/utils/create-env/index.js +5 -8
  10. package/dist/constants.d.ts +1 -0
  11. package/dist/constants.js +2 -1
  12. package/dist/controllers/assets.js +9 -7
  13. package/dist/controllers/files.js +2 -1
  14. package/dist/controllers/utils.js +2 -2
  15. package/dist/database/helpers/fn/dialects/mssql.js +2 -1
  16. package/dist/database/helpers/fn/dialects/mysql.js +3 -2
  17. package/dist/database/helpers/fn/dialects/oracle.js +2 -1
  18. package/dist/database/helpers/fn/dialects/postgres.js +2 -1
  19. package/dist/database/helpers/fn/dialects/sqlite.js +2 -1
  20. package/dist/database/helpers/fn/types.d.ts +1 -0
  21. package/dist/database/helpers/fn/types.js +5 -4
  22. package/dist/database/helpers/index.d.ts +1 -1
  23. package/dist/database/helpers/schema/dialects/mssql.d.ts +6 -0
  24. package/dist/database/helpers/schema/dialects/mssql.js +14 -0
  25. package/dist/database/helpers/schema/dialects/mysql.d.ts +5 -0
  26. package/dist/database/helpers/schema/dialects/mysql.js +19 -0
  27. package/dist/database/helpers/schema/dialects/oracle.d.ts +1 -0
  28. package/dist/database/helpers/schema/dialects/oracle.js +3 -0
  29. package/dist/database/helpers/schema/index.d.ts +2 -2
  30. package/dist/database/helpers/schema/index.js +4 -4
  31. package/dist/database/helpers/schema/types.d.ts +5 -0
  32. package/dist/database/helpers/schema/types.js +13 -0
  33. package/dist/database/index.d.ts +6 -0
  34. package/dist/database/index.js +20 -1
  35. package/dist/database/migrations/20211007A-update-presets.js +2 -2
  36. package/dist/database/migrations/run.js +7 -31
  37. package/dist/database/run-ast.js +132 -6
  38. package/dist/database/system-data/fields/index.js +2 -1
  39. package/dist/env.js +3 -2
  40. package/dist/exceptions/range-not-satisfiable.d.ts +1 -1
  41. package/dist/extensions.d.ts +7 -1
  42. package/dist/extensions.js +41 -15
  43. package/dist/logger.js +27 -1
  44. package/dist/middleware/schema.js +1 -1
  45. package/dist/operations/request/index.d.ts +1 -2
  46. package/dist/operations/request/index.js +2 -2
  47. package/dist/services/assets.d.ts +4 -3
  48. package/dist/services/assets.js +13 -11
  49. package/dist/services/authentication.js +4 -3
  50. package/dist/services/authorization.js +1 -1
  51. package/dist/services/collections.js +7 -7
  52. package/dist/services/fields.d.ts +3 -2
  53. package/dist/services/fields.js +40 -20
  54. package/dist/services/files.d.ts +4 -3
  55. package/dist/services/files.js +92 -68
  56. package/dist/services/flows.d.ts +0 -2
  57. package/dist/services/flows.js +0 -14
  58. package/dist/services/flows.test.d.ts +1 -0
  59. package/dist/services/graphql/index.d.ts +5 -1
  60. package/dist/services/graphql/index.js +29 -31
  61. package/dist/services/import-export.d.ts +4 -3
  62. package/dist/services/items.js +7 -1
  63. package/dist/services/meta.js +2 -2
  64. package/dist/services/operations.d.ts +0 -2
  65. package/dist/services/operations.js +0 -12
  66. package/dist/services/operations.test.d.ts +1 -0
  67. package/dist/services/permissions.d.ts +0 -5
  68. package/dist/services/permissions.js +0 -25
  69. package/dist/services/permissions.test.d.ts +1 -0
  70. package/dist/services/relations.d.ts +2 -2
  71. package/dist/services/relations.js +24 -16
  72. package/dist/services/roles.js +0 -3
  73. package/dist/services/roles.test.d.ts +1 -0
  74. package/dist/services/server.js +8 -6
  75. package/dist/services/shares.js +2 -2
  76. package/dist/services/specifications.js +12 -1
  77. package/dist/services/users.js +10 -4
  78. package/dist/services/webhooks.d.ts +0 -2
  79. package/dist/services/webhooks.js +0 -10
  80. package/dist/services/webhooks.test.d.ts +1 -0
  81. package/dist/storage/get-storage-driver.d.ts +3 -0
  82. package/dist/storage/get-storage-driver.js +20 -0
  83. package/dist/storage/get-storage-driver.test.d.ts +1 -0
  84. package/dist/storage/index.d.ts +5 -0
  85. package/dist/storage/index.js +20 -0
  86. package/dist/storage/index.test.d.ts +1 -0
  87. package/dist/storage/register-drivers.d.ts +2 -0
  88. package/dist/storage/register-drivers.js +22 -0
  89. package/dist/storage/register-drivers.test.d.ts +1 -0
  90. package/dist/storage/register-locations.d.ts +2 -0
  91. package/dist/storage/register-locations.js +17 -0
  92. package/dist/storage/register-locations.test.d.ts +1 -0
  93. package/dist/utils/apply-query.d.ts +27 -3
  94. package/dist/utils/apply-query.js +180 -127
  95. package/dist/utils/apply-snapshot.js +32 -13
  96. package/dist/utils/dynamic-import.d.ts +1 -0
  97. package/dist/utils/dynamic-import.js +7 -0
  98. package/dist/utils/get-collection-from-alias.d.ts +6 -0
  99. package/dist/utils/get-collection-from-alias.js +15 -0
  100. package/dist/utils/get-collection-from-alias.test.d.ts +1 -0
  101. package/dist/utils/get-column-path.d.ts +14 -8
  102. package/dist/utils/get-column-path.js +24 -7
  103. package/dist/utils/get-column.d.ts +8 -1
  104. package/dist/utils/get-column.js +10 -3
  105. package/dist/utils/get-config-from-env.js +3 -2
  106. package/dist/utils/get-default-value.d.ts +1 -1
  107. package/dist/utils/get-schema.d.ts +6 -2
  108. package/dist/utils/get-schema.js +1 -1
  109. package/dist/utils/get-snapshot.js +1 -1
  110. package/dist/utils/parse-image-metadata.d.ts +3 -0
  111. package/dist/utils/parse-image-metadata.js +73 -0
  112. package/dist/utils/track.js +2 -2
  113. package/dist/utils/validate-env.js +3 -2
  114. package/dist/webhooks.js +2 -2
  115. package/package.json +18 -22
  116. package/dist/storage.d.ts +0 -3
  117. package/dist/storage.js +0 -61
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.GraphQLService = void 0;
7
7
  const types_1 = require("@directus/shared/types");
8
+ const utils_1 = require("@directus/shared/utils");
8
9
  const argon2_1 = __importDefault(require("argon2"));
9
10
  const graphql_1 = require("graphql");
10
11
  const graphql_compose_1 = require("graphql-compose");
@@ -13,7 +14,6 @@ const lodash_1 = require("lodash");
13
14
  const ms_1 = __importDefault(require("ms"));
14
15
  const cache_1 = require("../../cache");
15
16
  const constants_1 = require("../../constants");
16
- const constants_2 = require("@directus/shared/constants");
17
17
  const database_1 = __importDefault(require("../../database"));
18
18
  const env_1 = __importDefault(require("../../env"));
19
19
  const exceptions_1 = require("../../exceptions");
@@ -44,7 +44,7 @@ const shares_1 = require("../shares");
44
44
  const specifications_1 = require("../specifications");
45
45
  const tfa_1 = require("../tfa");
46
46
  const users_1 = require("../users");
47
- const utils_1 = require("../utils");
47
+ const utils_2 = require("../utils");
48
48
  const webhooks_1 = require("../webhooks");
49
49
  const date_1 = require("./types/date");
50
50
  const geojson_1 = require("./types/geojson");
@@ -53,6 +53,7 @@ const void_1 = require("./types/void");
53
53
  const add_path_to_validation_error_1 = require("./utils/add-path-to-validation-error");
54
54
  const hash_1 = require("./types/hash");
55
55
  const bigint_1 = require("./types/bigint");
56
+ const constants_2 = require("@directus/shared/constants");
56
57
  const validationRules = Array.from(graphql_1.specifiedRules);
57
58
  if (env_1.default.GRAPHQL_INTROSPECTION === false) {
58
59
  validationRules.push(graphql_1.NoSchemaIntrospectionCustomRule);
@@ -1111,14 +1112,7 @@ class GraphQLService {
1111
1112
  // Transform count(a.b.c) into a.b.count(c)
1112
1113
  if ((_c = query.fields) === null || _c === void 0 ? void 0 : _c.length) {
1113
1114
  for (let fieldIndex = 0; fieldIndex < query.fields.length; fieldIndex++) {
1114
- if (query.fields[fieldIndex].includes('(') && query.fields[fieldIndex].includes(')')) {
1115
- const functionName = query.fields[fieldIndex].split('(')[0];
1116
- const columnNames = query.fields[fieldIndex].match(constants_2.REGEX_BETWEEN_PARENS)[1].split('.');
1117
- if (columnNames.length > 1) {
1118
- const column = columnNames.pop();
1119
- query.fields[fieldIndex] = columnNames.join('.') + '.' + functionName + '(' + column + ')';
1120
- }
1121
- }
1115
+ query.fields[fieldIndex] = (0, utils_1.parseFilterFunctionPath)(query.fields[fieldIndex]);
1122
1116
  }
1123
1117
  }
1124
1118
  const result = await this.read(collection, query);
@@ -1347,28 +1341,10 @@ class GraphQLService {
1347
1341
  }
1348
1342
  return (0, lodash_1.uniq)(fields);
1349
1343
  };
1350
- const replaceFuncs = (filter) => {
1351
- if (!filter)
1352
- return filter;
1353
- return replaceFuncDeep(filter);
1354
- function replaceFuncDeep(filter) {
1355
- return (0, lodash_1.transform)(filter, (result, value, key) => {
1356
- let currentKey = key;
1357
- if (typeof key === 'string' && key.endsWith('_func')) {
1358
- const functionName = Object.keys(value)[0];
1359
- currentKey = `${functionName}(${currentKey.slice(0, -5)})`;
1360
- result[currentKey] = Object.values(value)[0];
1361
- }
1362
- else {
1363
- result[currentKey] =
1364
- (value === null || value === void 0 ? void 0 : value.constructor) === Object || (value === null || value === void 0 ? void 0 : value.constructor) === Array ? replaceFuncDeep(value) : value;
1365
- }
1366
- });
1367
- }
1368
- };
1369
1344
  query.alias = parseAliases(selections);
1370
1345
  query.fields = parseFields(selections);
1371
- query.filter = replaceFuncs(query.filter);
1346
+ query.filter = this.replaceFuncs(query.filter);
1347
+ query.deep = this.replaceFuncs(query.deep);
1372
1348
  (0, validate_query_1.validateQuery)(query);
1373
1349
  return query;
1374
1350
  }
@@ -1393,9 +1369,31 @@ class GraphQLService {
1393
1369
  return selectionNode.name.value;
1394
1370
  })) !== null && _b !== void 0 ? _b : [];
1395
1371
  }
1372
+ query.filter = this.replaceFuncs(query.filter);
1396
1373
  (0, validate_query_1.validateQuery)(query);
1397
1374
  return query;
1398
1375
  }
1376
+ /**
1377
+ * Replace functions from GraphQL format to Directus-Filter format
1378
+ */
1379
+ replaceFuncs(filter) {
1380
+ if (!filter)
1381
+ return filter;
1382
+ return replaceFuncDeep(filter);
1383
+ function replaceFuncDeep(filter) {
1384
+ return (0, lodash_1.transform)(filter, (result, value, key) => {
1385
+ const isFunctionKey = typeof key === 'string' && key.endsWith('_func') && constants_2.FUNCTIONS.includes(Object.keys(value)[0]);
1386
+ if (isFunctionKey) {
1387
+ const functionName = Object.keys(value)[0];
1388
+ const fieldName = key.slice(0, -5);
1389
+ result[`${functionName}(${fieldName})`] = Object.values(value)[0];
1390
+ }
1391
+ else {
1392
+ result[key] = (value === null || value === void 0 ? void 0 : value.constructor) === Object || (value === null || value === void 0 ? void 0 : value.constructor) === Array ? replaceFuncDeep(value) : value;
1393
+ }
1394
+ });
1395
+ }
1396
+ }
1399
1397
  /**
1400
1398
  * Convert Directus-Exception into a GraphQL format, so it can be returned by GraphQL properly.
1401
1399
  */
@@ -1870,7 +1868,7 @@ class GraphQLService {
1870
1868
  to: new graphql_1.GraphQLNonNull(graphql_1.GraphQLID),
1871
1869
  },
1872
1870
  resolve: async (_, args) => {
1873
- const service = new utils_1.UtilsService({
1871
+ const service = new utils_2.UtilsService({
1874
1872
  accountability: this.accountability,
1875
1873
  schema: this.schema,
1876
1874
  });
@@ -2,14 +2,15 @@
2
2
  import { Accountability, Query, SchemaOverview } from '@directus/shared/types';
3
3
  import { Knex } from 'knex';
4
4
  import { AbstractServiceOptions, File } from '../types';
5
+ import type { Readable } from 'node:stream';
5
6
  export declare class ImportService {
6
7
  knex: Knex;
7
8
  accountability: Accountability | null;
8
9
  schema: SchemaOverview;
9
10
  constructor(options: AbstractServiceOptions);
10
- import(collection: string, mimetype: string, stream: NodeJS.ReadableStream): Promise<void>;
11
- importJSON(collection: string, stream: NodeJS.ReadableStream): Promise<void>;
12
- importCSV(collection: string, stream: NodeJS.ReadableStream): Promise<void>;
11
+ import(collection: string, mimetype: string, stream: Readable): Promise<void>;
12
+ importJSON(collection: string, stream: Readable): Promise<void>;
13
+ importCSV(collection: string, stream: Readable): Promise<void>;
13
14
  }
14
15
  export declare class ExportService {
15
16
  knex: Knex;
@@ -8,6 +8,7 @@ const types_1 = require("@directus/shared/types");
8
8
  const lodash_1 = require("lodash");
9
9
  const cache_1 = require("../cache");
10
10
  const database_1 = __importDefault(require("../database"));
11
+ const helpers_1 = require("../database/helpers");
11
12
  const run_ast_1 = __importDefault(require("../database/run-ast"));
12
13
  const emitter_1 = __importDefault(require("../emitter"));
13
14
  const env_1 = __importDefault(require("../env"));
@@ -98,7 +99,12 @@ class ItemsService {
98
99
  .returning(primaryKeyField)
99
100
  .then((result) => result[0]);
100
101
  const returnedKey = typeof result === 'object' ? result[primaryKeyField] : result;
101
- primaryKey = primaryKey !== null && primaryKey !== void 0 ? primaryKey : returnedKey;
102
+ if (this.schema.collections[this.collection].fields[primaryKeyField].type === 'uuid') {
103
+ primaryKey = (0, helpers_1.getHelpers)(trx).schema.formatUUID(primaryKey !== null && primaryKey !== void 0 ? primaryKey : returnedKey);
104
+ }
105
+ else {
106
+ primaryKey = primaryKey !== null && primaryKey !== void 0 ? primaryKey : returnedKey;
107
+ }
102
108
  }
103
109
  catch (err) {
104
110
  throw await (0, translate_1.translateDatabaseError)(err);
@@ -40,7 +40,7 @@ class MetaService {
40
40
  if (!permissionsRecord)
41
41
  throw new exceptions_1.ForbiddenException();
42
42
  const permissions = (_d = permissionsRecord.permissions) !== null && _d !== void 0 ? _d : {};
43
- (0, apply_query_1.applyFilter)(this.knex, this.schema, dbQuery, permissions, collection);
43
+ (0, apply_query_1.applyFilter)(this.knex, this.schema, dbQuery, permissions, collection, {});
44
44
  }
45
45
  const result = await dbQuery;
46
46
  return Number((_e = result === null || result === void 0 ? void 0 : result.count) !== null && _e !== void 0 ? _e : 0);
@@ -64,7 +64,7 @@ class MetaService {
64
64
  }
65
65
  }
66
66
  if (Object.keys(filter).length > 0) {
67
- (0, apply_query_1.applyFilter)(this.knex, this.schema, dbQuery, filter, collection);
67
+ (0, apply_query_1.applyFilter)(this.knex, this.schema, dbQuery, filter, collection, {});
68
68
  }
69
69
  if (query.search) {
70
70
  (0, apply_query_1.applySearch)(this.schema, dbQuery, query.search, collection);
@@ -5,9 +5,7 @@ export declare class OperationsService extends ItemsService<OperationRaw> {
5
5
  constructor(options: AbstractServiceOptions);
6
6
  createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
7
7
  createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
8
- updateOne(key: PrimaryKey, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
9
8
  updateBatch(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
10
9
  updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
11
- deleteOne(key: PrimaryKey, opts?: MutationOptions): Promise<PrimaryKey>;
12
10
  deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
13
11
  }
@@ -19,12 +19,6 @@ class OperationsService extends items_1.ItemsService {
19
19
  await flowManager.reload();
20
20
  return result;
21
21
  }
22
- async updateOne(key, data, opts) {
23
- const flowManager = (0, flows_1.getFlowManager)();
24
- const result = await super.updateOne(key, data, opts);
25
- await flowManager.reload();
26
- return result;
27
- }
28
22
  async updateBatch(data, opts) {
29
23
  const flowManager = (0, flows_1.getFlowManager)();
30
24
  const result = await super.updateBatch(data, opts);
@@ -37,12 +31,6 @@ class OperationsService extends items_1.ItemsService {
37
31
  await flowManager.reload();
38
32
  return result;
39
33
  }
40
- async deleteOne(key, opts) {
41
- const flowManager = (0, flows_1.getFlowManager)();
42
- const result = await super.deleteOne(key, opts);
43
- await flowManager.reload();
44
- return result;
45
- }
46
34
  async deleteMany(keys, opts) {
47
35
  const flowManager = (0, flows_1.getFlowManager)();
48
36
  const result = await super.deleteMany(keys, opts);
@@ -0,0 +1 @@
1
+ export {};
@@ -10,13 +10,8 @@ export declare class PermissionsService extends ItemsService {
10
10
  readMany(keys: PrimaryKey[], query?: Query, opts?: QueryOptions): Promise<Partial<Item>[]>;
11
11
  createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
12
12
  createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
13
- updateByQuery(query: Query, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
14
- updateOne(key: PrimaryKey, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
15
13
  updateBatch(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
16
14
  updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
17
- upsertOne(payload: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
18
15
  upsertMany(payloads: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
19
- deleteByQuery(query: Query, opts?: MutationOptions): Promise<PrimaryKey[]>;
20
- deleteOne(key: PrimaryKey, opts?: MutationOptions): Promise<PrimaryKey>;
21
16
  deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
22
17
  }
@@ -60,16 +60,6 @@ class PermissionsService extends items_1.ItemsService {
60
60
  await (0, cache_1.clearSystemCache)();
61
61
  return res;
62
62
  }
63
- async updateByQuery(query, data, opts) {
64
- const res = await super.updateByQuery(query, data, opts);
65
- await (0, cache_1.clearSystemCache)();
66
- return res;
67
- }
68
- async updateOne(key, data, opts) {
69
- const res = await super.updateOne(key, data, opts);
70
- await (0, cache_1.clearSystemCache)();
71
- return res;
72
- }
73
63
  async updateBatch(data, opts) {
74
64
  const res = await super.updateBatch(data, opts);
75
65
  await (0, cache_1.clearSystemCache)();
@@ -80,26 +70,11 @@ class PermissionsService extends items_1.ItemsService {
80
70
  await (0, cache_1.clearSystemCache)();
81
71
  return res;
82
72
  }
83
- async upsertOne(payload, opts) {
84
- const res = await super.upsertOne(payload, opts);
85
- await (0, cache_1.clearSystemCache)();
86
- return res;
87
- }
88
73
  async upsertMany(payloads, opts) {
89
74
  const res = await super.upsertMany(payloads, opts);
90
75
  await (0, cache_1.clearSystemCache)();
91
76
  return res;
92
77
  }
93
- async deleteByQuery(query, opts) {
94
- const res = await super.deleteByQuery(query, opts);
95
- await (0, cache_1.clearSystemCache)();
96
- return res;
97
- }
98
- async deleteOne(key, opts) {
99
- const res = await super.deleteOne(key, opts);
100
- await (0, cache_1.clearSystemCache)();
101
- return res;
102
- }
103
78
  async deleteMany(keys, opts) {
104
79
  const res = await super.deleteMany(keys, opts);
105
80
  await (0, cache_1.clearSystemCache)();
@@ -0,0 +1 @@
1
+ export {};
@@ -21,13 +21,13 @@ export declare class RelationsService {
21
21
  /**
22
22
  * Create a new relationship / foreign key constraint
23
23
  */
24
- createOne(relation: Partial<Relation>): Promise<void>;
24
+ createOne(relation: Partial<Relation>, opts?: MutationOptions): Promise<void>;
25
25
  /**
26
26
  * Update an existing foreign key constraint
27
27
  *
28
28
  * Note: You can update anything under meta, but only the `on_delete` trigger under schema
29
29
  */
30
- updateOne(collection: string, field: string, relation: Partial<Relation>): Promise<void>;
30
+ updateOne(collection: string, field: string, relation: Partial<Relation>, opts?: MutationOptions): Promise<void>;
31
31
  /**
32
32
  * Delete an existing relationship
33
33
  */
@@ -127,7 +127,7 @@ class RelationsService {
127
127
  /**
128
128
  * Create a new relationship / foreign key constraint
129
129
  */
130
- async createOne(relation) {
130
+ async createOne(relation, opts) {
131
131
  if (this.accountability && this.accountability.admin !== true) {
132
132
  throw new exceptions_1.ForbiddenException();
133
133
  }
@@ -185,7 +185,7 @@ class RelationsService {
185
185
  // happens in `filterForbidden` down below
186
186
  });
187
187
  await relationsItemService.createOne(metaRow, {
188
- bypassEmitAction: (params) => nestedActionEvents.push(params),
188
+ bypassEmitAction: (params) => (opts === null || opts === void 0 ? void 0 : opts.bypassEmitAction) ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
189
189
  });
190
190
  });
191
191
  }
@@ -193,11 +193,15 @@ class RelationsService {
193
193
  if (runPostColumnChange) {
194
194
  await this.helpers.schema.postColumnChange();
195
195
  }
196
- await (0, cache_1.clearSystemCache)();
197
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
198
- for (const nestedActionEvent of nestedActionEvents) {
199
- nestedActionEvent.context.schema = updatedSchema;
200
- emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
196
+ if ((opts === null || opts === void 0 ? void 0 : opts.autoPurgeSystemCache) !== false) {
197
+ await (0, cache_1.clearSystemCache)();
198
+ }
199
+ if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
200
+ const updatedSchema = await (0, get_schema_1.getSchema)();
201
+ for (const nestedActionEvent of nestedActionEvents) {
202
+ nestedActionEvent.context.schema = updatedSchema;
203
+ emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
204
+ }
201
205
  }
202
206
  }
203
207
  }
@@ -206,7 +210,7 @@ class RelationsService {
206
210
  *
207
211
  * Note: You can update anything under meta, but only the `on_delete` trigger under schema
208
212
  */
209
- async updateOne(collection, field, relation) {
213
+ async updateOne(collection, field, relation, opts) {
210
214
  if (this.accountability && this.accountability.admin !== true) {
211
215
  throw new exceptions_1.ForbiddenException();
212
216
  }
@@ -254,7 +258,7 @@ class RelationsService {
254
258
  if (relation.meta) {
255
259
  if (existingRelation === null || existingRelation === void 0 ? void 0 : existingRelation.meta) {
256
260
  await relationsItemService.updateOne(existingRelation.meta.id, relation.meta, {
257
- bypassEmitAction: (params) => nestedActionEvents.push(params),
261
+ bypassEmitAction: (params) => (opts === null || opts === void 0 ? void 0 : opts.bypassEmitAction) ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
258
262
  });
259
263
  }
260
264
  else {
@@ -264,7 +268,7 @@ class RelationsService {
264
268
  many_field: relation.field,
265
269
  one_collection: existingRelation.related_collection || null,
266
270
  }, {
267
- bypassEmitAction: (params) => nestedActionEvents.push(params),
271
+ bypassEmitAction: (params) => (opts === null || opts === void 0 ? void 0 : opts.bypassEmitAction) ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
268
272
  });
269
273
  }
270
274
  }
@@ -274,11 +278,15 @@ class RelationsService {
274
278
  if (runPostColumnChange) {
275
279
  await this.helpers.schema.postColumnChange();
276
280
  }
277
- await (0, cache_1.clearSystemCache)();
278
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
279
- for (const nestedActionEvent of nestedActionEvents) {
280
- nestedActionEvent.context.schema = updatedSchema;
281
- emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
281
+ if ((opts === null || opts === void 0 ? void 0 : opts.autoPurgeSystemCache) !== false) {
282
+ await (0, cache_1.clearSystemCache)();
283
+ }
284
+ if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
285
+ const updatedSchema = await (0, get_schema_1.getSchema)();
286
+ for (const nestedActionEvent of nestedActionEvents) {
287
+ nestedActionEvent.context.schema = updatedSchema;
288
+ emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
289
+ }
282
290
  }
283
291
  }
284
292
  }
@@ -343,7 +351,7 @@ class RelationsService {
343
351
  await (0, cache_1.clearSystemCache)();
344
352
  }
345
353
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
346
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
354
+ const updatedSchema = await (0, get_schema_1.getSchema)();
347
355
  for (const nestedActionEvent of nestedActionEvents) {
348
356
  nestedActionEvent.context.schema = updatedSchema;
349
357
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -56,9 +56,6 @@ class RolesService extends items_1.ItemsService {
56
56
  return;
57
57
  }
58
58
  async updateOne(key, data, opts) {
59
- if ('admin_access' in data && data.admin_access === false) {
60
- await this.checkForOtherAdminRoles([key]);
61
- }
62
59
  if ('users' in data) {
63
60
  await this.checkForOtherAdminUsers(key, data.users);
64
61
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -28,7 +28,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.ServerService = void 0;
30
30
  const lodash_1 = require("lodash");
31
- const nanoid_1 = require("nanoid");
32
31
  const os_1 = __importDefault(require("os"));
33
32
  const perf_hooks_1 = require("perf_hooks");
34
33
  // @ts-ignore
@@ -38,11 +37,12 @@ const database_1 = __importStar(require("../database"));
38
37
  const env_1 = __importDefault(require("../env"));
39
38
  const logger_1 = __importDefault(require("../logger"));
40
39
  const rate_limiter_1 = require("../middleware/rate-limiter");
41
- const storage_1 = __importDefault(require("../storage"));
40
+ const storage_1 = require("../storage");
42
41
  const utils_1 = require("@directus/shared/utils");
43
42
  const mailer_1 = __importDefault(require("../mailer"));
44
43
  const settings_1 = require("./settings");
45
44
  const get_os_info_1 = require("../utils/get-os-info");
45
+ const node_stream_1 = require("node:stream");
46
46
  class ServerService {
47
47
  constructor(options) {
48
48
  this.knex = options.knex || (0, database_1.default)();
@@ -101,7 +101,8 @@ class ServerService {
101
101
  }
102
102
  async health() {
103
103
  var _a;
104
- const checkID = (0, nanoid_1.nanoid)(5);
104
+ const { nanoid } = await import('nanoid');
105
+ const checkID = nanoid(5);
105
106
  const data = {
106
107
  status: 'ok',
107
108
  releaseId: package_json_1.version,
@@ -246,9 +247,10 @@ class ServerService {
246
247
  return checks;
247
248
  }
248
249
  async function testStorage() {
250
+ const storage = await (0, storage_1.getStorage)();
249
251
  const checks = {};
250
252
  for (const location of (0, utils_1.toArray)(env_1.default.STORAGE_LOCATIONS)) {
251
- const disk = storage_1.default.disk(location);
253
+ const disk = storage.location(location);
252
254
  const envThresholdKey = `STORAGE_${location}_HEALTHCHECK_THRESHOLD`.toUpperCase();
253
255
  checks[`storage:${location}:responseTime`] = [
254
256
  {
@@ -261,8 +263,8 @@ class ServerService {
261
263
  ];
262
264
  const startTime = perf_hooks_1.performance.now();
263
265
  try {
264
- await disk.put(`health-${checkID}`, 'check');
265
- await disk.get(`health-${checkID}`);
266
+ await disk.write(`health-${checkID}`, node_stream_1.Readable.from(['check']));
267
+ await disk.read(`health-${checkID}`);
266
268
  await disk.delete(`health-${checkID}`);
267
269
  }
268
270
  catch (err) {
@@ -10,7 +10,6 @@ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
10
10
  const ms_1 = __importDefault(require("ms"));
11
11
  const exceptions_1 = require("../exceptions");
12
12
  const env_1 = __importDefault(require("../env"));
13
- const nanoid_1 = require("nanoid");
14
13
  const authorization_1 = require("./authorization");
15
14
  const users_1 = require("./users");
16
15
  const mail_1 = require("./mail");
@@ -32,6 +31,7 @@ class SharesService extends items_1.ItemsService {
32
31
  }
33
32
  async login(payload) {
34
33
  var _a, _b, _c;
34
+ const { nanoid } = await import('nanoid');
35
35
  const record = await this.knex
36
36
  .select({
37
37
  share_id: 'id',
@@ -79,7 +79,7 @@ class SharesService extends items_1.ItemsService {
79
79
  expiresIn: env_1.default.ACCESS_TOKEN_TTL,
80
80
  issuer: 'directus',
81
81
  });
82
- const refreshToken = (0, nanoid_1.nanoid)(64);
82
+ const refreshToken = nanoid(64);
83
83
  const refreshTokenExpiration = new Date(Date.now() + (0, ms_1.default)(env_1.default.REFRESH_TOKEN_TTL));
84
84
  await this.knex('directus_sessions').insert({
85
85
  token: refreshToken,
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.SpecificationService = void 0;
7
- const format_title_1 = __importDefault(require("@directus/format-title"));
8
7
  const specs_1 = __importDefault(require("@directus/specs"));
9
8
  const lodash_1 = require("lodash");
10
9
  // @ts-ignore
@@ -16,6 +15,9 @@ const collections_1 = require("./collections");
16
15
  const fields_1 = require("./fields");
17
16
  const graphql_1 = require("./graphql");
18
17
  const relations_1 = require("./relations");
18
+ const constants_1 = require("../constants");
19
+ // @ts-ignore
20
+ const format_title_1 = __importDefault(require("@directus/format-title"));
19
21
  class SpecificationService {
20
22
  constructor(options) {
21
23
  this.accountability = options.accountability || null;
@@ -330,10 +332,19 @@ class OASSpecsService {
330
332
  return paths;
331
333
  }
332
334
  async generateComponents(collections, fields, relations, tags) {
335
+ var _a;
333
336
  let components = (0, lodash_1.cloneDeep)(specs_1.default.components);
334
337
  if (!components)
335
338
  components = {};
336
339
  components.schemas = {};
340
+ // Always includes the schemas with these names
341
+ if (((_a = specs_1.default.components) === null || _a === void 0 ? void 0 : _a.schemas) !== null) {
342
+ for (const schemaName of constants_1.OAS_REQUIRED_SCHEMAS) {
343
+ if (specs_1.default.components.schemas[schemaName] !== null) {
344
+ components.schemas[schemaName] = (0, lodash_1.cloneDeep)(specs_1.default.components.schemas[schemaName]);
345
+ }
346
+ }
347
+ }
337
348
  if (!tags)
338
349
  return;
339
350
  for (const collection of collections) {
@@ -202,11 +202,17 @@ class UsersService extends items_1.ItemsService {
202
202
  if (data.tfa_secret !== undefined) {
203
203
  throw new exceptions_2.InvalidPayloadException(`You can't change the "tfa_secret" value manually.`);
204
204
  }
205
- if (data.provider !== undefined && this.accountability && this.accountability.admin !== true) {
206
- throw new exceptions_2.InvalidPayloadException(`You can't change the "provider" value manually.`);
205
+ if (data.provider !== undefined) {
206
+ if (this.accountability && this.accountability.admin !== true) {
207
+ throw new exceptions_2.InvalidPayloadException(`You can't change the "provider" value manually.`);
208
+ }
209
+ data.auth_data = null;
207
210
  }
208
- if (data.external_identifier !== undefined && this.accountability && this.accountability.admin !== true) {
209
- throw new exceptions_2.InvalidPayloadException(`You can't change the "external_identifier" value manually.`);
211
+ if (data.external_identifier !== undefined) {
212
+ if (this.accountability && this.accountability.admin !== true) {
213
+ throw new exceptions_2.InvalidPayloadException(`You can't change the "external_identifier" value manually.`);
214
+ }
215
+ data.auth_data = null;
210
216
  }
211
217
  return await super.updateMany(keys, data, opts);
212
218
  }
@@ -6,8 +6,6 @@ export declare class WebhooksService extends ItemsService<Webhook> {
6
6
  constructor(options: AbstractServiceOptions);
7
7
  createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
8
8
  createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
9
- updateOne(key: PrimaryKey, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
10
9
  updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
11
- deleteOne(key: PrimaryKey, opts?: MutationOptions): Promise<PrimaryKey>;
12
10
  deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
13
11
  }
@@ -18,21 +18,11 @@ class WebhooksService extends items_1.ItemsService {
18
18
  this.messenger.publish('webhooks', { type: 'reload' });
19
19
  return result;
20
20
  }
21
- async updateOne(key, data, opts) {
22
- const result = await super.updateOne(key, data, opts);
23
- this.messenger.publish('webhooks', { type: 'reload' });
24
- return result;
25
- }
26
21
  async updateMany(keys, data, opts) {
27
22
  const result = await super.updateMany(keys, data, opts);
28
23
  this.messenger.publish('webhooks', { type: 'reload' });
29
24
  return result;
30
25
  }
31
- async deleteOne(key, opts) {
32
- const result = await super.deleteOne(key, opts);
33
- this.messenger.publish('webhooks', { type: 'reload' });
34
- return result;
35
- }
36
26
  async deleteMany(keys, opts) {
37
27
  const result = await super.deleteMany(keys, opts);
38
28
  this.messenger.publish('webhooks', { type: 'reload' });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { Driver } from '@directus/storage';
2
+ export declare const _aliasMap: Record<string, string>;
3
+ export declare const getStorageDriver: (driverName: string) => Promise<typeof Driver>;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getStorageDriver = exports._aliasMap = void 0;
4
+ exports._aliasMap = {
5
+ local: '@directus/storage-driver-local',
6
+ s3: '@directus/storage-driver-s3',
7
+ gcs: '@directus/storage-driver-gcs',
8
+ azure: '@directus/storage-driver-azure',
9
+ cloudinary: '@directus/storage-driver-cloudinary',
10
+ };
11
+ const getStorageDriver = async (driverName) => {
12
+ if (driverName in exports._aliasMap) {
13
+ driverName = exports._aliasMap[driverName];
14
+ }
15
+ else {
16
+ throw new Error(`Driver "${driverName}" doesn't exist.`);
17
+ }
18
+ return (await import(driverName)).default;
19
+ };
20
+ exports.getStorageDriver = getStorageDriver;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { StorageManager } from '@directus/storage';
2
+ export declare const _cache: {
3
+ storage: any | null;
4
+ };
5
+ export declare const getStorage: () => Promise<StorageManager>;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getStorage = exports._cache = void 0;
4
+ const validate_env_1 = require("../utils/validate-env");
5
+ const register_drivers_1 = require("./register-drivers");
6
+ const register_locations_1 = require("./register-locations");
7
+ exports._cache = {
8
+ storage: null,
9
+ };
10
+ const getStorage = async () => {
11
+ if (exports._cache.storage)
12
+ return exports._cache.storage;
13
+ const { StorageManager } = await import('@directus/storage');
14
+ (0, validate_env_1.validateEnv)(['STORAGE_LOCATIONS']);
15
+ exports._cache.storage = new StorageManager();
16
+ await (0, register_drivers_1.registerDrivers)(exports._cache.storage);
17
+ await (0, register_locations_1.registerLocations)(exports._cache.storage);
18
+ return exports._cache.storage;
19
+ };
20
+ exports.getStorage = getStorage;