directus 9.21.2 → 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 (103) hide show
  1. package/dist/app.js +9 -5
  2. package/dist/app.test.d.ts +1 -0
  3. package/dist/cli/commands/bootstrap/index.js +2 -2
  4. package/dist/cli/commands/security/secret.js +2 -2
  5. package/dist/cli/utils/create-env/env-stub.liquid +3 -3
  6. package/dist/cli/utils/create-env/index.js +5 -8
  7. package/dist/constants.d.ts +1 -0
  8. package/dist/constants.js +2 -1
  9. package/dist/controllers/assets.js +9 -7
  10. package/dist/controllers/files.js +2 -1
  11. package/dist/controllers/utils.js +2 -2
  12. package/dist/database/helpers/fn/dialects/mssql.js +2 -1
  13. package/dist/database/helpers/fn/dialects/mysql.js +2 -1
  14. package/dist/database/helpers/fn/dialects/oracle.js +2 -1
  15. package/dist/database/helpers/fn/dialects/postgres.js +2 -1
  16. package/dist/database/helpers/fn/dialects/sqlite.js +2 -1
  17. package/dist/database/helpers/fn/types.d.ts +1 -0
  18. package/dist/database/helpers/fn/types.js +5 -4
  19. package/dist/database/helpers/index.d.ts +1 -1
  20. package/dist/database/helpers/schema/dialects/mssql.d.ts +6 -0
  21. package/dist/database/helpers/schema/dialects/mssql.js +14 -0
  22. package/dist/database/helpers/schema/dialects/mysql.d.ts +5 -0
  23. package/dist/database/helpers/schema/dialects/mysql.js +19 -0
  24. package/dist/database/helpers/schema/dialects/oracle.d.ts +1 -0
  25. package/dist/database/helpers/schema/dialects/oracle.js +3 -0
  26. package/dist/database/helpers/schema/index.d.ts +2 -2
  27. package/dist/database/helpers/schema/index.js +4 -4
  28. package/dist/database/helpers/schema/types.d.ts +5 -0
  29. package/dist/database/helpers/schema/types.js +13 -0
  30. package/dist/database/index.d.ts +6 -0
  31. package/dist/database/index.js +20 -1
  32. package/dist/database/migrations/20211007A-update-presets.js +2 -2
  33. package/dist/database/migrations/run.js +7 -31
  34. package/dist/database/run-ast.js +132 -6
  35. package/dist/database/system-data/fields/index.js +2 -1
  36. package/dist/env.js +3 -2
  37. package/dist/exceptions/range-not-satisfiable.d.ts +1 -1
  38. package/dist/extensions.d.ts +7 -1
  39. package/dist/extensions.js +41 -15
  40. package/dist/logger.js +27 -1
  41. package/dist/operations/request/index.d.ts +1 -2
  42. package/dist/operations/request/index.js +2 -2
  43. package/dist/services/assets.d.ts +4 -3
  44. package/dist/services/assets.js +13 -11
  45. package/dist/services/authentication.js +4 -3
  46. package/dist/services/authorization.js +1 -1
  47. package/dist/services/files.d.ts +4 -3
  48. package/dist/services/files.js +92 -68
  49. package/dist/services/flows.d.ts +0 -2
  50. package/dist/services/flows.js +0 -14
  51. package/dist/services/flows.test.d.ts +1 -0
  52. package/dist/services/graphql/index.d.ts +5 -1
  53. package/dist/services/graphql/index.js +29 -31
  54. package/dist/services/import-export.d.ts +4 -3
  55. package/dist/services/items.js +7 -1
  56. package/dist/services/meta.js +2 -2
  57. package/dist/services/operations.d.ts +0 -2
  58. package/dist/services/operations.js +0 -12
  59. package/dist/services/operations.test.d.ts +1 -0
  60. package/dist/services/permissions.d.ts +0 -5
  61. package/dist/services/permissions.js +0 -25
  62. package/dist/services/permissions.test.d.ts +1 -0
  63. package/dist/services/roles.js +0 -3
  64. package/dist/services/roles.test.d.ts +1 -0
  65. package/dist/services/server.js +8 -6
  66. package/dist/services/shares.js +2 -2
  67. package/dist/services/specifications.js +12 -1
  68. package/dist/services/webhooks.d.ts +0 -2
  69. package/dist/services/webhooks.js +0 -10
  70. package/dist/services/webhooks.test.d.ts +1 -0
  71. package/dist/storage/get-storage-driver.d.ts +3 -0
  72. package/dist/storage/get-storage-driver.js +20 -0
  73. package/dist/storage/get-storage-driver.test.d.ts +1 -0
  74. package/dist/storage/index.d.ts +5 -0
  75. package/dist/storage/index.js +20 -0
  76. package/dist/storage/index.test.d.ts +1 -0
  77. package/dist/storage/register-drivers.d.ts +2 -0
  78. package/dist/storage/register-drivers.js +22 -0
  79. package/dist/storage/register-drivers.test.d.ts +1 -0
  80. package/dist/storage/register-locations.d.ts +2 -0
  81. package/dist/storage/register-locations.js +17 -0
  82. package/dist/storage/register-locations.test.d.ts +1 -0
  83. package/dist/utils/apply-query.d.ts +27 -3
  84. package/dist/utils/apply-query.js +180 -127
  85. package/dist/utils/dynamic-import.d.ts +1 -0
  86. package/dist/utils/dynamic-import.js +7 -0
  87. package/dist/utils/get-collection-from-alias.d.ts +6 -0
  88. package/dist/utils/get-collection-from-alias.js +15 -0
  89. package/dist/utils/get-collection-from-alias.test.d.ts +1 -0
  90. package/dist/utils/get-column-path.d.ts +14 -8
  91. package/dist/utils/get-column-path.js +24 -7
  92. package/dist/utils/get-column.d.ts +8 -1
  93. package/dist/utils/get-column.js +10 -3
  94. package/dist/utils/get-config-from-env.js +3 -2
  95. package/dist/utils/get-default-value.d.ts +1 -1
  96. package/dist/utils/parse-image-metadata.d.ts +3 -0
  97. package/dist/utils/parse-image-metadata.js +73 -0
  98. package/dist/utils/track.js +2 -2
  99. package/dist/utils/validate-env.js +3 -2
  100. package/dist/webhooks.js +2 -2
  101. package/package.json +17 -11
  102. package/dist/storage.d.ts +0 -3
  103. package/dist/storage.js +0 -61
@@ -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 {};
@@ -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) {
@@ -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;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { StorageManager } from '@directus/storage';
2
+ export declare const registerDrivers: (storage: StorageManager) => Promise<void>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerDrivers = void 0;
4
+ const env_1 = require("../env");
5
+ const get_storage_driver_1 = require("./get-storage-driver");
6
+ const registerDrivers = async (storage) => {
7
+ const env = (0, env_1.getEnv)();
8
+ const usedDrivers = [];
9
+ for (const [key, value] of Object.entries(env)) {
10
+ if ((key.startsWith('STORAGE_') && key.endsWith('_DRIVER')) === false)
11
+ continue;
12
+ if (value && usedDrivers.includes(value) === false)
13
+ usedDrivers.push(value);
14
+ }
15
+ for (const driverName of usedDrivers) {
16
+ const storageDriver = await (0, get_storage_driver_1.getStorageDriver)(driverName);
17
+ if (storageDriver) {
18
+ storage.registerDriver(driverName, storageDriver);
19
+ }
20
+ }
21
+ };
22
+ exports.registerDrivers = registerDrivers;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { StorageManager } from '@directus/storage';
2
+ export declare const registerLocations: (storage: StorageManager) => Promise<void>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerLocations = void 0;
4
+ const utils_1 = require("@directus/shared/utils");
5
+ const env_1 = require("../env");
6
+ const get_config_from_env_1 = require("../utils/get-config-from-env");
7
+ const registerLocations = async (storage) => {
8
+ const env = (0, env_1.getEnv)();
9
+ const locations = (0, utils_1.toArray)(env.STORAGE_LOCATIONS);
10
+ locations.forEach((location) => {
11
+ location = location.trim();
12
+ const driverConfig = (0, get_config_from_env_1.getConfigFromEnv)(`STORAGE_${location.toUpperCase()}_`);
13
+ const { driver, ...options } = driverConfig;
14
+ storage.registerLocation(location, { driver, options });
15
+ });
16
+ };
17
+ exports.registerLocations = registerLocations;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,10 +1,34 @@
1
1
  import { Aggregate, Filter, Query, SchemaOverview } from '@directus/shared/types';
2
2
  import { Knex } from 'knex';
3
+ import { AliasMap } from './get-column-path';
4
+ export declare const generateAlias: () => string;
3
5
  /**
4
6
  * Apply the Query to a given Knex query builder instance
5
7
  */
6
- export default function applyQuery(knex: Knex, collection: string, dbQuery: Knex.QueryBuilder, query: Query, schema: SchemaOverview, subQuery?: boolean): Knex.QueryBuilder;
7
- export declare function applySort(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootSort: string[], collection: string, subQuery?: boolean): void;
8
- export declare function applyFilter(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootFilter: Filter, collection: string, subQuery?: boolean): Knex.QueryBuilder<any, any>;
8
+ export default function applyQuery(knex: Knex, collection: string, dbQuery: Knex.QueryBuilder, query: Query, schema: SchemaOverview, options?: {
9
+ aliasMap?: AliasMap;
10
+ isInnerQuery?: boolean;
11
+ hasMultiRelationalSort?: boolean;
12
+ }): {
13
+ query: Knex.QueryBuilder<any, any>;
14
+ hasMultiRelationalFilter: boolean;
15
+ };
16
+ export type ColumnSortRecord = {
17
+ order: 'asc' | 'desc';
18
+ column: string;
19
+ };
20
+ export declare function applySort(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootSort: string[], collection: string, aliasMap: AliasMap, returnRecords?: boolean): {
21
+ sortRecords: {
22
+ order: "asc" | "desc";
23
+ column: any;
24
+ }[];
25
+ hasMultiRelationalSort: boolean;
26
+ } | undefined;
27
+ export declare function applyLimit(rootQuery: Knex.QueryBuilder, limit: any): void;
28
+ export declare function applyOffset(knex: Knex, rootQuery: Knex.QueryBuilder, offset: any): void;
29
+ export declare function applyFilter(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootFilter: Filter, collection: string, aliasMap: AliasMap): {
30
+ query: Knex.QueryBuilder<any, any>;
31
+ hasMultiRelationalFilter: boolean;
32
+ };
9
33
  export declare function applySearch(schema: SchemaOverview, dbQuery: Knex.QueryBuilder, searchQuery: string, collection: string): Promise<void>;
10
34
  export declare function applyAggregate(dbQuery: Knex.QueryBuilder, aggregate: Aggregate, collection: string): void;