directus 9.15.1 → 9.16.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 (80) hide show
  1. package/dist/__utils__/items-utils.d.ts +2 -0
  2. package/dist/__utils__/items-utils.js +36 -0
  3. package/dist/__utils__/schemas.d.ts +13 -0
  4. package/dist/__utils__/schemas.js +304 -0
  5. package/dist/__utils__/snapshots.d.ts +5 -0
  6. package/dist/__utils__/snapshots.js +897 -0
  7. package/dist/app.js +1 -0
  8. package/dist/cli/index.test.d.ts +1 -0
  9. package/dist/cli/index.test.js +58 -0
  10. package/dist/cli/utils/create-env/env-stub.liquid +2 -2
  11. package/dist/controllers/assets.js +20 -16
  12. package/dist/controllers/files.test.d.ts +1 -0
  13. package/dist/controllers/files.test.js +49 -0
  14. package/dist/controllers/server.js +0 -1
  15. package/dist/database/migrations/run.test.d.ts +1 -0
  16. package/dist/database/migrations/run.test.js +92 -0
  17. package/dist/env.js +8 -0
  18. package/dist/env.test.d.ts +8 -0
  19. package/dist/env.test.js +39 -0
  20. package/dist/flows.js +2 -1
  21. package/dist/middleware/authenticate.test.d.ts +1 -0
  22. package/dist/middleware/authenticate.test.js +174 -0
  23. package/dist/middleware/extract-token.test.d.ts +1 -0
  24. package/dist/middleware/extract-token.test.js +60 -0
  25. package/dist/operations/exec/index.d.ts +5 -0
  26. package/dist/operations/exec/index.js +26 -0
  27. package/dist/operations/exec/index.test.d.ts +1 -0
  28. package/dist/operations/exec/index.test.js +95 -0
  29. package/dist/operations/notification/index.js +9 -6
  30. package/dist/operations/request/index.js +22 -3
  31. package/dist/services/files.js +3 -2
  32. package/dist/services/files.test.d.ts +1 -0
  33. package/dist/services/files.test.js +53 -0
  34. package/dist/services/flows.js +4 -0
  35. package/dist/services/graphql/index.d.ts +2 -2
  36. package/dist/services/graphql/index.js +33 -38
  37. package/dist/services/items.js +83 -39
  38. package/dist/services/items.test.d.ts +1 -0
  39. package/dist/services/items.test.js +765 -0
  40. package/dist/services/payload.d.ts +7 -4
  41. package/dist/services/payload.js +35 -8
  42. package/dist/services/payload.test.d.ts +1 -0
  43. package/dist/services/payload.test.js +94 -0
  44. package/dist/services/server.js +5 -3
  45. package/dist/services/specifications.test.d.ts +1 -0
  46. package/dist/services/specifications.test.js +96 -0
  47. package/dist/types/items.d.ts +11 -0
  48. package/dist/utils/apply-query.js +7 -3
  49. package/dist/utils/apply-snapshot.js +15 -0
  50. package/dist/utils/apply-snapshot.test.d.ts +1 -0
  51. package/dist/utils/apply-snapshot.test.js +305 -0
  52. package/dist/utils/calculate-field-depth.test.d.ts +1 -0
  53. package/dist/utils/calculate-field-depth.test.js +76 -0
  54. package/dist/utils/filter-items.test.d.ts +1 -0
  55. package/dist/utils/filter-items.test.js +60 -0
  56. package/dist/utils/get-cache-key.test.d.ts +1 -0
  57. package/dist/utils/get-cache-key.test.js +53 -0
  58. package/dist/utils/get-column-path.test.d.ts +1 -0
  59. package/dist/utils/get-column-path.test.js +136 -0
  60. package/dist/utils/get-config-from-env.test.d.ts +1 -0
  61. package/dist/utils/get-config-from-env.test.js +19 -0
  62. package/dist/utils/get-graphql-type.d.ts +1 -1
  63. package/dist/utils/get-graphql-type.js +4 -1
  64. package/dist/utils/get-os-info.d.ts +9 -0
  65. package/dist/utils/get-os-info.js +47 -0
  66. package/dist/utils/get-relation-info.test.d.ts +1 -0
  67. package/dist/utils/get-relation-info.test.js +88 -0
  68. package/dist/utils/get-relation-type.test.d.ts +1 -0
  69. package/dist/utils/get-relation-type.test.js +69 -0
  70. package/dist/utils/get-string-byte-size.test.d.ts +1 -0
  71. package/dist/utils/get-string-byte-size.test.js +8 -0
  72. package/dist/utils/is-directus-jwt.test.d.ts +1 -0
  73. package/dist/utils/is-directus-jwt.test.js +26 -0
  74. package/dist/utils/jwt.test.d.ts +1 -0
  75. package/dist/utils/jwt.test.js +36 -0
  76. package/dist/utils/merge-permissions.test.d.ts +1 -0
  77. package/dist/utils/merge-permissions.test.js +80 -0
  78. package/dist/utils/validate-keys.test.d.ts +1 -0
  79. package/dist/utils/validate-keys.test.js +97 -0
  80. package/package.json +10 -10
@@ -6,7 +6,10 @@ const graphql_compose_1 = require("graphql-compose");
6
6
  const date_1 = require("../services/graphql/types/date");
7
7
  const geojson_1 = require("../services/graphql/types/geojson");
8
8
  const hash_1 = require("../services/graphql/types/hash");
9
- function getGraphQLType(localType) {
9
+ function getGraphQLType(localType, special) {
10
+ if (special.includes('conceal')) {
11
+ return hash_1.GraphQLHash;
12
+ }
10
13
  switch (localType) {
11
14
  case 'boolean':
12
15
  return graphql_1.GraphQLBoolean;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Get current host OS information
3
+ *
4
+ * @returns Object of OS type and version
5
+ */
6
+ export declare function getOSInfo(): {
7
+ osType: string;
8
+ osVersion: string;
9
+ };
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getOSInfo = void 0;
7
+ const os_1 = __importDefault(require("os"));
8
+ /**
9
+ * Get current host OS information
10
+ *
11
+ * @returns Object of OS type and version
12
+ */
13
+ function getOSInfo() {
14
+ const osType = os_1.default.type() === 'Darwin' ? 'macOS' : os_1.default.type();
15
+ const osVersion = osType === 'macOS' ? macosRelease() : os_1.default.release();
16
+ return { osType, osVersion };
17
+ }
18
+ exports.getOSInfo = getOSInfo;
19
+ /**
20
+ * Get the name and version of a macOS release from the Darwin version.
21
+ * Lifted from `macos-release`.
22
+ */
23
+ function macosRelease() {
24
+ const release = Number(os_1.default.release().split('.')[0]);
25
+ const nameMap = new Map([
26
+ [22, ['Ventura', '13']],
27
+ [21, ['Monterey', '12']],
28
+ [20, ['Big Sur', '11']],
29
+ [19, ['Catalina', '10.15']],
30
+ [18, ['Mojave', '10.14']],
31
+ [17, ['High Sierra', '10.13']],
32
+ [16, ['Sierra', '10.12']],
33
+ [15, ['El Capitan', '10.11']],
34
+ [14, ['Yosemite', '10.10']],
35
+ [13, ['Mavericks', '10.9']],
36
+ [12, ['Mountain Lion', '10.8']],
37
+ [11, ['Lion', '10.7']],
38
+ [10, ['Snow Leopard', '10.6']],
39
+ [9, ['Leopard', '10.5']],
40
+ [8, ['Tiger', '10.4']],
41
+ [7, ['Panther', '10.3']],
42
+ [6, ['Jaguar', '10.2']],
43
+ [5, ['Puma', '10.1']],
44
+ ]);
45
+ const current = nameMap.get(release);
46
+ return current ? `${current[0]} (${current[1]})` : 'Unknown';
47
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const get_relation_info_1 = require("../../src/utils/get-relation-info");
4
+ describe('getRelationInfo', () => {
5
+ it('Errors on suspiciously long implicit $FOLLOW', () => {
6
+ expect(() => (0, get_relation_info_1.getRelationInfo)([], 'related_test_collection', '$FOLLOW(test_collection, test_field, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)')).toThrowError(Error);
7
+ });
8
+ it('Generates a new relation object for an implicit o2m relation', () => {
9
+ const result = (0, get_relation_info_1.getRelationInfo)([], 'related_test_collection', '$FOLLOW(test_collection, test_field)');
10
+ expect(result).toEqual({
11
+ relation: {
12
+ collection: 'test_collection',
13
+ field: 'test_field',
14
+ related_collection: 'related_test_collection',
15
+ schema: null,
16
+ meta: null,
17
+ },
18
+ relationType: 'o2m',
19
+ });
20
+ });
21
+ it('Generates a new relation object for an implicit o2a relation', () => {
22
+ const result = (0, get_relation_info_1.getRelationInfo)([], 'related_test_collection', '$FOLLOW(test_collection, test_field, test_collection_field)');
23
+ expect(result).toEqual({
24
+ relation: {
25
+ collection: 'test_collection',
26
+ field: 'test_field',
27
+ related_collection: 'related_test_collection',
28
+ schema: null,
29
+ meta: {
30
+ one_collection_field: 'test_collection_field',
31
+ },
32
+ },
33
+ relationType: 'o2a',
34
+ });
35
+ });
36
+ it('Returns the correct existing relation for the given collection/field', () => {
37
+ const testRelations = [
38
+ // o2m
39
+ {
40
+ collection: 'articles',
41
+ field: 'author_id',
42
+ related_collection: 'authors',
43
+ meta: {
44
+ one_field: 'articles',
45
+ },
46
+ schema: null,
47
+ },
48
+ // m2o
49
+ {
50
+ collection: 'articles',
51
+ field: 'category_id',
52
+ related_collection: 'categories',
53
+ meta: null,
54
+ schema: null,
55
+ },
56
+ // a2o
57
+ {
58
+ collection: 'pages',
59
+ field: 'item',
60
+ related_collection: null,
61
+ meta: {
62
+ one_collection_field: 'collection',
63
+ one_allowed_collections: ['headings', 'paragraphs', 'images'],
64
+ },
65
+ },
66
+ ];
67
+ const o2mResult = (0, get_relation_info_1.getRelationInfo)(testRelations, 'authors', 'articles');
68
+ expect(o2mResult).toEqual({
69
+ relationType: 'o2m',
70
+ relation: testRelations[0],
71
+ });
72
+ const m2oResult = (0, get_relation_info_1.getRelationInfo)(testRelations, 'articles', 'category_id');
73
+ expect(m2oResult).toEqual({
74
+ relationType: 'm2o',
75
+ relation: testRelations[1],
76
+ });
77
+ const a2oResult = (0, get_relation_info_1.getRelationInfo)(testRelations, 'pages', 'item');
78
+ expect(a2oResult).toEqual({
79
+ relationType: 'a2o',
80
+ relation: testRelations[2],
81
+ });
82
+ const noResult = (0, get_relation_info_1.getRelationInfo)(testRelations, 'does not exist', 'wrong field');
83
+ expect(noResult).toEqual({
84
+ relation: null,
85
+ relationType: null,
86
+ });
87
+ });
88
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const get_relation_type_1 = require("../../src/utils/get-relation-type");
4
+ test('Returns null if no relation object is included', () => {
5
+ const result = (0, get_relation_type_1.getRelationType)({ relation: null, collection: null, field: 'test' });
6
+ expect(result).toBe(null);
7
+ });
8
+ test('Returns a2o if relation matches and includes one_collection_field and one_allowed_collection', () => {
9
+ const relation = {
10
+ collection: 'pages',
11
+ field: 'item',
12
+ related_collection: null,
13
+ meta: {
14
+ one_collection_field: 'collection',
15
+ one_allowed_collections: ['paragraphs', 'headings', 'images'],
16
+ },
17
+ };
18
+ const result = (0, get_relation_type_1.getRelationType)({
19
+ relation,
20
+ collection: 'pages',
21
+ field: 'item',
22
+ });
23
+ expect(result).toBe('a2o');
24
+ });
25
+ test('Returns m2o', () => {
26
+ const relation = {
27
+ collection: 'articles',
28
+ field: 'author',
29
+ related_collection: 'authors',
30
+ };
31
+ const result = (0, get_relation_type_1.getRelationType)({
32
+ relation,
33
+ collection: 'articles',
34
+ field: 'author',
35
+ });
36
+ expect(result).toBe('m2o');
37
+ });
38
+ test('Returns o2m', () => {
39
+ const relation = {
40
+ collection: 'articles',
41
+ field: 'author',
42
+ related_collection: 'authors',
43
+ meta: {
44
+ one_field: 'articles',
45
+ },
46
+ };
47
+ const result = (0, get_relation_type_1.getRelationType)({
48
+ relation,
49
+ collection: 'authors',
50
+ field: 'articles',
51
+ });
52
+ expect(result).toBe('o2m');
53
+ });
54
+ test('Returns null when field/collection doesnt match the relationship', () => {
55
+ const relation = {
56
+ collection: 'articles',
57
+ field: 'author',
58
+ related_collection: 'authors',
59
+ meta: {
60
+ one_field: 'articles',
61
+ },
62
+ };
63
+ const result = (0, get_relation_type_1.getRelationType)({
64
+ relation,
65
+ collection: 'unrelated',
66
+ field: 'wrong',
67
+ });
68
+ expect(result).toBe(null);
69
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const get_string_byte_size_1 = require("../../src/utils/get-string-byte-size");
4
+ test('Returns correct byte size for given input string', () => {
5
+ expect((0, get_string_byte_size_1.stringByteSize)('test')).toBe(4);
6
+ expect((0, get_string_byte_size_1.stringByteSize)('🐡')).toBe(4);
7
+ expect((0, get_string_byte_size_1.stringByteSize)('👨‍👧‍👦')).toBe(18);
8
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const is_directus_jwt_1 = __importDefault(require("../../src/utils/is-directus-jwt"));
7
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
+ test('Returns false for non JWT string', () => {
9
+ const result = (0, is_directus_jwt_1.default)('test');
10
+ expect(result).toBe(false);
11
+ });
12
+ test('Returns false for JWTs with text payload', () => {
13
+ const token = jsonwebtoken_1.default.sign('plaintext', 'secret');
14
+ const result = (0, is_directus_jwt_1.default)(token);
15
+ expect(result).toBe(false);
16
+ });
17
+ test(`Returns false if token issuer isn't "directus"`, () => {
18
+ const token = jsonwebtoken_1.default.sign({ payload: 'content' }, 'secret', { issuer: 'rijk' });
19
+ const result = (0, is_directus_jwt_1.default)(token);
20
+ expect(result).toBe(false);
21
+ });
22
+ test(`Returns true if token is valid JWT and issuer is "directus"`, () => {
23
+ const token = jsonwebtoken_1.default.sign({ payload: 'content' }, 'secret', { issuer: 'directus' });
24
+ const result = (0, is_directus_jwt_1.default)(token);
25
+ expect(result).toBe(true);
26
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jwt_1 = require("../../src/utils/jwt");
7
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
+ const exceptions_1 = require("../../src/exceptions");
9
+ const payload = { role: null, app_access: false, admin_access: false };
10
+ const secret = 'test-secret';
11
+ const options = { issuer: 'directus' };
12
+ test('Returns the payload of a correctly signed token', () => {
13
+ const token = jsonwebtoken_1.default.sign(payload, secret, options);
14
+ const result = (0, jwt_1.verifyAccessJWT)(token, secret);
15
+ expect(result).toEqual(payload);
16
+ });
17
+ test('Throws TokenExpiredException when token used has expired', () => {
18
+ const token = jsonwebtoken_1.default.sign({ ...payload, exp: new Date().getTime() / 1000 - 500 }, secret, options);
19
+ expect(() => (0, jwt_1.verifyAccessJWT)(token, secret)).toThrow(exceptions_1.TokenExpiredException);
20
+ });
21
+ const InvalidTokenCases = {
22
+ 'wrong issuer': jsonwebtoken_1.default.sign(payload, secret, { issuer: 'wrong' }),
23
+ 'wrong secret': jsonwebtoken_1.default.sign(payload, 'wrong-secret', options),
24
+ 'string payload': jsonwebtoken_1.default.sign('illegal payload', secret),
25
+ 'missing properties in token payload': jsonwebtoken_1.default.sign({ role: null }, secret, options),
26
+ };
27
+ Object.entries(InvalidTokenCases).forEach(([title, token]) => test(`Throws InvalidTokenError - ${title}`, () => {
28
+ expect(() => (0, jwt_1.verifyAccessJWT)(token, secret)).toThrow(exceptions_1.InvalidTokenException);
29
+ }));
30
+ test(`Throws ServiceUnavailableException for unexpected error from jsonwebtoken`, () => {
31
+ jest.spyOn(jsonwebtoken_1.default, 'verify').mockImplementation(() => {
32
+ throw new Error();
33
+ });
34
+ const token = jsonwebtoken_1.default.sign(payload, secret, options);
35
+ expect(() => (0, jwt_1.verifyAccessJWT)(token, secret)).toThrow(exceptions_1.ServiceUnavailableException);
36
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const merge_permissions_1 = require("../../src/utils/merge-permissions");
4
+ const fullFilter = {};
5
+ const conditionalFilter = { user: { id: { _eq: '$CURRENT_USER' } } };
6
+ const conditionalFilter2 = { count: { _gt: 42 } };
7
+ const permissionTemplate = {
8
+ role: null,
9
+ collection: 'directus_users',
10
+ permissions: null,
11
+ validation: null,
12
+ presets: null,
13
+ fields: null,
14
+ };
15
+ describe('merging permissions', () => {
16
+ test('processes _or permissions', () => {
17
+ const mergedPermission = (0, merge_permissions_1.mergePermission)('or', { ...permissionTemplate, permissions: conditionalFilter }, { ...permissionTemplate, permissions: conditionalFilter2 });
18
+ expect(mergedPermission).toStrictEqual({
19
+ ...permissionTemplate,
20
+ permissions: {
21
+ _or: [conditionalFilter, conditionalFilter2],
22
+ },
23
+ });
24
+ });
25
+ test('processes _or validations', () => {
26
+ const mergedPermission = (0, merge_permissions_1.mergePermission)('or', { ...permissionTemplate, validation: conditionalFilter }, { ...permissionTemplate, validation: conditionalFilter2 });
27
+ expect(mergedPermission).toStrictEqual({
28
+ ...permissionTemplate,
29
+ validation: {
30
+ _or: [conditionalFilter, conditionalFilter2],
31
+ },
32
+ });
33
+ });
34
+ test('processes _and permissions', () => {
35
+ const mergedPermission = (0, merge_permissions_1.mergePermission)('and', { ...permissionTemplate, permissions: conditionalFilter }, { ...permissionTemplate, permissions: conditionalFilter2 });
36
+ expect(mergedPermission).toStrictEqual({
37
+ ...permissionTemplate,
38
+ permissions: {
39
+ _and: [conditionalFilter, conditionalFilter2],
40
+ },
41
+ });
42
+ });
43
+ test('processes _and validations', () => {
44
+ const mergedPermission = (0, merge_permissions_1.mergePermission)('and', { ...permissionTemplate, validation: conditionalFilter }, { ...permissionTemplate, validation: conditionalFilter2 });
45
+ expect(mergedPermission).toStrictEqual({
46
+ ...permissionTemplate,
47
+ validation: {
48
+ _and: [conditionalFilter, conditionalFilter2],
49
+ },
50
+ });
51
+ });
52
+ test('{} supersedes conditional permissions in _or', () => {
53
+ const mergedPermission = (0, merge_permissions_1.mergePermission)('or', { ...permissionTemplate, permissions: fullFilter }, { ...permissionTemplate, permissions: conditionalFilter });
54
+ expect(mergedPermission).toStrictEqual({ ...permissionTemplate, permissions: fullFilter });
55
+ });
56
+ test('{} supersedes conditional validations in _or', () => {
57
+ const mergedPermission = (0, merge_permissions_1.mergePermission)('or', { ...permissionTemplate, validation: fullFilter }, { ...permissionTemplate, validation: conditionalFilter });
58
+ expect(mergedPermission).toStrictEqual({ ...permissionTemplate, validation: fullFilter });
59
+ });
60
+ test('{} does not supersede conditional permissions in _and', () => {
61
+ const mergedPermission = (0, merge_permissions_1.mergePermission)('and', { ...permissionTemplate, permissions: fullFilter }, { ...permissionTemplate, permissions: conditionalFilter });
62
+ const expectedPermission = {
63
+ ...permissionTemplate,
64
+ permissions: {
65
+ _and: [fullFilter, conditionalFilter],
66
+ },
67
+ };
68
+ expect(mergedPermission).toStrictEqual(expectedPermission);
69
+ });
70
+ test('{} does not supersede conditional validations in _and', () => {
71
+ const mergedPermission = (0, merge_permissions_1.mergePermission)('and', { ...permissionTemplate, validation: fullFilter }, { ...permissionTemplate, validation: conditionalFilter });
72
+ const expectedPermission = {
73
+ ...permissionTemplate,
74
+ validation: {
75
+ _and: [fullFilter, conditionalFilter],
76
+ },
77
+ };
78
+ expect(mergedPermission).toStrictEqual(expectedPermission);
79
+ });
80
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const validate_keys_1 = require("../../src/utils/validate-keys");
4
+ const uuid_1 = require("uuid");
5
+ const schema = {
6
+ collections: {
7
+ pk_integer: {
8
+ collection: 'pk_integer',
9
+ primary: 'id',
10
+ singleton: false,
11
+ note: 'Sample schema with integer primary key',
12
+ sortField: null,
13
+ accountability: null,
14
+ fields: {
15
+ id: {
16
+ field: 'id',
17
+ defaultValue: null,
18
+ nullable: false,
19
+ generated: false,
20
+ type: 'integer',
21
+ dbType: 'integer',
22
+ precision: null,
23
+ scale: null,
24
+ special: [],
25
+ note: null,
26
+ alias: false,
27
+ validation: null,
28
+ },
29
+ },
30
+ },
31
+ pk_uuid: {
32
+ collection: 'pk_uuid',
33
+ primary: 'id',
34
+ singleton: false,
35
+ note: 'Sample schema with uuid primary key',
36
+ sortField: null,
37
+ accountability: null,
38
+ fields: {
39
+ id: {
40
+ field: 'id',
41
+ defaultValue: null,
42
+ nullable: false,
43
+ generated: false,
44
+ type: 'uuid',
45
+ dbType: 'uuid',
46
+ precision: null,
47
+ scale: null,
48
+ special: [],
49
+ note: null,
50
+ alias: false,
51
+ validation: null,
52
+ },
53
+ },
54
+ },
55
+ },
56
+ relations: [],
57
+ };
58
+ describe('validate keys', () => {
59
+ describe('of integer type', () => {
60
+ it('Throws an error when provided with an invalid integer key', () => {
61
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_integer', 'id', 'invalid')).toThrowError();
62
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_integer', 'id', NaN)).toThrowError();
63
+ });
64
+ it('Throws an error when provided with an array containing an invalid integer key', () => {
65
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_integer', 'id', [111, 'invalid', 222])).toThrowError();
66
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_integer', 'id', [555, NaN, 666])).toThrowError();
67
+ });
68
+ it('Does not throw an error when provided with a valid integer key', () => {
69
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_integer', 'id', 111)).not.toThrowError();
70
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_integer', 'id', '222')).not.toThrowError();
71
+ });
72
+ it('Does not throw an error when provided with an array of valid integer keys', () => {
73
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_integer', 'id', [111, 222, 333])).not.toThrowError();
74
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_integer', 'id', ['444', '555', '666'])).not.toThrowError();
75
+ });
76
+ });
77
+ describe('of uuid type', () => {
78
+ it('Throws an error when provided with an invalid uuid key', () => {
79
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', 'fakeuuid-62d9-434d-a7c7-878c8376782e')).toThrowError();
80
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', 'invalid')).toThrowError();
81
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', NaN)).toThrowError();
82
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', 111)).toThrowError();
83
+ });
84
+ it('Throws an error when provided with an array containing an invalid uuid key', () => {
85
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', [(0, uuid_1.v4)(), 'fakeuuid-62d9-434d-a7c7-878c8376782e', (0, uuid_1.v4)()])).toThrowError();
86
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', [(0, uuid_1.v4)(), 'invalid', (0, uuid_1.v4)()])).toThrowError();
87
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', [(0, uuid_1.v4)(), NaN, (0, uuid_1.v4)()])).toThrowError();
88
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', [(0, uuid_1.v4)(), 111, (0, uuid_1.v4)()])).toThrowError();
89
+ });
90
+ it('Does not throw an error when provided with a valid uuid key', () => {
91
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', (0, uuid_1.v4)())).not.toThrowError();
92
+ });
93
+ it('Does not throw an error when provided with an array of valid uuid keys', () => {
94
+ expect(() => (0, validate_keys_1.validateKeys)(schema, 'pk_uuid', 'id', [(0, uuid_1.v4)(), (0, uuid_1.v4)(), (0, uuid_1.v4)()])).not.toThrowError();
95
+ });
96
+ });
97
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "directus",
3
- "version": "9.15.1",
3
+ "version": "9.16.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.",
@@ -66,16 +66,16 @@
66
66
  ],
67
67
  "dependencies": {
68
68
  "@aws-sdk/client-ses": "^3.107.0",
69
- "@directus/app": "9.15.1",
69
+ "@directus/app": "9.16.0",
70
70
  "@directus/drive": "9.15.1",
71
- "@directus/drive-azure": "9.15.1",
72
- "@directus/drive-gcs": "9.15.1",
73
- "@directus/drive-s3": "9.15.1",
71
+ "@directus/drive-azure": "9.16.0",
72
+ "@directus/drive-gcs": "9.16.0",
73
+ "@directus/drive-s3": "9.16.0",
74
74
  "@directus/extensions-sdk": "^9.14.1",
75
75
  "@directus/format-title": "^9.15.0",
76
- "@directus/schema": "9.15.1",
77
- "@directus/shared": "9.15.1",
78
- "@directus/specs": "9.15.1",
76
+ "@directus/schema": "9.16.0",
77
+ "@directus/shared": "9.16.0",
78
+ "@directus/specs": "9.16.0",
79
79
  "@godaddy/terminus": "^4.10.2",
80
80
  "@rollup/plugin-alias": "^3.1.9",
81
81
  "@rollup/plugin-virtual": "^2.1.0",
@@ -117,11 +117,10 @@
117
117
  "jsonwebtoken": "^8.5.1",
118
118
  "keyv": "^4.3.0",
119
119
  "knex": "2.2.0",
120
- "knex-schema-inspector": "^2.0.3",
120
+ "knex-schema-inspector": "2.0.4",
121
121
  "ldapjs": "^2.3.3",
122
122
  "liquidjs": "^9.37.0",
123
123
  "lodash": "^4.17.21",
124
- "macos-release": "^2.4.1",
125
124
  "marked": "^4.0.16",
126
125
  "micromustache": "^8.0.3",
127
126
  "mime-types": "^2.1.35",
@@ -152,6 +151,7 @@
152
151
  "update-check": "^1.5.4",
153
152
  "uuid": "^8.3.2",
154
153
  "uuid-validate": "0.0.3",
154
+ "vm2": "^3.9.10",
155
155
  "wellknown": "^0.5.0"
156
156
  },
157
157
  "optionalDependencies": {