directus 9.1.2 → 9.2.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 (78) hide show
  1. package/dist/auth.js +5 -3
  2. package/dist/cli/commands/database/install.js +2 -4
  3. package/dist/cli/commands/schema/apply.js +26 -10
  4. package/dist/controllers/assets.js +0 -27
  5. package/dist/controllers/auth.js +7 -2
  6. package/dist/controllers/extensions.js +1 -1
  7. package/dist/database/{functions/types.d.ts → helpers/date/dialects/mssql.d.ts} +2 -1
  8. package/dist/database/{functions → helpers/date}/dialects/mssql.js +4 -6
  9. package/dist/database/{functions → helpers/date}/dialects/mysql.d.ts +2 -4
  10. package/dist/database/{functions → helpers/date}/dialects/mysql.js +4 -6
  11. package/dist/database/{functions/dialects/mssql.d.ts → helpers/date/dialects/oracle.d.ts} +2 -4
  12. package/dist/database/{functions → helpers/date}/dialects/oracle.js +4 -6
  13. package/dist/database/helpers/date/dialects/postgres.d.ts +12 -0
  14. package/dist/database/{functions → helpers/date}/dialects/postgres.js +4 -6
  15. package/dist/database/{functions → helpers/date}/dialects/sqlite.d.ts +3 -4
  16. package/dist/database/helpers/date/dialects/sqlite.js +35 -0
  17. package/dist/database/helpers/date/index.d.ts +6 -0
  18. package/dist/database/helpers/date/index.js +15 -0
  19. package/dist/database/helpers/date/types.d.ts +13 -0
  20. package/dist/database/helpers/date/types.js +10 -0
  21. package/dist/database/helpers/geometry/dialects/mssql.d.ts +14 -0
  22. package/dist/database/helpers/geometry/dialects/mssql.js +36 -0
  23. package/dist/database/helpers/geometry/dialects/mysql.d.ts +7 -0
  24. package/dist/database/helpers/geometry/dialects/mysql.js +16 -0
  25. package/dist/database/helpers/geometry/dialects/oracle.d.ts +15 -0
  26. package/dist/database/helpers/geometry/dialects/oracle.js +39 -0
  27. package/dist/database/helpers/geometry/dialects/postgres.d.ts +10 -0
  28. package/dist/database/helpers/geometry/dialects/postgres.js +23 -0
  29. package/dist/database/helpers/geometry/dialects/redshift.d.ts +7 -0
  30. package/dist/database/helpers/geometry/dialects/redshift.js +16 -0
  31. package/dist/database/helpers/geometry/dialects/sqlite.d.ts +6 -0
  32. package/dist/database/helpers/geometry/dialects/sqlite.js +14 -0
  33. package/dist/database/helpers/geometry/index.d.ts +6 -0
  34. package/dist/database/helpers/geometry/index.js +15 -0
  35. package/dist/database/helpers/{geometry.d.ts → geometry/types.d.ts} +3 -7
  36. package/dist/database/helpers/geometry/types.js +54 -0
  37. package/dist/database/helpers/index.d.ts +8 -0
  38. package/dist/database/helpers/index.js +33 -0
  39. package/dist/database/helpers/types.d.ts +5 -0
  40. package/dist/database/helpers/types.js +9 -0
  41. package/dist/database/index.js +6 -6
  42. package/dist/database/run-ast.js +5 -5
  43. package/dist/database/seeds/run.js +3 -3
  44. package/dist/database/system-data/fields/notifications.yaml +1 -0
  45. package/dist/env.js +1 -0
  46. package/dist/extensions.js +17 -2
  47. package/dist/middleware/sanitize-query.js +1 -1
  48. package/dist/services/activity.js +7 -2
  49. package/dist/services/assets.js +14 -0
  50. package/dist/services/fields.d.ts +2 -0
  51. package/dist/services/fields.js +57 -26
  52. package/dist/services/files.d.ts +1 -1
  53. package/dist/services/files.js +13 -11
  54. package/dist/services/graphql.js +3 -0
  55. package/dist/services/items.js +18 -29
  56. package/dist/services/payload.d.ts +2 -0
  57. package/dist/services/payload.js +3 -3
  58. package/dist/utils/apply-query.js +9 -11
  59. package/dist/utils/apply-snapshot.js +27 -28
  60. package/dist/utils/get-column.js +2 -2
  61. package/dist/utils/get-default-index-name.js +2 -2
  62. package/dist/utils/get-local-type.js +1 -12
  63. package/dist/utils/merge-permissions.js +2 -2
  64. package/dist/utils/sanitize-query.js +1 -12
  65. package/dist/utils/validate-query.js +1 -1
  66. package/dist/webhooks.js +16 -24
  67. package/package.json +13 -13
  68. package/dist/database/functions/dialects/oracle.d.ts +0 -14
  69. package/dist/database/functions/dialects/postgres.d.ts +0 -14
  70. package/dist/database/functions/dialects/sqlite.js +0 -33
  71. package/dist/database/functions/index.d.ts +0 -3
  72. package/dist/database/functions/index.js +0 -26
  73. package/dist/database/functions/types.js +0 -2
  74. package/dist/database/helpers/date.d.ts +0 -8
  75. package/dist/database/helpers/date.js +0 -44
  76. package/dist/database/helpers/geometry.js +0 -189
  77. package/dist/utils/get-simple-hash.d.ts +0 -5
  78. package/dist/utils/get-simple-hash.js +0 -15
@@ -213,8 +213,16 @@ class ItemsService {
213
213
  if (records === null) {
214
214
  throw new exceptions_1.ForbiddenException();
215
215
  }
216
+ const filteredRecords = await emitter_1.default.emitFilter(`${this.eventScope}.read`, records, {
217
+ query,
218
+ collection: this.collection,
219
+ }, {
220
+ database: this.knex,
221
+ schema: this.schema,
222
+ accountability: this.accountability,
223
+ });
216
224
  emitter_1.default.emitAction(`${this.eventScope}.read`, {
217
- payload: records,
225
+ payload: filteredRecords,
218
226
  query,
219
227
  collection: this.collection,
220
228
  }, {
@@ -222,23 +230,15 @@ class ItemsService {
222
230
  schema: this.schema,
223
231
  accountability: this.accountability,
224
232
  });
225
- return records;
233
+ return filteredRecords;
226
234
  }
227
235
  /**
228
236
  * Get single item by primary key
229
237
  */
230
- async readOne(key, query, opts) {
231
- query = query !== null && query !== void 0 ? query : {};
238
+ async readOne(key, query = {}, opts) {
232
239
  const primaryKeyField = this.schema.collections[this.collection].primary;
233
- const queryWithKey = {
234
- ...query,
235
- filter: {
236
- ...(query.filter || {}),
237
- [primaryKeyField]: {
238
- _eq: key,
239
- },
240
- },
241
- };
240
+ const filterWithKey = (0, lodash_1.assign)({}, query.filter, { [primaryKeyField]: { _eq: key } });
241
+ const queryWithKey = (0, lodash_1.assign)({}, query, { filter: filterWithKey });
242
242
  const results = await this.readByQuery(queryWithKey, opts);
243
243
  if (results.length === 0) {
244
244
  throw new exceptions_1.ForbiddenException();
@@ -248,23 +248,12 @@ class ItemsService {
248
248
  /**
249
249
  * Get multiple items by primary keys
250
250
  */
251
- async readMany(keys, query, opts) {
252
- query = query !== null && query !== void 0 ? query : {};
251
+ async readMany(keys, query = {}, opts) {
252
+ var _a;
253
253
  const primaryKeyField = this.schema.collections[this.collection].primary;
254
- const queryWithKeys = {
255
- ...query,
256
- filter: {
257
- _and: [
258
- query.filter || {},
259
- {
260
- [primaryKeyField]: {
261
- _in: keys,
262
- },
263
- },
264
- ],
265
- },
266
- };
267
- const results = await this.readByQuery(queryWithKeys, opts);
254
+ const filterWithKey = { _and: [{ [primaryKeyField]: { _in: keys } }, (_a = query.filter) !== null && _a !== void 0 ? _a : {}] };
255
+ const queryWithKey = (0, lodash_1.assign)({}, query, { filter: filterWithKey });
256
+ const results = await this.readByQuery(queryWithKey, opts);
268
257
  return results;
269
258
  }
270
259
  /**
@@ -1,6 +1,7 @@
1
1
  import { Knex } from 'knex';
2
2
  import { AbstractServiceOptions, Item, PrimaryKey, SchemaOverview } from '../types';
3
3
  import { Accountability } from '@directus/shared/types';
4
+ import { Helpers } from '../database/helpers';
4
5
  declare type Action = 'create' | 'read' | 'update';
5
6
  declare type Transformers = {
6
7
  [type: string]: (context: {
@@ -18,6 +19,7 @@ declare type Transformers = {
18
19
  export declare class PayloadService {
19
20
  accountability: Accountability | null;
20
21
  knex: Knex;
22
+ helpers: Helpers;
21
23
  collection: string;
22
24
  schema: SchemaOverview;
23
25
  constructor(collection: string, options: AbstractServiceOptions);
@@ -13,7 +13,7 @@ const exceptions_1 = require("../exceptions");
13
13
  const utils_1 = require("@directus/shared/utils");
14
14
  const items_1 = require("./items");
15
15
  const flat_1 = require("flat");
16
- const geometry_1 = require("../database/helpers/geometry");
16
+ const helpers_1 = require("../database/helpers");
17
17
  const wellknown_1 = require("wellknown");
18
18
  const generate_hash_1 = require("../utils/generate-hash");
19
19
  /**
@@ -111,6 +111,7 @@ class PayloadService {
111
111
  };
112
112
  this.accountability = options.accountability || null;
113
113
  this.knex = options.knex || (0, database_1.default)();
114
+ this.helpers = (0, helpers_1.getHelpers)(this.knex);
114
115
  this.collection = collection;
115
116
  this.schema = options.schema;
116
117
  return this;
@@ -188,10 +189,9 @@ class PayloadService {
188
189
  * to check if the value is a raw instance before stringifying it in the next step.
189
190
  */
190
191
  processGeometries(payloads, action) {
191
- const helper = (0, geometry_1.getGeometryHelper)();
192
192
  const process = action == 'read'
193
193
  ? (value) => (typeof value === 'string' ? (0, wellknown_1.parse)(value) : value)
194
- : (value) => helper.fromGeoJSON(typeof value == 'string' ? JSON.parse(value) : value);
194
+ : (value) => this.helpers.st.fromGeoJSON(typeof value == 'string' ? JSON.parse(value) : value);
195
195
  const fieldsInCollection = Object.entries(this.schema.collections[this.collection].fields);
196
196
  const geometryColumns = fieldsInCollection.filter(([_, field]) => field.type.startsWith('geometry'));
197
197
  for (const [name] of geometryColumns) {
@@ -11,8 +11,7 @@ const exceptions_1 = require("../exceptions");
11
11
  const apply_function_to_column_name_1 = require("./apply-function-to-column-name");
12
12
  const get_column_1 = require("./get-column");
13
13
  const get_relation_type_1 = require("./get-relation-type");
14
- const geometry_1 = require("../database/helpers/geometry");
15
- const date_1 = require("../database/helpers/date");
14
+ const helpers_1 = require("../database/helpers");
16
15
  const generateAlias = (0, nanoid_1.customAlphabet)('abcdefghijklmnopqrstuvwxyz', 5);
17
16
  /**
18
17
  * Apply the Query to a given Knex query builder instance
@@ -45,7 +44,7 @@ function applyQuery(knex, collection, dbQuery, query, schema, subQuery = false)
45
44
  applySearch(schema, dbQuery, query.search, collection);
46
45
  }
47
46
  if (query.group) {
48
- dbQuery.groupBy(query.group.map(apply_function_to_column_name_1.applyFunctionToColumnName));
47
+ dbQuery.groupBy(`${collection}.${query.group.map(apply_function_to_column_name_1.applyFunctionToColumnName)}`);
49
48
  }
50
49
  if (query.aggregate) {
51
50
  applyAggregate(dbQuery, query.aggregate, collection);
@@ -117,6 +116,7 @@ exports.default = applyQuery;
117
116
  * ```
118
117
  */
119
118
  function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery = false) {
119
+ const helpers = (0, helpers_1.getHelpers)(knex);
120
120
  const relations = schema.relations;
121
121
  const aliasMap = {};
122
122
  addJoins(rootQuery, rootFilter, collection);
@@ -273,16 +273,15 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
273
273
  query.where(key, '!=', '');
274
274
  });
275
275
  }
276
- const dateHelper = (0, date_1.getDateHelper)();
277
276
  const [collection, field] = key.split('.');
278
277
  if (collection in schema.collections && field in schema.collections[collection].fields) {
279
278
  const type = schema.collections[collection].fields[field].type;
280
279
  if (['date', 'dateTime', 'time', 'timestamp'].includes(type)) {
281
280
  if (Array.isArray(compareValue)) {
282
- compareValue = compareValue.map((val) => dateHelper.parseDate(val));
281
+ compareValue = compareValue.map((val) => helpers.date.parse(val));
283
282
  }
284
283
  else {
285
- compareValue = dateHelper.parseDate(compareValue);
284
+ compareValue = helpers.date.parse(compareValue);
286
285
  }
287
286
  }
288
287
  }
@@ -361,18 +360,17 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
361
360
  value = value.split(',');
362
361
  dbQuery[logical].whereNotBetween(selectionRaw, value);
363
362
  }
364
- const geometryHelper = (0, geometry_1.getGeometryHelper)();
365
363
  if (operator == '_intersects') {
366
- dbQuery[logical].whereRaw(geometryHelper.intersects(key, compareValue));
364
+ dbQuery[logical].whereRaw(helpers.st.intersects(key, compareValue));
367
365
  }
368
366
  if (operator == '_nintersects') {
369
- dbQuery[logical].whereRaw(geometryHelper.nintersects(key, compareValue));
367
+ dbQuery[logical].whereRaw(helpers.st.nintersects(key, compareValue));
370
368
  }
371
369
  if (operator == '_intersects_bbox') {
372
- dbQuery[logical].whereRaw(geometryHelper.intersects_bbox(key, compareValue));
370
+ dbQuery[logical].whereRaw(helpers.st.intersects_bbox(key, compareValue));
373
371
  }
374
372
  if (operator == '_nintersects_bbox') {
375
- dbQuery[logical].whereRaw(geometryHelper.nintersects_bbox(key, compareValue));
373
+ dbQuery[logical].whereRaw(helpers.st.nintersects_bbox(key, compareValue));
376
374
  }
377
375
  }
378
376
  function getWhereColumn(path, collection) {
@@ -36,14 +36,13 @@ async function applySnapshot(snapshot, options) {
36
36
  // edits
37
37
  snapshotDiff.fields = snapshotDiff.fields.filter((fieldDiff) => fieldDiff.collection !== collection);
38
38
  }
39
- if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E') {
40
- const updates = diff.reduce((acc, edit) => {
41
- if (edit.kind !== 'E')
42
- return acc;
43
- (0, lodash_1.set)(acc, edit.path, edit.rhs);
44
- return acc;
45
- }, {});
46
- await collectionsService.updateOne(collection, updates);
39
+ if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A') {
40
+ const newValues = snapshot.collections.find((field) => {
41
+ return field.collection === collection;
42
+ });
43
+ if (newValues) {
44
+ await collectionsService.updateOne(collection, newValues);
45
+ }
47
46
  }
48
47
  }
49
48
  const fieldsService = new services_1.FieldsService({ knex: trx, schema: await (0, get_schema_1.getSchema)({ database: trx }) });
@@ -51,18 +50,15 @@ async function applySnapshot(snapshot, options) {
51
50
  if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N') {
52
51
  await fieldsService.createField(collection, diff[0].rhs);
53
52
  }
54
- if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E') {
55
- const updates = diff.reduce((acc, edit) => {
56
- if (edit.kind !== 'E')
57
- return acc;
58
- (0, lodash_1.set)(acc, edit.path, edit.rhs);
59
- return acc;
60
- }, {});
61
- await fieldsService.updateField(collection, {
62
- field,
63
- type: 'unknown',
64
- ...updates,
53
+ if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A') {
54
+ const newValues = snapshot.fields.find((snapshotField) => {
55
+ return snapshotField.collection === collection && snapshotField.field === field;
65
56
  });
57
+ if (newValues) {
58
+ await fieldsService.updateField(collection, {
59
+ ...newValues,
60
+ });
61
+ }
66
62
  }
67
63
  if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D') {
68
64
  await fieldsService.deleteField(collection, field);
@@ -72,18 +68,21 @@ async function applySnapshot(snapshot, options) {
72
68
  }
73
69
  }
74
70
  const relationsService = new services_1.RelationsService({ knex: trx, schema: await (0, get_schema_1.getSchema)({ database: trx }) });
75
- for (const { collection, field, diff, related_collection } of snapshotDiff.relations) {
71
+ for (const { collection, field, diff } of snapshotDiff.relations) {
72
+ const structure = {};
73
+ for (const diffEdit of diff) {
74
+ (0, lodash_1.set)(structure, diffEdit.path, undefined);
75
+ }
76
76
  if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N') {
77
77
  await relationsService.createOne(diff[0].rhs);
78
78
  }
79
- if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E') {
80
- const updates = diff.reduce((acc, edit) => {
81
- if (edit.kind !== 'E')
82
- return acc;
83
- (0, lodash_1.set)(acc, edit.path, edit.rhs);
84
- return acc;
85
- }, { collection, field, related_collection });
86
- await relationsService.updateOne(collection, field, updates);
79
+ if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A') {
80
+ const newValues = snapshot.relations.find((relation) => {
81
+ return relation.collection === collection && relation.field === field;
82
+ });
83
+ if (newValues) {
84
+ await relationsService.updateOne(collection, field, newValues);
85
+ }
87
86
  }
88
87
  if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D') {
89
88
  await relationsService.deleteOne(collection, field);
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getColumn = void 0;
4
- const functions_1 = require("../database/functions");
4
+ const helpers_1 = require("../database/helpers");
5
5
  const constants_1 = require("@directus/shared/constants");
6
6
  const apply_function_to_column_name_1 = require("./apply-function-to-column-name");
7
7
  /**
@@ -15,7 +15,7 @@ const apply_function_to_column_name_1 = require("./apply-function-to-column-name
15
15
  * @returns Knex raw instance
16
16
  */
17
17
  function getColumn(knex, table, column, alias = (0, apply_function_to_column_name_1.applyFunctionToColumnName)(column)) {
18
- const fn = (0, functions_1.FunctionsHelper)(knex);
18
+ const { date: fn } = (0, helpers_1.getHelpers)(knex);
19
19
  if (column.includes('(') && column.includes(')')) {
20
20
  const functionName = column.split('(')[0];
21
21
  const columnName = column.match(constants_1.REGEX_BETWEEN_PARENS)[1];
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getDefaultIndexName = void 0;
4
- const get_simple_hash_1 = require("./get-simple-hash");
4
+ const utils_1 = require("@directus/shared/utils");
5
5
  /**
6
6
  * Generate an index name for a given collection + fields combination.
7
7
  *
@@ -18,7 +18,7 @@ function getDefaultIndexName(type, collection, fields) {
18
18
  const indexName = (table + '_' + fields.join('_') + '_' + type).toLowerCase();
19
19
  if (indexName.length <= 60)
20
20
  return indexName;
21
- const suffix = `__${(0, get_simple_hash_1.simpleHash)(indexName)}_${type}`;
21
+ const suffix = `__${(0, utils_1.getSimpleHash)(indexName)}_${type}`;
22
22
  const prefix = indexName.substring(0, 60 - suffix.length);
23
23
  return `${prefix}${suffix}`;
24
24
  }
@@ -1,10 +1,5 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const database_1 = require("../database");
7
- const database_2 = __importDefault(require("../database"));
8
3
  const localTypeMap = {
9
4
  // Shared
10
5
  boolean: 'boolean',
@@ -100,8 +95,6 @@ const localTypeMap = {
100
95
  integerfirst: 'integer',
101
96
  };
102
97
  function getLocalType(column, field) {
103
- const database = (0, database_2.default)();
104
- const databaseClient = (0, database_1.getDatabaseClient)(database);
105
98
  if (!column)
106
99
  return 'alias';
107
100
  const dataType = column.data_type.toLowerCase();
@@ -125,13 +118,9 @@ function getLocalType(column, field) {
125
118
  return 'decimal';
126
119
  }
127
120
  /** Handle MS SQL varchar(MAX) (eg TEXT) types */
128
- if (dataType === 'nvarchar(MAX)') {
121
+ if (column.data_type === 'nvarchar' && column.max_length === -1) {
129
122
  return 'text';
130
123
  }
131
- /** Handle Boolean as TINYINT and edgecase MySQL where it still is just tinyint */
132
- if (databaseClient === 'mysql' && dataType === 'tinyint(1)') {
133
- return 'boolean';
134
- }
135
124
  return type !== null && type !== void 0 ? type : 'unknown';
136
125
  }
137
126
  exports.default = getLocalType;
@@ -23,13 +23,13 @@ function mergePerm(currentPerm, newPerm) {
23
23
  let validation = currentPerm.validation;
24
24
  let fields = currentPerm.fields;
25
25
  let presets = currentPerm.presets;
26
- if (newPerm.permissions) {
26
+ if (newPerm.permissions && !(0, lodash_1.isEmpty)(newPerm.permissions)) {
27
27
  if (currentPerm.permissions && Object.keys(currentPerm.permissions)[0] === '_or') {
28
28
  permissions = {
29
29
  _or: [...currentPerm.permissions._or, newPerm.permissions],
30
30
  };
31
31
  }
32
- else if (currentPerm.permissions) {
32
+ else if (currentPerm.permissions && !(0, lodash_1.isEmpty)(currentPerm.permissions)) {
33
33
  permissions = {
34
34
  _or: [currentPerm.permissions, newPerm.permissions],
35
35
  };
@@ -106,17 +106,6 @@ function sanitizeFilter(rawFilter, accountability) {
106
106
  logger_1.default.warn('Invalid value passed for filter query parameter.');
107
107
  }
108
108
  }
109
- filters = (0, utils_1.deepMap)(filters, (val) => {
110
- try {
111
- const parsed = JSON.parse(val);
112
- if (typeof parsed == 'number' && !Number.isSafeInteger(parsed))
113
- return val;
114
- return parsed;
115
- }
116
- catch {
117
- return val;
118
- }
119
- });
120
109
  return (0, utils_1.parseFilter)(filters, accountability);
121
110
  }
122
111
  function sanitizeLimit(rawLimit) {
@@ -167,7 +156,7 @@ function sanitizeDeep(deep, accountability) {
167
156
  const [parsedKey, parsedValue] = Object.entries(parsedSubQuery)[0];
168
157
  parsedLevel[`_${parsedKey}`] = parsedValue;
169
158
  }
170
- else {
159
+ else if ((0, lodash_1.isPlainObject)(value)) {
171
160
  parse(value, [...path, key]);
172
161
  }
173
162
  }
@@ -100,7 +100,7 @@ function validateFilterPrimitive(value, key) {
100
100
  false) {
101
101
  throw new exceptions_1.InvalidQueryException(`The filter value for "${key}" has to be a string, number, or boolean`);
102
102
  }
103
- if (typeof value === 'number' && Number.isNaN(value)) {
103
+ if (typeof value === 'number' && (Number.isNaN(value) || !Number.isSafeInteger(value))) {
104
104
  throw new exceptions_1.InvalidQueryException(`The filter value for "${key}" is not a valid number`);
105
105
  }
106
106
  if (typeof value === 'string' && value.length === 0) {
package/dist/webhooks.js CHANGED
@@ -8,7 +8,6 @@ const axios_1 = __importDefault(require("axios"));
8
8
  const database_1 = __importDefault(require("./database"));
9
9
  const emitter_1 = __importDefault(require("./emitter"));
10
10
  const logger_1 = __importDefault(require("./logger"));
11
- const lodash_1 = require("lodash");
12
11
  const services_1 = require("./services");
13
12
  const get_schema_1 = require("./utils/get-schema");
14
13
  let registered = [];
@@ -17,20 +16,12 @@ async function register() {
17
16
  const webhookService = new services_1.WebhooksService({ knex: (0, database_1.default)(), schema: await (0, get_schema_1.getSchema)() });
18
17
  const webhooks = await webhookService.readByQuery({ filter: { status: { _eq: 'active' } } });
19
18
  for (const webhook of webhooks) {
20
- if (webhook.actions.includes('*')) {
21
- const event = 'items.*';
22
- const handler = createHandler(webhook);
19
+ for (const action of webhook.actions) {
20
+ const event = `items.${action}`;
21
+ const handler = createHandler(webhook, event);
23
22
  emitter_1.default.onAction(event, handler);
24
23
  registered.push({ event, handler });
25
24
  }
26
- else {
27
- for (const action of webhook.actions) {
28
- const event = `items.${action}`;
29
- const handler = createHandler(webhook);
30
- emitter_1.default.onAction(event, handler);
31
- registered.push({ event, handler });
32
- }
33
- }
34
25
  }
35
26
  }
36
27
  exports.register = register;
@@ -41,19 +32,20 @@ function unregister() {
41
32
  registered = [];
42
33
  }
43
34
  exports.unregister = unregister;
44
- function createHandler(webhook) {
45
- return async (data) => {
46
- if (webhook.collections.includes('*') === false && webhook.collections.includes(data.collection) === false)
35
+ function createHandler(webhook, event) {
36
+ return async (meta, context) => {
37
+ if (webhook.collections.includes(meta.collection) === false)
47
38
  return;
48
- const webhookPayload = (0, lodash_1.pick)(data, [
49
- 'event',
50
- 'accountability.user',
51
- 'accountability.role',
52
- 'collection',
53
- 'item',
54
- 'action',
55
- 'payload',
56
- ]);
39
+ const webhookPayload = {
40
+ event,
41
+ accountability: context.accountability
42
+ ? {
43
+ user: context.accountability.user,
44
+ role: context.accountability.role,
45
+ }
46
+ : null,
47
+ ...meta,
48
+ };
57
49
  try {
58
50
  await (0, axios_1.default)({
59
51
  url: webhook.url,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "directus",
3
- "version": "9.1.2",
3
+ "version": "9.2.0",
4
4
  "license": "GPL-3.0-only",
5
5
  "homepage": "https://github.com/directus/directus#readme",
6
6
  "description": "Directus is a real-time API and App dashboard for managing SQL database content.",
@@ -76,16 +76,16 @@
76
76
  ],
77
77
  "dependencies": {
78
78
  "@aws-sdk/client-ses": "^3.40.0",
79
- "@directus/app": "9.1.2",
80
- "@directus/drive": "9.1.2",
81
- "@directus/drive-azure": "9.1.2",
82
- "@directus/drive-gcs": "9.1.2",
83
- "@directus/drive-s3": "9.1.2",
84
- "@directus/extensions-sdk": "9.1.2",
85
- "@directus/format-title": "9.1.2",
86
- "@directus/schema": "9.1.2",
87
- "@directus/shared": "9.1.2",
88
- "@directus/specs": "9.1.2",
79
+ "@directus/app": "9.2.0",
80
+ "@directus/drive": "9.2.0",
81
+ "@directus/drive-azure": "9.2.0",
82
+ "@directus/drive-gcs": "9.2.0",
83
+ "@directus/drive-s3": "9.2.0",
84
+ "@directus/extensions-sdk": "9.2.0",
85
+ "@directus/format-title": "9.2.0",
86
+ "@directus/schema": "9.2.0",
87
+ "@directus/shared": "9.2.0",
88
+ "@directus/specs": "9.2.0",
89
89
  "@godaddy/terminus": "^4.9.0",
90
90
  "@rollup/plugin-alias": "^3.1.2",
91
91
  "@rollup/plugin-virtual": "^2.0.3",
@@ -122,7 +122,7 @@
122
122
  "jsonwebtoken": "^8.5.1",
123
123
  "keyv": "^4.0.3",
124
124
  "knex": "^0.95.11",
125
- "knex-schema-inspector": "1.6.4",
125
+ "knex-schema-inspector": "1.6.6",
126
126
  "ldapjs": "^2.3.1",
127
127
  "liquidjs": "^9.25.0",
128
128
  "lodash": "^4.17.21",
@@ -169,7 +169,7 @@
169
169
  "sqlite3": "^5.0.2",
170
170
  "tedious": "^13.0.0"
171
171
  },
172
- "gitHead": "9bf033c18dd5bdf6fe4058d915083fd5ca393b05",
172
+ "gitHead": "776c105aacfda559a1ebf49cb2220599652f6c48",
173
173
  "devDependencies": {
174
174
  "@types/async": "3.2.10",
175
175
  "@types/atob": "2.1.2",
@@ -1,14 +0,0 @@
1
- import { Knex } from 'knex';
2
- import { HelperFn } from '../types';
3
- export declare class HelperOracle implements HelperFn {
4
- private knex;
5
- constructor(knex: Knex);
6
- year(table: string, column: string): Knex.Raw;
7
- month(table: string, column: string): Knex.Raw;
8
- week(table: string, column: string): Knex.Raw;
9
- day(table: string, column: string): Knex.Raw;
10
- weekday(table: string, column: string): Knex.Raw;
11
- hour(table: string, column: string): Knex.Raw;
12
- minute(table: string, column: string): Knex.Raw;
13
- second(table: string, column: string): Knex.Raw;
14
- }
@@ -1,14 +0,0 @@
1
- import { Knex } from 'knex';
2
- import { HelperFn } from '../types';
3
- export declare class HelperPostgres implements HelperFn {
4
- private knex;
5
- constructor(knex: Knex);
6
- year(table: string, column: string): Knex.Raw;
7
- month(table: string, column: string): Knex.Raw;
8
- week(table: string, column: string): Knex.Raw;
9
- day(table: string, column: string): Knex.Raw;
10
- weekday(table: string, column: string): Knex.Raw;
11
- hour(table: string, column: string): Knex.Raw;
12
- minute(table: string, column: string): Knex.Raw;
13
- second(table: string, column: string): Knex.Raw;
14
- }
@@ -1,33 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HelperSQLite = void 0;
4
- class HelperSQLite {
5
- constructor(knex) {
6
- this.knex = knex;
7
- }
8
- year(table, column) {
9
- return this.knex.raw("strftime('%Y', ??.??)", [table, column]);
10
- }
11
- month(table, column) {
12
- return this.knex.raw("strftime('%m', ??.??)", [table, column]);
13
- }
14
- week(table, column) {
15
- return this.knex.raw("strftime('%W', ??.??)", [table, column]);
16
- }
17
- day(table, column) {
18
- return this.knex.raw("strftime('%d', ??.??)", [table, column]);
19
- }
20
- weekday(table, column) {
21
- return this.knex.raw("strftime('%w', ??.??)", [table, column]);
22
- }
23
- hour(table, column) {
24
- return this.knex.raw("strftime('%H', ??.??)", [table, column]);
25
- }
26
- minute(table, column) {
27
- return this.knex.raw("strftime('%M', ??.??)", [table, column]);
28
- }
29
- second(table, column) {
30
- return this.knex.raw("strftime('%S', ??.??)", [table, column]);
31
- }
32
- }
33
- exports.HelperSQLite = HelperSQLite;
@@ -1,3 +0,0 @@
1
- import { Knex } from 'knex';
2
- import { HelperFn } from './types';
3
- export declare function FunctionsHelper(knex: Knex): HelperFn;
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FunctionsHelper = void 0;
4
- const postgres_1 = require("./dialects/postgres");
5
- const mysql_1 = require("./dialects/mysql");
6
- const mssql_1 = require("./dialects/mssql");
7
- const sqlite_1 = require("./dialects/sqlite");
8
- const oracle_1 = require("./dialects/oracle");
9
- function FunctionsHelper(knex) {
10
- switch (knex.client.constructor.name) {
11
- case 'Client_MySQL':
12
- return new mysql_1.HelperMySQL(knex);
13
- case 'Client_PG':
14
- return new postgres_1.HelperPostgres(knex);
15
- case 'Client_SQLite3':
16
- return new sqlite_1.HelperSQLite(knex);
17
- case 'Client_Oracledb':
18
- case 'Client_Oracle':
19
- return new oracle_1.HelperOracle(knex);
20
- case 'Client_MSSQL':
21
- return new mssql_1.HelperMSSQL(knex);
22
- default:
23
- throw Error('Unsupported driver used: ' + knex.client.constructor.name);
24
- }
25
- }
26
- exports.FunctionsHelper = FunctionsHelper;
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,8 +0,0 @@
1
- import { Knex } from 'knex';
2
- export declare function getDateHelper(): KnexDate;
3
- declare class KnexDate {
4
- protected knex: Knex;
5
- constructor(knex: Knex);
6
- parseDate(date: string): string;
7
- }
8
- export {};