directus 9.6.0 → 9.8.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 (99) hide show
  1. package/dist/app.js +3 -1
  2. package/dist/auth/drivers/oauth2.js +3 -0
  3. package/dist/auth/drivers/openid.js +3 -0
  4. package/dist/cache.d.ts +4 -1
  5. package/dist/cache.js +29 -7
  6. package/dist/cli/commands/schema/apply.d.ts +1 -0
  7. package/dist/cli/commands/schema/apply.js +9 -5
  8. package/dist/cli/index.js +1 -0
  9. package/dist/controllers/assets.js +9 -1
  10. package/dist/controllers/utils.js +18 -1
  11. package/dist/database/helpers/date/dialects/default.d.ts +3 -0
  12. package/dist/database/helpers/date/dialects/default.js +7 -0
  13. package/dist/database/helpers/date/dialects/sqlite.d.ts +0 -9
  14. package/dist/database/helpers/date/dialects/sqlite.js +0 -24
  15. package/dist/database/helpers/date/index.d.ts +6 -6
  16. package/dist/database/helpers/date/index.js +13 -13
  17. package/dist/database/helpers/date/types.d.ts +0 -9
  18. package/dist/database/helpers/{date → fn}/dialects/mssql.d.ts +3 -2
  19. package/dist/database/helpers/{date → fn}/dialects/mssql.js +14 -3
  20. package/dist/database/helpers/{date → fn}/dialects/mysql.d.ts +3 -2
  21. package/dist/database/helpers/{date → fn}/dialects/mysql.js +14 -3
  22. package/dist/database/helpers/{date → fn}/dialects/oracle.d.ts +3 -2
  23. package/dist/database/helpers/{date → fn}/dialects/oracle.js +14 -3
  24. package/dist/database/helpers/{date → fn}/dialects/postgres.d.ts +3 -2
  25. package/dist/database/helpers/{date → fn}/dialects/postgres.js +14 -3
  26. package/dist/database/helpers/fn/dialects/sqlite.d.ts +13 -0
  27. package/dist/database/helpers/fn/dialects/sqlite.js +42 -0
  28. package/dist/database/helpers/fn/index.d.ts +7 -0
  29. package/dist/database/helpers/fn/index.js +17 -0
  30. package/dist/database/helpers/fn/types.d.ts +18 -0
  31. package/dist/database/helpers/fn/types.js +27 -0
  32. package/dist/database/helpers/index.d.ts +4 -1
  33. package/dist/database/helpers/index.js +7 -1
  34. package/dist/database/index.js +0 -3
  35. package/dist/database/migrations/20220308A-add-bookmark-icon-and-color.d.ts +3 -0
  36. package/dist/database/migrations/20220308A-add-bookmark-icon-and-color.js +17 -0
  37. package/dist/database/migrations/20220314A-add-translation-strings.d.ts +3 -0
  38. package/dist/database/migrations/20220314A-add-translation-strings.js +15 -0
  39. package/dist/database/migrations/20220322A-rename-field-typecast-flags.d.ts +3 -0
  40. package/dist/database/migrations/20220322A-rename-field-typecast-flags.js +77 -0
  41. package/dist/database/migrations/20220323A-add-field-validation.d.ts +3 -0
  42. package/dist/database/migrations/20220323A-add-field-validation.js +17 -0
  43. package/dist/database/migrations/20220325A-fix-typecast-flags.d.ts +3 -0
  44. package/dist/database/migrations/20220325A-fix-typecast-flags.js +49 -0
  45. package/dist/database/migrations/20220325B-add-default-language.d.ts +3 -0
  46. package/dist/database/migrations/20220325B-add-default-language.js +28 -0
  47. package/dist/database/migrations/run.js +1 -1
  48. package/dist/database/run-ast.js +11 -3
  49. package/dist/database/system-data/fields/activity.yaml +4 -4
  50. package/dist/database/system-data/fields/collections.yaml +4 -4
  51. package/dist/database/system-data/fields/fields.yaml +17 -8
  52. package/dist/database/system-data/fields/files.yaml +2 -2
  53. package/dist/database/system-data/fields/panels.yaml +2 -2
  54. package/dist/database/system-data/fields/permissions.yaml +4 -4
  55. package/dist/database/system-data/fields/presets.yaml +17 -3
  56. package/dist/database/system-data/fields/relations.yaml +1 -1
  57. package/dist/database/system-data/fields/revisions.yaml +2 -2
  58. package/dist/database/system-data/fields/roles.yaml +4 -4
  59. package/dist/database/system-data/fields/settings.yaml +19 -4
  60. package/dist/database/system-data/fields/users.yaml +2 -2
  61. package/dist/database/system-data/fields/webhooks.yaml +4 -4
  62. package/dist/env.js +6 -2
  63. package/dist/exceptions/database/dialects/mysql.js +23 -17
  64. package/dist/logger.js +2 -1
  65. package/dist/middleware/respond.js +7 -28
  66. package/dist/services/activity.js +4 -1
  67. package/dist/services/authorization.d.ts +1 -1
  68. package/dist/services/authorization.js +156 -14
  69. package/dist/services/collections.js +222 -198
  70. package/dist/services/fields.js +184 -173
  71. package/dist/services/files.js +69 -3
  72. package/dist/services/graphql.js +2 -2
  73. package/dist/services/import-export.d.ts +34 -0
  74. package/dist/services/import-export.js +270 -0
  75. package/dist/services/index.d.ts +2 -1
  76. package/dist/services/index.js +2 -1
  77. package/dist/services/items.js +1 -0
  78. package/dist/services/payload.js +11 -9
  79. package/dist/services/permissions.js +10 -10
  80. package/dist/services/relations.js +93 -78
  81. package/dist/services/server.js +1 -0
  82. package/dist/services/shares.js +2 -1
  83. package/dist/services/users.js +3 -1
  84. package/dist/utils/apply-query.js +21 -3
  85. package/dist/utils/get-column.d.ts +6 -5
  86. package/dist/utils/get-column.js +16 -8
  87. package/dist/utils/get-date-formatted.d.ts +1 -0
  88. package/dist/utils/get-date-formatted.js +14 -0
  89. package/dist/utils/get-local-type.js +2 -2
  90. package/dist/utils/get-permissions.js +1 -1
  91. package/dist/utils/get-schema.d.ts +1 -1
  92. package/dist/utils/get-schema.js +16 -11
  93. package/dist/utils/track.js +3 -2
  94. package/dist/utils/url.d.ts +1 -1
  95. package/dist/utils/url.js +1 -1
  96. package/dist/utils/validate-storage.js +3 -1
  97. package/package.json +13 -12
  98. package/dist/services/import.d.ts +0 -13
  99. package/dist/services/import.js +0 -118
@@ -25,24 +25,24 @@ fields:
25
25
 
26
26
  - field: app_access
27
27
  interface: boolean
28
- special: boolean
28
+ special: cast-boolean
29
29
  width: half
30
30
 
31
31
  - field: admin_access
32
32
  interface: boolean
33
- special: boolean
33
+ special: cast-boolean
34
34
  width: half
35
35
 
36
36
  - field: ip_access
37
37
  interface: tags
38
38
  options:
39
39
  placeholder: $t:field_options.directus_roles.ip_access
40
- special: csv
40
+ special: cast-csv
41
41
  width: full
42
42
 
43
43
  - field: enforce_tfa
44
44
  interface: boolean
45
- special: boolean
45
+ special: cast-boolean
46
46
  width: half
47
47
 
48
48
  - field: users
@@ -32,7 +32,18 @@ fields:
32
32
  translations:
33
33
  language: en-US
34
34
  translations: Website
35
- width: full
35
+ width: half
36
+
37
+ - field: default_language
38
+ interface: system-language
39
+ options:
40
+ iconRight: language
41
+ placeholder: en-US
42
+ includeProjectDefault: false
43
+ translations:
44
+ language: en-US
45
+ translations: Default Language
46
+ width: half
36
47
 
37
48
  - field: branding_divider
38
49
  interface: presentation-divider
@@ -121,7 +132,7 @@ fields:
121
132
 
122
133
  - field: module_bar
123
134
  interface: system-modules
124
- special: json
135
+ special: cast-json
125
136
 
126
137
  - field: security_divider
127
138
  interface: presentation-divider
@@ -297,7 +308,7 @@ fields:
297
308
  ]
298
309
  width: full
299
310
  template: '{{key}}'
300
- special: json
311
+ special: cast-json
301
312
  width: full
302
313
 
303
314
  - field: map_divider
@@ -322,7 +333,7 @@ fields:
322
333
 
323
334
  - field: basemaps
324
335
  interface: list
325
- special: json
336
+ special: cast-json
326
337
  options:
327
338
  template: '{{name}}'
328
339
  fields:
@@ -378,3 +389,7 @@ fields:
378
389
  interface: input
379
390
  options:
380
391
  placeholder: $t:fields.directus_settings.attribution_placeholder
392
+
393
+ - field: translation_strings
394
+ special: cast-json
395
+ hidden: true
@@ -50,7 +50,7 @@ fields:
50
50
 
51
51
  - field: tags
52
52
  interface: tags
53
- special: json
53
+ special: cast-json
54
54
  width: full
55
55
  options:
56
56
  iconRight: local_offer
@@ -93,7 +93,7 @@ fields:
93
93
  - field: email_notifications
94
94
  interface: boolean
95
95
  width: half
96
- special: boolean
96
+ special: cast-boolean
97
97
 
98
98
  - field: admin_divider
99
99
  interface: presentation-divider
@@ -60,12 +60,12 @@ fields:
60
60
  interface: boolean
61
61
  options:
62
62
  label: $t:fields.directus_webhooks.data_label
63
- special: boolean
63
+ special: cast-boolean
64
64
  width: half
65
65
  display: boolean
66
66
 
67
67
  - field: headers
68
- special: json
68
+ special: cast-json
69
69
  interface: list
70
70
  options:
71
71
  template: '{{ header }}: {{ value }}'
@@ -105,7 +105,7 @@ fields:
105
105
  value: update
106
106
  - text: $t:delete_label
107
107
  value: delete
108
- special: csv
108
+ special: cast-csv
109
109
  width: full
110
110
  display: labels
111
111
  display_options:
@@ -129,7 +129,7 @@ fields:
129
129
 
130
130
  - field: collections
131
131
  interface: system-collections
132
- special: csv
132
+ special: cast-csv
133
133
  width: full
134
134
  display: labels
135
135
  display_options:
package/dist/env.js CHANGED
@@ -35,8 +35,8 @@ const defaults = {
35
35
  REFRESH_TOKEN_COOKIE_SAME_SITE: 'lax',
36
36
  REFRESH_TOKEN_COOKIE_NAME: 'directus_refresh_token',
37
37
  ROOT_REDIRECT: './admin',
38
- CORS_ENABLED: true,
39
- CORS_ORIGIN: true,
38
+ CORS_ENABLED: false,
39
+ CORS_ORIGIN: false,
40
40
  CORS_METHODS: 'GET,POST,PATCH,DELETE',
41
41
  CORS_ALLOWED_HEADERS: 'Content-Type,Authorization',
42
42
  CORS_EXPOSED_HEADERS: 'Content-Range',
@@ -65,8 +65,10 @@ const defaults = {
65
65
  ASSETS_TRANSFORM_MAX_OPERATIONS: 5,
66
66
  IP_TRUST_PROXY: true,
67
67
  IP_CUSTOM_HEADER: false,
68
+ IMPORT_IP_DENY_LIST: '0.0.0.0',
68
69
  SERVE_APP: true,
69
70
  RELATIONAL_BATCH_SIZE: 25000,
71
+ EXPORT_BATCH_SIZE: 5000,
70
72
  };
71
73
  // Allows us to force certain environment variable into a type, instead of relying
72
74
  // on the auto-parsed type in processValues. ref #3705
@@ -79,6 +81,7 @@ const typeMap = {
79
81
  DB_DATABASE: 'string',
80
82
  DB_PORT: 'number',
81
83
  DB_EXCLUDE_TABLES: 'array',
84
+ IMPORT_IP_DENY_LIST: 'array',
82
85
  };
83
86
  let env = {
84
87
  ...defaults,
@@ -232,6 +235,7 @@ function processValues(env) {
232
235
  }
233
236
  if (String(value).includes(',')) {
234
237
  env[key] = (0, utils_1.toArray)(value);
238
+ continue;
235
239
  }
236
240
  // Try converting the value to a JS object. This allows JSON objects to be passed for nested
237
241
  // config flags, or custom param names (that aren't camelCased)
@@ -38,6 +38,7 @@ function extractError(error) {
38
38
  }
39
39
  exports.extractError = extractError;
40
40
  function uniqueViolation(error) {
41
+ var _a, _b, _c, _d, _e;
41
42
  const betweenQuotes = /'([^']+)'/g;
42
43
  const matches = error.sqlMessage.match(betweenQuotes);
43
44
  if (!matches)
@@ -49,13 +50,13 @@ function uniqueViolation(error) {
49
50
  */
50
51
  /** MySQL 8+ style error message */
51
52
  if (matches[1].includes('.')) {
52
- const collection = matches[1].slice(1, -1).split('.')[0];
53
+ const collection = (_a = matches[1]) === null || _a === void 0 ? void 0 : _a.slice(1, -1).split('.')[0];
53
54
  let field = null;
54
- const indexName = matches[1].slice(1, -1).split('.')[1];
55
+ const indexName = (_b = matches[1]) === null || _b === void 0 ? void 0 : _b.slice(1, -1).split('.')[1];
55
56
  if ((indexName === null || indexName === void 0 ? void 0 : indexName.startsWith(`${collection}_`)) && indexName.endsWith('_unique')) {
56
- field = indexName.slice(collection.length + 1, -7);
57
+ field = indexName === null || indexName === void 0 ? void 0 : indexName.slice(collection.length + 1, -7);
57
58
  }
58
- const invalid = matches[0].slice(1, -1);
59
+ const invalid = (_c = matches[0]) === null || _c === void 0 ? void 0 : _c.slice(1, -1);
59
60
  return new record_not_unique_1.RecordNotUniqueException(field, {
60
61
  collection,
61
62
  field,
@@ -64,13 +65,13 @@ function uniqueViolation(error) {
64
65
  }
65
66
  else {
66
67
  /** MySQL 5.7 style error message */
67
- const indexName = matches[1].slice(1, -1);
68
+ const indexName = (_d = matches[1]) === null || _d === void 0 ? void 0 : _d.slice(1, -1);
68
69
  const collection = indexName.split('_')[0];
69
70
  let field = null;
70
71
  if ((indexName === null || indexName === void 0 ? void 0 : indexName.startsWith(`${collection}_`)) && indexName.endsWith('_unique')) {
71
- field = indexName.slice(collection.length + 1, -7);
72
+ field = indexName === null || indexName === void 0 ? void 0 : indexName.slice(collection.length + 1, -7);
72
73
  }
73
- const invalid = matches[0].slice(1, -1);
74
+ const invalid = (_e = matches[0]) === null || _e === void 0 ? void 0 : _e.slice(1, -1);
74
75
  return new record_not_unique_1.RecordNotUniqueException(field, {
75
76
  collection,
76
77
  field,
@@ -79,57 +80,61 @@ function uniqueViolation(error) {
79
80
  }
80
81
  }
81
82
  function numericValueOutOfRange(error) {
83
+ var _a, _b;
82
84
  const betweenTicks = /`([^`]+)`/g;
83
85
  const betweenQuotes = /'([^']+)'/g;
84
86
  const tickMatches = error.sql.match(betweenTicks);
85
87
  const quoteMatches = error.sqlMessage.match(betweenQuotes);
86
88
  if (!tickMatches || !quoteMatches)
87
89
  return error;
88
- const collection = tickMatches[0].slice(1, -1);
89
- const field = quoteMatches[0].slice(1, -1);
90
+ const collection = (_a = tickMatches[0]) === null || _a === void 0 ? void 0 : _a.slice(1, -1);
91
+ const field = (_b = quoteMatches[0]) === null || _b === void 0 ? void 0 : _b.slice(1, -1);
90
92
  return new value_out_of_range_1.ValueOutOfRangeException(field, {
91
93
  collection,
92
94
  field,
93
95
  });
94
96
  }
95
97
  function valueLimitViolation(error) {
98
+ var _a, _b;
96
99
  const betweenTicks = /`([^`]+)`/g;
97
100
  const betweenQuotes = /'([^']+)'/g;
98
101
  const tickMatches = error.sql.match(betweenTicks);
99
102
  const quoteMatches = error.sqlMessage.match(betweenQuotes);
100
103
  if (!tickMatches || !quoteMatches)
101
104
  return error;
102
- const collection = tickMatches[0].slice(1, -1);
103
- const field = quoteMatches[0].slice(1, -1);
105
+ const collection = (_a = tickMatches[0]) === null || _a === void 0 ? void 0 : _a.slice(1, -1);
106
+ const field = (_b = quoteMatches[0]) === null || _b === void 0 ? void 0 : _b.slice(1, -1);
104
107
  return new value_too_long_1.ValueTooLongException(field, {
105
108
  collection,
106
109
  field,
107
110
  });
108
111
  }
109
112
  function notNullViolation(error) {
113
+ var _a, _b;
110
114
  const betweenTicks = /`([^`]+)`/g;
111
115
  const betweenQuotes = /'([^']+)'/g;
112
116
  const tickMatches = error.sql.match(betweenTicks);
113
117
  const quoteMatches = error.sqlMessage.match(betweenQuotes);
114
118
  if (!tickMatches || !quoteMatches)
115
119
  return error;
116
- const collection = tickMatches[0].slice(1, -1);
117
- const field = quoteMatches[0].slice(1, -1);
120
+ const collection = (_a = tickMatches[0]) === null || _a === void 0 ? void 0 : _a.slice(1, -1);
121
+ const field = (_b = quoteMatches[0]) === null || _b === void 0 ? void 0 : _b.slice(1, -1);
118
122
  return new not_null_violation_1.NotNullViolationException(field, {
119
123
  collection,
120
124
  field,
121
125
  });
122
126
  }
123
127
  function foreignKeyViolation(error) {
128
+ var _a, _b, _c;
124
129
  const betweenTicks = /`([^`]+)`/g;
125
130
  const betweenParens = /\(([^)]+)\)/g;
126
131
  const tickMatches = error.sqlMessage.match(betweenTicks);
127
132
  const parenMatches = error.sql.match(betweenParens);
128
133
  if (!tickMatches || !parenMatches)
129
134
  return error;
130
- const collection = tickMatches[1].slice(1, -1);
131
- const field = tickMatches[3].slice(1, -1);
132
- const invalid = parenMatches[1].slice(1, -1);
135
+ const collection = (_a = tickMatches[1]) === null || _a === void 0 ? void 0 : _a.slice(1, -1);
136
+ const field = (_b = tickMatches[3]) === null || _b === void 0 ? void 0 : _b.slice(1, -1);
137
+ const invalid = (_c = parenMatches[1]) === null || _c === void 0 ? void 0 : _c.slice(1, -1);
133
138
  return new invalid_foreign_key_1.InvalidForeignKeyException(field, {
134
139
  collection,
135
140
  field,
@@ -137,12 +142,13 @@ function foreignKeyViolation(error) {
137
142
  });
138
143
  }
139
144
  function containsNullValues(error) {
145
+ var _a;
140
146
  const betweenTicks = /`([^`]+)`/g;
141
147
  // Normally, we shouldn't read from the executed SQL. In this case, we're altering a single
142
148
  // column, so we shouldn't have the problem where multiple columns are altered at the same time
143
149
  const tickMatches = error.sql.match(betweenTicks);
144
150
  if (!tickMatches)
145
151
  return error;
146
- const field = tickMatches[1].slice(1, -1);
152
+ const field = (_a = tickMatches[1]) === null || _a === void 0 ? void 0 : _a.slice(1, -1);
147
153
  return new contains_null_values_1.ContainsNullValuesException(field);
148
154
  }
package/dist/logger.js CHANGED
@@ -28,6 +28,7 @@ const pino_http_1 = __importStar(require("pino-http"));
28
28
  const get_config_from_env_1 = require("./utils/get-config-from-env");
29
29
  const url_1 = require("url");
30
30
  const env_1 = __importDefault(require("./env"));
31
+ const utils_1 = require("@directus/shared/utils");
31
32
  const pinoOptions = {
32
33
  level: env_1.default.LOG_LEVEL || 'info',
33
34
  redact: {
@@ -43,7 +44,7 @@ const loggerEnvConfig = (0, get_config_from_env_1.getConfigFromEnv)('LOGGER_', '
43
44
  // Expose custom log levels into formatter function
44
45
  if (loggerEnvConfig.levels) {
45
46
  const customLogLevels = {};
46
- for (const el of loggerEnvConfig.levels.split(',')) {
47
+ for (const el of (0, utils_1.toArray)(loggerEnvConfig.levels)) {
47
48
  const key_val = el.split(':');
48
49
  customLogLevels[key_val[0].trim()] = key_val[1].trim();
49
50
  }
@@ -4,16 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.respond = void 0;
7
- const json2csv_1 = require("json2csv");
8
7
  const ms_1 = __importDefault(require("ms"));
9
- const stream_1 = require("stream");
10
8
  const cache_1 = require("../cache");
11
9
  const env_1 = __importDefault(require("../env"));
12
10
  const async_handler_1 = __importDefault(require("../utils/async-handler"));
13
11
  const get_cache_key_1 = require("../utils/get-cache-key");
14
- const js2xmlparser_1 = require("js2xmlparser");
15
12
  const get_cache_headers_1 = require("../utils/get-cache-headers");
16
13
  const logger_1 = __importDefault(require("../logger"));
14
+ const services_1 = require("../services");
15
+ const get_date_formatted_1 = require("../utils/get-date-formatted");
17
16
  exports.respond = (0, async_handler_1.default)(async (req, res) => {
18
17
  var _a, _b, _c;
19
18
  const { cache } = (0, cache_1.getCache)();
@@ -39,6 +38,7 @@ exports.respond = (0, async_handler_1.default)(async (req, res) => {
39
38
  res.setHeader('Vary', 'Origin, Cache-Control');
40
39
  }
41
40
  if (req.sanitizedQuery.export) {
41
+ const exportService = new services_1.ExportService({ accountability: req.accountability, schema: req.schema });
42
42
  let filename = '';
43
43
  if (req.collection) {
44
44
  filename += req.collection;
@@ -46,32 +46,21 @@ exports.respond = (0, async_handler_1.default)(async (req, res) => {
46
46
  else {
47
47
  filename += 'Export';
48
48
  }
49
- filename += ' ' + getDateFormatted();
49
+ filename += ' ' + (0, get_date_formatted_1.getDateFormatted)();
50
50
  if (req.sanitizedQuery.export === 'json') {
51
51
  res.attachment(`${filename}.json`);
52
52
  res.set('Content-Type', 'application/json');
53
- return res.status(200).send(JSON.stringify(((_a = res.locals.payload) === null || _a === void 0 ? void 0 : _a.data) || null, null, '\t'));
53
+ return res.status(200).send(exportService.transform((_a = res.locals.payload) === null || _a === void 0 ? void 0 : _a.data, 'json'));
54
54
  }
55
55
  if (req.sanitizedQuery.export === 'xml') {
56
56
  res.attachment(`${filename}.xml`);
57
57
  res.set('Content-Type', 'text/xml');
58
- return res.status(200).send((0, js2xmlparser_1.parse)('data', (_b = res.locals.payload) === null || _b === void 0 ? void 0 : _b.data));
58
+ return res.status(200).send(exportService.transform((_b = res.locals.payload) === null || _b === void 0 ? void 0 : _b.data, 'xml'));
59
59
  }
60
60
  if (req.sanitizedQuery.export === 'csv') {
61
61
  res.attachment(`${filename}.csv`);
62
62
  res.set('Content-Type', 'text/csv');
63
- const stream = new stream_1.PassThrough();
64
- if (!((_c = res.locals.payload) === null || _c === void 0 ? void 0 : _c.data) || res.locals.payload.data.length === 0) {
65
- stream.end(Buffer.from(''));
66
- return stream.pipe(res);
67
- }
68
- else {
69
- stream.end(Buffer.from(JSON.stringify(res.locals.payload.data), 'utf-8'));
70
- const json2csv = new json2csv_1.Transform({
71
- transforms: [json2csv_1.transforms.flatten({ separator: '.' })],
72
- });
73
- return stream.pipe(json2csv).pipe(res);
74
- }
63
+ return res.status(200).send(exportService.transform((_c = res.locals.payload) === null || _c === void 0 ? void 0 : _c.data, 'csv'));
75
64
  }
76
65
  }
77
66
  if (Buffer.isBuffer(res.locals.payload)) {
@@ -84,13 +73,3 @@ exports.respond = (0, async_handler_1.default)(async (req, res) => {
84
73
  return res.status(204).end();
85
74
  }
86
75
  });
87
- function getDateFormatted() {
88
- const date = new Date();
89
- let month = String(date.getMonth() + 1);
90
- if (month.length === 1)
91
- month = '0' + month;
92
- let day = String(date.getDate());
93
- if (day.length === 1)
94
- day = '0' + day;
95
- return `${date.getFullYear()}-${month}-${day} at ${date.getHours()}.${date.getMinutes()}.${date.getSeconds()}`;
96
- }
@@ -16,6 +16,7 @@ const user_name_1 = require("../utils/user-name");
16
16
  const lodash_1 = require("lodash");
17
17
  const env_1 = __importDefault(require("../env"));
18
18
  const uuid_validate_1 = __importDefault(require("uuid-validate"));
19
+ const url_1 = require("../utils/url");
19
20
  class ActivityService extends items_1.ItemsService {
20
21
  constructor(options) {
21
22
  super('directus_activity', options);
@@ -70,7 +71,9 @@ ${(0, user_name_1.userName)(sender)} has mentioned you in a comment:
70
71
 
71
72
  ${comment}
72
73
 
73
- <a href="${env_1.default.PUBLIC_URL}/admin/content/${data.collection}/${data.item}">Click here to view.</a>
74
+ <a href="${new url_1.Url(env_1.default.PUBLIC_URL)
75
+ .addPath('admin', 'content', data.collection, data.item)
76
+ .toString()}">Click here to view.</a>
74
77
  `;
75
78
  await this.notificationsService.createOne({
76
79
  recipient: userID,
@@ -1,6 +1,6 @@
1
+ import { Accountability, PermissionsAction, SchemaOverview } from '@directus/shared/types';
1
2
  import { Knex } from 'knex';
2
3
  import { AbstractServiceOptions, AST, Item, PrimaryKey } from '../types';
3
- import { PermissionsAction, Accountability, SchemaOverview } from '@directus/shared/types';
4
4
  import { PayloadService } from './payload';
5
5
  export declare class AuthorizationService {
6
6
  knex: Knex;