directus 9.23.3 → 9.24.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 (132) hide show
  1. package/dist/app.js +15 -15
  2. package/dist/auth/drivers/ldap.js +22 -22
  3. package/dist/auth/drivers/local.js +7 -7
  4. package/dist/auth/drivers/oauth2.js +27 -25
  5. package/dist/auth/drivers/openid.js +32 -30
  6. package/dist/auth/drivers/saml.js +10 -10
  7. package/dist/auth.js +4 -3
  8. package/dist/cache.js +16 -11
  9. package/dist/cli/commands/bootstrap/index.js +5 -4
  10. package/dist/cli/utils/create-db-connection.js +1 -1
  11. package/dist/cli/utils/create-env/index.js +1 -1
  12. package/dist/constants.d.ts +1 -0
  13. package/dist/constants.js +6 -5
  14. package/dist/controllers/activity.js +10 -10
  15. package/dist/controllers/assets.js +19 -18
  16. package/dist/controllers/auth.js +16 -16
  17. package/dist/controllers/collections.js +11 -11
  18. package/dist/controllers/dashboards.js +11 -11
  19. package/dist/controllers/extensions.js +3 -3
  20. package/dist/controllers/fields.js +17 -17
  21. package/dist/controllers/files.js +18 -17
  22. package/dist/controllers/flows.js +13 -13
  23. package/dist/controllers/folders.js +11 -11
  24. package/dist/controllers/graphql.js +6 -6
  25. package/dist/controllers/items.js +19 -19
  26. package/dist/controllers/notifications.js +11 -11
  27. package/dist/controllers/operations.js +11 -11
  28. package/dist/controllers/panels.js +11 -11
  29. package/dist/controllers/permissions.js +11 -11
  30. package/dist/controllers/presets.js +11 -11
  31. package/dist/controllers/relations.js +11 -11
  32. package/dist/controllers/revisions.js +3 -3
  33. package/dist/controllers/roles.js +11 -11
  34. package/dist/controllers/schema.js +5 -5
  35. package/dist/controllers/server.js +7 -7
  36. package/dist/controllers/settings.js +2 -2
  37. package/dist/controllers/shares.js +14 -14
  38. package/dist/controllers/users.js +16 -16
  39. package/dist/controllers/utils.js +7 -7
  40. package/dist/controllers/webhooks.js +11 -11
  41. package/dist/database/helpers/fn/types.d.ts +0 -1
  42. package/dist/database/helpers/fn/types.js +0 -2
  43. package/dist/database/helpers/index.d.ts +3 -3
  44. package/dist/database/index.js +5 -5
  45. package/dist/database/migrations/20210805B-change-image-metadata-structure.js +15 -15
  46. package/dist/database/migrations/run.js +1 -1
  47. package/dist/database/run-ast.js +6 -6
  48. package/dist/database/system-data/collections/index.js +2 -2
  49. package/dist/database/system-data/fields/index.js +3 -3
  50. package/dist/env.js +1 -1
  51. package/dist/exceptions/database/dialects/mssql.js +2 -2
  52. package/dist/exceptions/database/dialects/mysql.js +6 -6
  53. package/dist/exceptions/database/record-not-unique.d.ts +1 -1
  54. package/dist/extensions.js +10 -10
  55. package/dist/flows.js +33 -31
  56. package/dist/logger.d.ts +1 -0
  57. package/dist/logger.js +32 -32
  58. package/dist/mailer.js +16 -16
  59. package/dist/messenger.js +4 -4
  60. package/dist/middleware/authenticate.d.ts +1 -1
  61. package/dist/middleware/authenticate.js +2 -2
  62. package/dist/middleware/cache.js +11 -11
  63. package/dist/middleware/collection-exists.js +4 -4
  64. package/dist/middleware/cors.js +8 -8
  65. package/dist/middleware/error-handler.js +2 -2
  66. package/dist/middleware/extract-token.js +3 -3
  67. package/dist/middleware/get-permissions.js +1 -1
  68. package/dist/middleware/graphql.js +12 -6
  69. package/dist/middleware/rate-limiter-global.js +5 -5
  70. package/dist/middleware/rate-limiter-ip.js +2 -2
  71. package/dist/middleware/respond.js +16 -16
  72. package/dist/middleware/sanitize-query.js +1 -1
  73. package/dist/middleware/schema.js +1 -1
  74. package/dist/middleware/use-collection.js +1 -1
  75. package/dist/middleware/validate-batch.js +1 -1
  76. package/dist/operations/exec/index.js +2 -2
  77. package/dist/rate-limiter.js +1 -1
  78. package/dist/request/validate-ip.js +2 -2
  79. package/dist/server.js +4 -4
  80. package/dist/services/activity.js +14 -14
  81. package/dist/services/assets.js +6 -6
  82. package/dist/services/authentication.js +9 -9
  83. package/dist/services/collections.js +9 -9
  84. package/dist/services/fields.js +5 -5
  85. package/dist/services/files.js +18 -18
  86. package/dist/services/graphql/index.js +170 -116
  87. package/dist/services/import-export.js +6 -6
  88. package/dist/services/items.js +6 -6
  89. package/dist/services/mail/index.js +5 -5
  90. package/dist/services/meta.js +1 -0
  91. package/dist/services/notifications.js +4 -4
  92. package/dist/services/relations.js +4 -4
  93. package/dist/services/revisions.js +3 -3
  94. package/dist/services/roles.js +5 -5
  95. package/dist/services/server.js +27 -27
  96. package/dist/services/shares.js +9 -9
  97. package/dist/services/specifications.js +5 -3
  98. package/dist/services/users.d.ts +1 -5
  99. package/dist/services/users.js +24 -27
  100. package/dist/storage/register-locations.js +1 -1
  101. package/dist/utils/apply-diff.js +12 -12
  102. package/dist/utils/apply-query.js +3 -2
  103. package/dist/utils/dynamic-import.js +1 -1
  104. package/dist/utils/generate-hash.js +1 -1
  105. package/dist/utils/get-ast-from-query.js +2 -2
  106. package/dist/utils/get-auth-providers.js +1 -1
  107. package/dist/utils/get-cache-headers.js +3 -3
  108. package/dist/utils/get-collection-from-alias.js +1 -0
  109. package/dist/utils/get-column-path.js +2 -1
  110. package/dist/utils/get-default-value.js +1 -1
  111. package/dist/utils/get-ip-from-req.js +2 -2
  112. package/dist/utils/get-permissions.js +11 -11
  113. package/dist/utils/get-schema.js +5 -5
  114. package/dist/utils/get-snapshot-diff.js +1 -1
  115. package/dist/utils/is-url-allowed.js +5 -2
  116. package/dist/utils/parse-image-metadata.js +3 -3
  117. package/dist/utils/reduce-schema.js +5 -5
  118. package/dist/utils/sanitize-query.js +26 -26
  119. package/dist/utils/should-skip-cache.js +13 -4
  120. package/dist/utils/strip-function.js +1 -1
  121. package/dist/utils/telemetry.d.ts +1 -0
  122. package/dist/utils/telemetry.js +30 -0
  123. package/dist/utils/validate-keys.js +1 -1
  124. package/dist/utils/validate-query.js +1 -1
  125. package/dist/utils/validate-storage.js +8 -8
  126. package/dist/webhooks.js +2 -2
  127. package/package.json +13 -13
  128. package/dist/utils/redact-header-cookies.d.ts +0 -1
  129. package/dist/utils/redact-header-cookies.js +0 -11
  130. package/dist/utils/track.d.ts +0 -1
  131. package/dist/utils/track.js +0 -81
  132. /package/dist/{utils/redact-header-cookies.test.d.ts → logger.test.d.ts} +0 -0
@@ -17,10 +17,10 @@ exports.parseGraphQL = (0, async_handler_1.default)(async (req, res, next) => {
17
17
  let operationName = null;
18
18
  let document;
19
19
  if (req.method === 'GET') {
20
- query = req.query.query || null;
21
- if (req.query.variables) {
20
+ query = req.query['query'] || null;
21
+ if (req.query['variables']) {
22
22
  try {
23
- variables = (0, utils_1.parseJSON)(req.query.variables);
23
+ variables = (0, utils_1.parseJSON)(req.query['variables']);
24
24
  }
25
25
  catch {
26
26
  throw new exceptions_1.InvalidQueryException(`Variables are invalid JSON.`);
@@ -29,7 +29,7 @@ exports.parseGraphQL = (0, async_handler_1.default)(async (req, res, next) => {
29
29
  else {
30
30
  variables = {};
31
31
  }
32
- operationName = req.query.operationName || null;
32
+ operationName = req.query['operationName'] || null;
33
33
  }
34
34
  else {
35
35
  query = req.body.query || null;
@@ -56,8 +56,14 @@ exports.parseGraphQL = (0, async_handler_1.default)(async (req, res, next) => {
56
56
  }
57
57
  // Prevent caching responses when mutations are made
58
58
  if (operationAST?.operation === 'mutation') {
59
- res.locals.cache = false;
59
+ res.locals['cache'] = false;
60
60
  }
61
- res.locals.graphqlParams = { document, query, variables, operationName, contextValue: { req, res } };
61
+ res.locals['graphqlParams'] = {
62
+ document,
63
+ query,
64
+ variables,
65
+ operationName,
66
+ contextValue: { req, res },
67
+ };
62
68
  return next();
63
69
  });
@@ -13,7 +13,7 @@ const async_handler_1 = __importDefault(require("../utils/async-handler"));
13
13
  const validate_env_1 = require("../utils/validate-env");
14
14
  const RATE_LIMITER_GLOBAL_KEY = 'global-rate-limit';
15
15
  let checkRateLimit = (_req, _res, next) => next();
16
- if (env_1.default.RATE_LIMITER_GLOBAL_ENABLED === true) {
16
+ if (env_1.default['RATE_LIMITER_GLOBAL_ENABLED'] === true) {
17
17
  (0, validate_env_1.validateEnv)(['RATE_LIMITER_GLOBAL_STORE', 'RATE_LIMITER_GLOBAL_DURATION', 'RATE_LIMITER_GLOBAL_POINTS']);
18
18
  validateConfiguration();
19
19
  exports.rateLimiterGlobal = (0, rate_limiter_1.createRateLimiter)('RATE_LIMITER_GLOBAL');
@@ -26,7 +26,7 @@ if (env_1.default.RATE_LIMITER_GLOBAL_ENABLED === true) {
26
26
  throw rateLimiterRes;
27
27
  res.set('Retry-After', String(Math.round(rateLimiterRes.msBeforeNext / 1000)));
28
28
  throw new index_1.HitRateLimitException(`Too many requests, retry after ${(0, ms_1.default)(rateLimiterRes.msBeforeNext)}.`, {
29
- limit: +env_1.default.RATE_LIMITER_GLOBAL_POINTS,
29
+ limit: +env_1.default['RATE_LIMITER_GLOBAL_POINTS'],
30
30
  reset: new Date(Date.now() + rateLimiterRes.msBeforeNext),
31
31
  });
32
32
  }
@@ -35,12 +35,12 @@ if (env_1.default.RATE_LIMITER_GLOBAL_ENABLED === true) {
35
35
  }
36
36
  exports.default = checkRateLimit;
37
37
  function validateConfiguration() {
38
- if (env_1.default.RATE_LIMITER_ENABLED !== true) {
38
+ if (env_1.default['RATE_LIMITER_ENABLED'] !== true) {
39
39
  logger_1.default.error(`The IP based rate limiter needs to be enabled when using the global rate limiter.`);
40
40
  process.exit(1);
41
41
  }
42
- const globalPointsPerSec = Number(env_1.default.RATE_LIMITER_GLOBAL_POINTS) / Math.max(Number(env_1.default.RATE_LIMITER_GLOBAL_DURATION), 1);
43
- const regularPointsPerSec = Number(env_1.default.RATE_LIMITER_POINTS) / Math.max(Number(env_1.default.RATE_LIMITER_DURATION), 1);
42
+ const globalPointsPerSec = Number(env_1.default['RATE_LIMITER_GLOBAL_POINTS']) / Math.max(Number(env_1.default['RATE_LIMITER_GLOBAL_DURATION']), 1);
43
+ const regularPointsPerSec = Number(env_1.default['RATE_LIMITER_POINTS']) / Math.max(Number(env_1.default['RATE_LIMITER_DURATION']), 1);
44
44
  if (globalPointsPerSec <= regularPointsPerSec) {
45
45
  logger_1.default.error(`The global rate limiter needs to allow more requests per second than the IP based rate limiter.`);
46
46
  process.exit(1);
@@ -12,7 +12,7 @@ const async_handler_1 = __importDefault(require("../utils/async-handler"));
12
12
  const get_ip_from_req_1 = require("../utils/get-ip-from-req");
13
13
  const validate_env_1 = require("../utils/validate-env");
14
14
  let checkRateLimit = (_req, _res, next) => next();
15
- if (env_1.default.RATE_LIMITER_ENABLED === true) {
15
+ if (env_1.default['RATE_LIMITER_ENABLED'] === true) {
16
16
  (0, validate_env_1.validateEnv)(['RATE_LIMITER_STORE', 'RATE_LIMITER_DURATION', 'RATE_LIMITER_POINTS']);
17
17
  exports.rateLimiter = (0, rate_limiter_1.createRateLimiter)('RATE_LIMITER');
18
18
  checkRateLimit = (0, async_handler_1.default)(async (req, res, next) => {
@@ -24,7 +24,7 @@ if (env_1.default.RATE_LIMITER_ENABLED === true) {
24
24
  throw rateLimiterRes;
25
25
  res.set('Retry-After', String(Math.round(rateLimiterRes.msBeforeNext / 1000)));
26
26
  throw new exceptions_1.HitRateLimitException(`Too many requests, retry after ${(0, ms_1.default)(rateLimiterRes.msBeforeNext)}.`, {
27
- limit: +env_1.default.RATE_LIMITER_POINTS,
27
+ limit: +env_1.default['RATE_LIMITER_POINTS'],
28
28
  reset: new Date(Date.now() + rateLimiterRes.msBeforeNext),
29
29
  });
30
30
  }
@@ -18,26 +18,26 @@ const get_string_byte_size_1 = require("../utils/get-string-byte-size");
18
18
  exports.respond = (0, async_handler_1.default)(async (req, res) => {
19
19
  const { cache } = (0, cache_1.getCache)();
20
20
  let exceedsMaxSize = false;
21
- if (env_1.default.CACHE_VALUE_MAX_SIZE !== false) {
22
- const valueSize = res.locals.payload ? (0, get_string_byte_size_1.stringByteSize)(JSON.stringify(res.locals.payload)) : 0;
23
- const maxSize = (0, bytes_1.parse)(env_1.default.CACHE_VALUE_MAX_SIZE);
21
+ if (env_1.default['CACHE_VALUE_MAX_SIZE'] !== false) {
22
+ const valueSize = res.locals['payload'] ? (0, get_string_byte_size_1.stringByteSize)(JSON.stringify(res.locals['payload'])) : 0;
23
+ const maxSize = (0, bytes_1.parse)(env_1.default['CACHE_VALUE_MAX_SIZE']);
24
24
  exceedsMaxSize = valueSize > maxSize;
25
25
  }
26
26
  if ((req.method.toLowerCase() === 'get' || req.originalUrl?.startsWith('/graphql')) &&
27
- env_1.default.CACHE_ENABLED === true &&
27
+ env_1.default['CACHE_ENABLED'] === true &&
28
28
  cache &&
29
29
  !req.sanitizedQuery.export &&
30
- res.locals.cache !== false &&
30
+ res.locals['cache'] !== false &&
31
31
  exceedsMaxSize === false) {
32
32
  const key = (0, get_cache_key_1.getCacheKey)(req);
33
33
  try {
34
- await (0, cache_1.setCacheValue)(cache, key, res.locals.payload, (0, get_milliseconds_1.getMilliseconds)(env_1.default.CACHE_TTL));
35
- await (0, cache_1.setCacheValue)(cache, `${key}__expires_at`, { exp: Date.now() + (0, get_milliseconds_1.getMilliseconds)(env_1.default.CACHE_TTL, 0) });
34
+ await (0, cache_1.setCacheValue)(cache, key, res.locals['payload'], (0, get_milliseconds_1.getMilliseconds)(env_1.default['CACHE_TTL']));
35
+ await (0, cache_1.setCacheValue)(cache, `${key}__expires_at`, { exp: Date.now() + (0, get_milliseconds_1.getMilliseconds)(env_1.default['CACHE_TTL'], 0) });
36
36
  }
37
37
  catch (err) {
38
38
  logger_1.default.warn(err, `[cache] Couldn't set key ${key}. ${err}`);
39
39
  }
40
- res.setHeader('Cache-Control', (0, get_cache_headers_1.getCacheControlHeader)(req, (0, get_milliseconds_1.getMilliseconds)(env_1.default.CACHE_TTL), true, true));
40
+ res.setHeader('Cache-Control', (0, get_cache_headers_1.getCacheControlHeader)(req, (0, get_milliseconds_1.getMilliseconds)(env_1.default['CACHE_TTL']), true, true));
41
41
  res.setHeader('Vary', 'Origin, Cache-Control');
42
42
  }
43
43
  else {
@@ -58,29 +58,29 @@ exports.respond = (0, async_handler_1.default)(async (req, res) => {
58
58
  if (req.sanitizedQuery.export === 'json') {
59
59
  res.attachment(`${filename}.json`);
60
60
  res.set('Content-Type', 'application/json');
61
- return res.status(200).send(exportService.transform(res.locals.payload?.data, 'json'));
61
+ return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'json'));
62
62
  }
63
63
  if (req.sanitizedQuery.export === 'xml') {
64
64
  res.attachment(`${filename}.xml`);
65
65
  res.set('Content-Type', 'text/xml');
66
- return res.status(200).send(exportService.transform(res.locals.payload?.data, 'xml'));
66
+ return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'xml'));
67
67
  }
68
68
  if (req.sanitizedQuery.export === 'csv') {
69
69
  res.attachment(`${filename}.csv`);
70
70
  res.set('Content-Type', 'text/csv');
71
- return res.status(200).send(exportService.transform(res.locals.payload?.data, 'csv'));
71
+ return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'csv'));
72
72
  }
73
73
  if (req.sanitizedQuery.export === 'yaml') {
74
74
  res.attachment(`${filename}.yaml`);
75
75
  res.set('Content-Type', 'text/yaml');
76
- return res.status(200).send(exportService.transform(res.locals.payload?.data, 'yaml'));
76
+ return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'yaml'));
77
77
  }
78
78
  }
79
- if (Buffer.isBuffer(res.locals.payload)) {
80
- return res.end(res.locals.payload);
79
+ if (Buffer.isBuffer(res.locals['payload'])) {
80
+ return res.end(res.locals['payload']);
81
81
  }
82
- else if (res.locals.payload) {
83
- return res.json(res.locals.payload);
82
+ else if (res.locals['payload']) {
83
+ return res.json(res.locals['payload']);
84
84
  }
85
85
  else {
86
86
  return res.status(204).end();
@@ -11,7 +11,7 @@ const sanitizeQueryMiddleware = (req, _res, next) => {
11
11
  if (!req.query)
12
12
  return;
13
13
  req.sanitizedQuery = (0, sanitize_query_1.sanitizeQuery)({
14
- fields: req.query.fields || '*',
14
+ fields: req.query['fields'] || '*',
15
15
  ...req.query,
16
16
  }, req.accountability || null);
17
17
  Object.freeze(req.sanitizedQuery);
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const async_handler_1 = __importDefault(require("../utils/async-handler"));
7
7
  const get_schema_1 = require("../utils/get-schema");
8
- const schema = (0, async_handler_1.default)(async (req, res, next) => {
8
+ const schema = (0, async_handler_1.default)(async (req, _res, next) => {
9
9
  req.schema = await (0, get_schema_1.getSchema)();
10
10
  return next();
11
11
  });
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const async_handler_1 = __importDefault(require("../utils/async-handler"));
7
- const useCollection = (collection) => (0, async_handler_1.default)(async (req, res, next) => {
7
+ const useCollection = (collection) => (0, async_handler_1.default)(async (req, _res, next) => {
8
8
  req.collection = collection;
9
9
  next();
10
10
  });
@@ -9,7 +9,7 @@ const exceptions_1 = require("../exceptions");
9
9
  const exceptions_2 = require("@directus/shared/exceptions");
10
10
  const async_handler_1 = __importDefault(require("../utils/async-handler"));
11
11
  const sanitize_query_1 = require("../utils/sanitize-query");
12
- const validateBatch = (scope) => (0, async_handler_1.default)(async (req, res, next) => {
12
+ const validateBatch = (scope) => (0, async_handler_1.default)(async (req, _res, next) => {
13
13
  if (req.method.toLowerCase() === 'get') {
14
14
  req.body = {};
15
15
  return next();
@@ -6,10 +6,10 @@ const node_module_1 = require("node:module");
6
6
  exports.default = (0, utils_1.defineOperationApi)({
7
7
  id: 'exec',
8
8
  handler: async ({ code }, { data, env }) => {
9
- const allowedModules = env.FLOWS_EXEC_ALLOWED_MODULES ? (0, utils_1.toArray)(env.FLOWS_EXEC_ALLOWED_MODULES) : [];
9
+ const allowedModules = env['FLOWS_EXEC_ALLOWED_MODULES'] ? (0, utils_1.toArray)(env['FLOWS_EXEC_ALLOWED_MODULES']) : [];
10
10
  const allowedModulesBuiltIn = [];
11
11
  const allowedModulesExternal = [];
12
- const allowedEnv = data.$env ?? {};
12
+ const allowedEnv = data['$env'] ?? {};
13
13
  const opts = {
14
14
  eval: false,
15
15
  wasm: false,
@@ -9,7 +9,7 @@ const rate_limiter_flexible_1 = require("rate-limiter-flexible");
9
9
  const env_1 = __importDefault(require("./env"));
10
10
  const get_config_from_env_1 = require("./utils/get-config-from-env");
11
11
  function createRateLimiter(configPrefix = 'RATE_LIMITER', configOverrides) {
12
- switch (env_1.default.RATE_LIMITER_STORE) {
12
+ switch (env_1.default['RATE_LIMITER_STORE']) {
13
13
  case 'redis':
14
14
  return new rate_limiter_flexible_1.RateLimiterRedis(getConfig('redis', configPrefix, configOverrides));
15
15
  case 'memcache':
@@ -8,10 +8,10 @@ const node_os_1 = __importDefault(require("node:os"));
8
8
  const env_1 = require("../env");
9
9
  const validateIP = async (ip, url) => {
10
10
  const env = (0, env_1.getEnv)();
11
- if (env.IMPORT_IP_DENY_LIST.includes(ip)) {
11
+ if (env['IMPORT_IP_DENY_LIST'].includes(ip)) {
12
12
  throw new Error(`Requested URL "${url}" resolves to a denied IP address`);
13
13
  }
14
- if (env.IMPORT_IP_DENY_LIST.includes('0.0.0.0')) {
14
+ if (env['IMPORT_IP_DENY_LIST'].includes('0.0.0.0')) {
15
15
  const networkInterfaces = node_os_1.default.networkInterfaces();
16
16
  for (const networkInfo of Object.values(networkInterfaces)) {
17
17
  if (!networkInfo)
package/dist/server.js CHANGED
@@ -106,7 +106,7 @@ async function createServer() {
106
106
  (0, terminus_1.createTerminus)(server, terminusOptions);
107
107
  return server;
108
108
  async function beforeShutdown() {
109
- if (env_1.default.NODE_ENV !== 'development') {
109
+ if (env_1.default['NODE_ENV'] !== 'development') {
110
110
  logger_1.default.info('Shutting down...');
111
111
  }
112
112
  }
@@ -121,7 +121,7 @@ async function createServer() {
121
121
  schema: null,
122
122
  accountability: null,
123
123
  });
124
- if (env_1.default.NODE_ENV !== 'development') {
124
+ if (env_1.default['NODE_ENV'] !== 'development') {
125
125
  logger_1.default.info('Directus shut down OK. Bye bye!');
126
126
  }
127
127
  }
@@ -129,8 +129,8 @@ async function createServer() {
129
129
  exports.createServer = createServer;
130
130
  async function startServer() {
131
131
  const server = await createServer();
132
- const host = env_1.default.HOST;
133
- const port = env_1.default.PORT;
132
+ const host = env_1.default['HOST'];
133
+ const port = env_1.default['PORT'];
134
134
  server
135
135
  .listen(port, host, () => {
136
136
  (0, update_check_1.default)(package_json_1.default)
@@ -26,9 +26,9 @@ class ActivityService extends items_1.ItemsService {
26
26
  this.usersService = new users_1.UsersService({ schema: this.schema });
27
27
  }
28
28
  async createOne(data, opts) {
29
- if (data.action === types_1.Action.COMMENT && typeof data.comment === 'string') {
29
+ if (data['action'] === types_1.Action.COMMENT && typeof data['comment'] === 'string') {
30
30
  const usersRegExp = new RegExp(/@[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}/gi);
31
- const mentions = (0, lodash_1.uniq)(data.comment.match(usersRegExp) ?? []);
31
+ const mentions = (0, lodash_1.uniq)(data['comment'].match(usersRegExp) ?? []);
32
32
  const sender = await this.usersService.readOne(this.accountability.user, {
33
33
  fields: ['id', 'first_name', 'last_name', 'email'],
34
34
  });
@@ -39,24 +39,24 @@ class ActivityService extends items_1.ItemsService {
39
39
  });
40
40
  const accountability = {
41
41
  user: userID,
42
- role: user.role?.id ?? null,
43
- admin: user.role?.admin_access ?? null,
44
- app: user.role?.app_access ?? null,
42
+ role: user['role']?.id ?? null,
43
+ admin: user['role']?.admin_access ?? null,
44
+ app: user['role']?.app_access ?? null,
45
45
  };
46
46
  accountability.permissions = await (0, get_permissions_1.getPermissions)(accountability, this.schema);
47
47
  const authorizationService = new authorization_1.AuthorizationService({ schema: this.schema, accountability });
48
48
  const usersService = new users_1.UsersService({ schema: this.schema, accountability });
49
49
  try {
50
- await authorizationService.checkAccess('read', data.collection, data.item);
50
+ await authorizationService.checkAccess('read', data['collection'], data['item']);
51
51
  const templateData = await usersService.readByQuery({
52
52
  fields: ['id', 'first_name', 'last_name', 'email'],
53
53
  filter: { id: { _in: mentions.map((mention) => mention.substring(1)) } },
54
54
  });
55
55
  const userPreviews = templateData.reduce((acc, user) => {
56
- acc[user.id] = `<em>${(0, user_name_1.userName)(user)}</em>`;
56
+ acc[user['id']] = `<em>${(0, user_name_1.userName)(user)}</em>`;
57
57
  return acc;
58
58
  }, {});
59
- let comment = data.comment;
59
+ let comment = data['comment'];
60
60
  for (const mention of mentions) {
61
61
  const uuid = mention.substring(1);
62
62
  // We only match on UUIDs in the first place. This is just an extra sanity check
@@ -72,17 +72,17 @@ ${(0, user_name_1.userName)(sender)} has mentioned you in a comment:
72
72
 
73
73
  ${comment}
74
74
 
75
- <a href="${new url_1.Url(env_1.default.PUBLIC_URL)
76
- .addPath('admin', 'content', data.collection, data.item)
75
+ <a href="${new url_1.Url(env_1.default['PUBLIC_URL'])
76
+ .addPath('admin', 'content', data['collection'], data['item'])
77
77
  .toString()}">Click here to view.</a>
78
78
  `;
79
79
  await this.notificationsService.createOne({
80
80
  recipient: userID,
81
- sender: sender.id,
82
- subject: `You were mentioned in ${data.collection}`,
81
+ sender: sender['id'],
82
+ subject: `You were mentioned in ${data['collection']}`,
83
83
  message,
84
- collection: data.collection,
85
- item: data.item,
84
+ collection: data['collection'],
85
+ item: data['item'],
86
86
  });
87
87
  }
88
88
  catch (err) {
@@ -131,24 +131,24 @@ class AssetsService {
131
131
  const { width, height } = file;
132
132
  if (!width ||
133
133
  !height ||
134
- width > env_1.default.ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION ||
135
- height > env_1.default.ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION) {
134
+ width > env_1.default['ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION'] ||
135
+ height > env_1.default['ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION']) {
136
136
  throw new exceptions_1.IllegalAssetTransformation(`Image is too large to be transformed, or image size couldn't be determined.`);
137
137
  }
138
138
  const { queue, process } = sharp_1.default.counters();
139
- if (queue + process > env_1.default.ASSETS_TRANSFORM_MAX_CONCURRENT) {
139
+ if (queue + process > env_1.default['ASSETS_TRANSFORM_MAX_CONCURRENT']) {
140
140
  throw new service_unavailable_1.ServiceUnavailableException('Server too busy', {
141
141
  service: 'files',
142
142
  });
143
143
  }
144
144
  const readStream = await storage.location(file.storage).read(file.filename_disk, range);
145
145
  const transformer = (0, sharp_1.default)({
146
- limitInputPixels: Math.pow(env_1.default.ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION, 2),
146
+ limitInputPixels: Math.pow(env_1.default['ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION'], 2),
147
147
  sequentialRead: true,
148
- failOn: env_1.default.ASSETS_INVALID_IMAGE_SENSITIVITY_LEVEL,
148
+ failOn: env_1.default['ASSETS_INVALID_IMAGE_SENSITIVITY_LEVEL'],
149
149
  });
150
150
  transformer.timeout({
151
- seconds: (0, lodash_1.clamp)(Math.round((0, get_milliseconds_1.getMilliseconds)(env_1.default.ASSETS_TRANSFORM_TIMEOUT, 0) / 1000), 1, 3600),
151
+ seconds: (0, lodash_1.clamp)(Math.round((0, get_milliseconds_1.getMilliseconds)(env_1.default['ASSETS_TRANSFORM_TIMEOUT'], 0) / 1000), 1, 3600),
152
152
  });
153
153
  if (transforms.find((transform) => transform[0] === 'rotate') === undefined)
154
154
  transformer.rotate();
@@ -40,7 +40,7 @@ class AuthenticationService {
40
40
  */
41
41
  async login(providerName = constants_1.DEFAULT_AUTH_PROVIDER, payload, otp) {
42
42
  const { nanoid } = await import('nanoid');
43
- const STALL_TIME = env_1.default.LOGIN_STALL_TIME;
43
+ const STALL_TIME = env_1.default['LOGIN_STALL_TIME'];
44
44
  const timeStart = perf_hooks_1.performance.now();
45
45
  const provider = (0, auth_1.getAuthProvider)(providerName);
46
46
  let userId;
@@ -150,12 +150,12 @@ class AuthenticationService {
150
150
  schema: this.schema,
151
151
  accountability: this.accountability,
152
152
  });
153
- const accessToken = jsonwebtoken_1.default.sign(customClaims, env_1.default.SECRET, {
154
- expiresIn: env_1.default.ACCESS_TOKEN_TTL,
153
+ const accessToken = jsonwebtoken_1.default.sign(customClaims, env_1.default['SECRET'], {
154
+ expiresIn: env_1.default['ACCESS_TOKEN_TTL'],
155
155
  issuer: 'directus',
156
156
  });
157
157
  const refreshToken = nanoid(64);
158
- const refreshTokenExpiration = new Date(Date.now() + (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL, 0));
158
+ const refreshTokenExpiration = new Date(Date.now() + (0, get_milliseconds_1.getMilliseconds)(env_1.default['REFRESH_TOKEN_TTL'], 0));
159
159
  await this.knex('directus_sessions').insert({
160
160
  token: refreshToken,
161
161
  user: user.id,
@@ -185,7 +185,7 @@ class AuthenticationService {
185
185
  return {
186
186
  accessToken,
187
187
  refreshToken,
188
- expires: (0, get_milliseconds_1.getMilliseconds)(env_1.default.ACCESS_TOKEN_TTL),
188
+ expires: (0, get_milliseconds_1.getMilliseconds)(env_1.default['ACCESS_TOKEN_TTL']),
189
189
  id: user.id,
190
190
  };
191
191
  }
@@ -280,12 +280,12 @@ class AuthenticationService {
280
280
  schema: this.schema,
281
281
  accountability: this.accountability,
282
282
  });
283
- const accessToken = jsonwebtoken_1.default.sign(customClaims, env_1.default.SECRET, {
284
- expiresIn: env_1.default.ACCESS_TOKEN_TTL,
283
+ const accessToken = jsonwebtoken_1.default.sign(customClaims, env_1.default['SECRET'], {
284
+ expiresIn: env_1.default['ACCESS_TOKEN_TTL'],
285
285
  issuer: 'directus',
286
286
  });
287
287
  const newRefreshToken = nanoid(64);
288
- const refreshTokenExpiration = new Date(Date.now() + (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL, 0));
288
+ const refreshTokenExpiration = new Date(Date.now() + (0, get_milliseconds_1.getMilliseconds)(env_1.default['REFRESH_TOKEN_TTL'], 0));
289
289
  await this.knex('directus_sessions')
290
290
  .update({
291
291
  token: newRefreshToken,
@@ -298,7 +298,7 @@ class AuthenticationService {
298
298
  return {
299
299
  accessToken,
300
300
  refreshToken: newRefreshToken,
301
- expires: (0, get_milliseconds_1.getMilliseconds)(env_1.default.ACCESS_TOKEN_TTL),
301
+ expires: (0, get_milliseconds_1.getMilliseconds)(env_1.default['ACCESS_TOKEN_TTL']),
302
302
  id: record.user_id,
303
303
  };
304
304
  }
@@ -157,7 +157,7 @@ class CollectionsService {
157
157
  return payload.collection;
158
158
  }
159
159
  finally {
160
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
160
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
161
161
  await this.cache.clear();
162
162
  }
163
163
  if (opts?.autoPurgeSystemCache !== false) {
@@ -198,7 +198,7 @@ class CollectionsService {
198
198
  return collections;
199
199
  }
200
200
  finally {
201
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
201
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
202
202
  await this.cache.clear();
203
203
  }
204
204
  if (opts?.autoPurgeSystemCache !== false) {
@@ -270,8 +270,8 @@ class CollectionsService {
270
270
  });
271
271
  }
272
272
  }
273
- if (env_1.default.DB_EXCLUDE_TABLES) {
274
- return collections.filter((collection) => env_1.default.DB_EXCLUDE_TABLES.includes(collection.collection) === false);
273
+ if (env_1.default['DB_EXCLUDE_TABLES']) {
274
+ return collections.filter((collection) => env_1.default['DB_EXCLUDE_TABLES'].includes(collection.collection) === false);
275
275
  }
276
276
  return collections;
277
277
  }
@@ -342,7 +342,7 @@ class CollectionsService {
342
342
  return collectionKey;
343
343
  }
344
344
  finally {
345
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
345
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
346
346
  await this.cache.clear();
347
347
  }
348
348
  if (opts?.autoPurgeSystemCache !== false) {
@@ -390,7 +390,7 @@ class CollectionsService {
390
390
  });
391
391
  }
392
392
  finally {
393
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
393
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
394
394
  await this.cache.clear();
395
395
  }
396
396
  if (opts?.autoPurgeSystemCache !== false) {
@@ -432,7 +432,7 @@ class CollectionsService {
432
432
  return collectionKeys;
433
433
  }
434
434
  finally {
435
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
435
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
436
436
  await this.cache.clear();
437
437
  }
438
438
  if (opts?.autoPurgeSystemCache !== false) {
@@ -535,7 +535,7 @@ class CollectionsService {
535
535
  return collectionKey;
536
536
  }
537
537
  finally {
538
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
538
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
539
539
  await this.cache.clear();
540
540
  }
541
541
  if (opts?.autoPurgeSystemCache !== false) {
@@ -576,7 +576,7 @@ class CollectionsService {
576
576
  return collectionKeys;
577
577
  }
578
578
  finally {
579
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
579
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
580
580
  await this.cache.clear();
581
581
  }
582
582
  if (opts?.autoPurgeSystemCache !== false) {
@@ -298,7 +298,7 @@ class FieldsService {
298
298
  if (runPostColumnChange) {
299
299
  await this.helpers.schema.postColumnChange();
300
300
  }
301
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
301
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
302
302
  await this.cache.clear();
303
303
  }
304
304
  if (opts?.autoPurgeSystemCache !== false) {
@@ -393,7 +393,7 @@ class FieldsService {
393
393
  if (runPostColumnChange) {
394
394
  await this.helpers.schema.postColumnChange();
395
395
  }
396
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
396
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
397
397
  await this.cache.clear();
398
398
  }
399
399
  if (opts?.autoPurgeSystemCache !== false) {
@@ -478,10 +478,10 @@ class FieldsService {
478
478
  .first();
479
479
  const collectionMetaUpdates = {};
480
480
  if (collectionMeta?.archive_field === field) {
481
- collectionMetaUpdates.archive_field = null;
481
+ collectionMetaUpdates['archive_field'] = null;
482
482
  }
483
483
  if (collectionMeta?.sort_field === field) {
484
- collectionMetaUpdates.sort_field = null;
484
+ collectionMetaUpdates['sort_field'] = null;
485
485
  }
486
486
  if (Object.keys(collectionMetaUpdates).length > 0) {
487
487
  await trx('directus_collections').update(collectionMetaUpdates).where({ collection });
@@ -523,7 +523,7 @@ class FieldsService {
523
523
  if (runPostColumnChange) {
524
524
  await this.helpers.schema.postColumnChange();
525
525
  }
526
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
526
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
527
527
  await this.cache.clear();
528
528
  }
529
529
  if (opts?.autoPurgeSystemCache !== false) {
@@ -79,12 +79,12 @@ class FilesService extends items_1.ItemsService {
79
79
  if (['image/jpeg', 'image/png', 'image/webp', 'image/gif', 'image/tiff'].includes(payload.type)) {
80
80
  const stream = await storage.location(data.storage).read(payload.filename_disk);
81
81
  const { height, width, description, title, tags, metadata } = await this.getMetadata(stream);
82
- payload.height = height ?? null;
83
- payload.width = width ?? null;
84
- payload.description = description ?? null;
85
- payload.title = title ?? null;
86
- payload.tags = tags ?? null;
87
- payload.metadata = metadata ?? null;
82
+ payload.height ??= height ?? null;
83
+ payload.width ??= width ?? null;
84
+ payload.description ??= description ?? null;
85
+ payload.title ??= title ?? null;
86
+ payload.tags ??= tags ?? null;
87
+ payload.metadata ??= metadata ?? null;
88
88
  }
89
89
  // We do this in a service without accountability. Even if you don't have update permissions to the file,
90
90
  // we still want to be able to set the extracted values from the file on create
@@ -93,7 +93,7 @@ class FilesService extends items_1.ItemsService {
93
93
  schema: this.schema,
94
94
  });
95
95
  await sudoService.updateOne(primaryKey, payload, { emitEvents: false });
96
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
96
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
97
97
  await this.cache.clear();
98
98
  }
99
99
  if (opts?.emitEvents !== false) {
@@ -112,7 +112,7 @@ class FilesService extends items_1.ItemsService {
112
112
  /**
113
113
  * Extract metadata from a buffer's content
114
114
  */
115
- async getMetadata(stream, allowList = env_1.default.FILE_METADATA_ALLOW_LIST) {
115
+ async getMetadata(stream, allowList = env_1.default['FILE_METADATA_ALLOW_LIST']) {
116
116
  return new Promise((resolve, reject) => {
117
117
  (0, promises_1.pipeline)(stream, (0, sharp_1.default)().metadata(async (err, sharpMetadata) => {
118
118
  if (err) {
@@ -176,14 +176,14 @@ class FilesService extends items_1.ItemsService {
176
176
  logger_1.default.warn(err);
177
177
  }
178
178
  }
179
- if (fullMetadata?.iptc?.Caption && typeof fullMetadata.iptc.Caption === 'string') {
180
- metadata.description = fullMetadata.iptc?.Caption;
179
+ if (fullMetadata?.iptc?.['Caption'] && typeof fullMetadata.iptc['Caption'] === 'string') {
180
+ metadata.description = fullMetadata.iptc?.['Caption'];
181
181
  }
182
- if (fullMetadata?.iptc?.Headline && typeof fullMetadata.iptc.Headline === 'string') {
183
- metadata.title = fullMetadata.iptc.Headline;
182
+ if (fullMetadata?.iptc?.['Headline'] && typeof fullMetadata.iptc['Headline'] === 'string') {
183
+ metadata.title = fullMetadata.iptc['Headline'];
184
184
  }
185
- if (fullMetadata?.iptc?.Keywords) {
186
- metadata.tags = fullMetadata.iptc.Keywords;
185
+ if (fullMetadata?.iptc?.['Keywords']) {
186
+ metadata.tags = fullMetadata.iptc['Keywords'];
187
187
  }
188
188
  if (allowList === '*' || allowList?.[0] === '*') {
189
189
  metadata.metadata = fullMetadata;
@@ -229,7 +229,7 @@ class FilesService extends items_1.ItemsService {
229
229
  const filename = decodeURI(path_1.default.basename(parsedURL.pathname));
230
230
  const payload = {
231
231
  filename_download: filename,
232
- storage: (0, utils_1.toArray)(env_1.default.STORAGE_LOCATIONS)[0],
232
+ storage: (0, utils_1.toArray)(env_1.default['STORAGE_LOCATIONS'])[0],
233
233
  type: fileResponse.headers['content-type'],
234
234
  title: (0, format_title_1.default)(filename),
235
235
  ...(body || {}),
@@ -265,13 +265,13 @@ class FilesService extends items_1.ItemsService {
265
265
  }
266
266
  await super.deleteMany(keys);
267
267
  for (const file of files) {
268
- const disk = storage.location(file.storage);
268
+ const disk = storage.location(file['storage']);
269
269
  // Delete file + thumbnails
270
- for await (const filepath of disk.list(file.id)) {
270
+ for await (const filepath of disk.list(file['id'])) {
271
271
  await disk.delete(filepath);
272
272
  }
273
273
  }
274
- if (this.cache && env_1.default.CACHE_AUTO_PURGE && opts?.autoPurgeCache !== false) {
274
+ if (this.cache && env_1.default['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
275
275
  await this.cache.clear();
276
276
  }
277
277
  return keys;