directus 9.5.2 → 9.7.1

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 (73) hide show
  1. package/dist/app.js +3 -1
  2. package/dist/auth/drivers/ldap.d.ts +0 -1
  3. package/dist/auth/drivers/ldap.js +54 -60
  4. package/dist/auth/drivers/oauth2.js +3 -0
  5. package/dist/auth/drivers/openid.js +3 -0
  6. package/dist/cache.d.ts +4 -1
  7. package/dist/cache.js +27 -5
  8. package/dist/cli/commands/schema/apply.d.ts +1 -0
  9. package/dist/cli/commands/schema/apply.js +9 -5
  10. package/dist/cli/index.js +1 -0
  11. package/dist/cli/utils/create-env/env-stub.liquid +1 -0
  12. package/dist/controllers/assets.js +9 -1
  13. package/dist/controllers/utils.js +18 -1
  14. package/dist/database/index.js +0 -3
  15. package/dist/database/migrations/20220303A-remove-default-project-color.d.ts +3 -0
  16. package/dist/database/migrations/20220303A-remove-default-project-color.js +22 -0
  17. package/dist/database/migrations/20220314A-add-translation-strings.d.ts +3 -0
  18. package/dist/database/migrations/20220314A-add-translation-strings.js +15 -0
  19. package/dist/database/migrations/20220322A-rename-field-typecast-flags.d.ts +3 -0
  20. package/dist/database/migrations/20220322A-rename-field-typecast-flags.js +73 -0
  21. package/dist/database/migrations/run.js +1 -1
  22. package/dist/database/run-ast.d.ts +1 -1
  23. package/dist/database/run-ast.js +48 -35
  24. package/dist/database/system-data/fields/collections.yaml +4 -4
  25. package/dist/database/system-data/fields/fields.yaml +8 -8
  26. package/dist/database/system-data/fields/files.yaml +2 -2
  27. package/dist/database/system-data/fields/panels.yaml +2 -2
  28. package/dist/database/system-data/fields/permissions.yaml +4 -4
  29. package/dist/database/system-data/fields/presets.yaml +3 -3
  30. package/dist/database/system-data/fields/relations.yaml +1 -1
  31. package/dist/database/system-data/fields/revisions.yaml +2 -2
  32. package/dist/database/system-data/fields/roles.yaml +4 -4
  33. package/dist/database/system-data/fields/settings.yaml +25 -6
  34. package/dist/database/system-data/fields/users.yaml +2 -2
  35. package/dist/database/system-data/fields/webhooks.yaml +4 -4
  36. package/dist/env.js +9 -2
  37. package/dist/exceptions/database/dialects/mysql.js +23 -17
  38. package/dist/extensions.js +0 -2
  39. package/dist/middleware/authenticate.d.ts +5 -3
  40. package/dist/middleware/authenticate.js +22 -39
  41. package/dist/middleware/respond.js +7 -28
  42. package/dist/server.js +5 -2
  43. package/dist/services/authorization.js +60 -1
  44. package/dist/services/collections.js +6 -6
  45. package/dist/services/fields.js +3 -3
  46. package/dist/services/files.js +69 -3
  47. package/dist/services/graphql.js +2 -2
  48. package/dist/services/import-export.d.ts +34 -0
  49. package/dist/services/import-export.js +270 -0
  50. package/dist/services/index.d.ts +2 -1
  51. package/dist/services/index.js +2 -1
  52. package/dist/services/items.js +1 -0
  53. package/dist/services/mail/templates/base.liquid +2 -2
  54. package/dist/services/payload.js +3 -3
  55. package/dist/services/permissions.js +10 -10
  56. package/dist/services/relations.js +7 -4
  57. package/dist/services/utils.js +10 -0
  58. package/dist/utils/apply-query.js +2 -24
  59. package/dist/utils/get-date-formatted.d.ts +1 -0
  60. package/dist/utils/get-date-formatted.js +14 -0
  61. package/dist/utils/get-local-type.js +2 -2
  62. package/dist/utils/get-permissions.js +1 -1
  63. package/dist/utils/get-schema.js +1 -1
  64. package/dist/utils/is-directus-jwt.js +4 -21
  65. package/dist/utils/jwt.d.ts +2 -0
  66. package/dist/utils/jwt.js +49 -0
  67. package/dist/utils/merge-permissions.js +18 -6
  68. package/example.env +1 -0
  69. package/package.json +17 -18
  70. package/dist/__mocks__/cache.d.ts +0 -6
  71. package/dist/__mocks__/cache.js +0 -8
  72. package/dist/services/import.d.ts +0 -13
  73. package/dist/services/import.js +0 -118
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.verifyAccessJWT = void 0;
23
+ const jsonwebtoken_1 = __importStar(require("jsonwebtoken"));
24
+ const exceptions_1 = require("../exceptions");
25
+ function verifyAccessJWT(token, secret) {
26
+ let payload;
27
+ try {
28
+ payload = jsonwebtoken_1.default.verify(token, secret, {
29
+ issuer: 'directus',
30
+ });
31
+ }
32
+ catch (err) {
33
+ if (err instanceof jsonwebtoken_1.TokenExpiredError) {
34
+ throw new exceptions_1.InvalidTokenException('Token expired.');
35
+ }
36
+ else if (err instanceof jsonwebtoken_1.JsonWebTokenError) {
37
+ throw new exceptions_1.InvalidTokenException('Token invalid.');
38
+ }
39
+ else {
40
+ throw new exceptions_1.ServiceUnavailableException(`Couldn't verify token.`, { service: 'jwt' });
41
+ }
42
+ }
43
+ const { id, role, app_access, admin_access, share, share_scope } = payload;
44
+ if (role === undefined || app_access === undefined || admin_access === undefined) {
45
+ throw new exceptions_1.InvalidTokenException('Invalid token payload.');
46
+ }
47
+ return { id, role, app_access, admin_access, share, share_scope };
48
+ }
49
+ exports.verifyAccessJWT = verifyAccessJWT;
@@ -31,9 +31,15 @@ function mergePermission(strategy, currentPerm, newPerm) {
31
31
  };
32
32
  }
33
33
  else if (currentPerm.permissions) {
34
- permissions = {
35
- [logicalKey]: [currentPerm.permissions, newPerm.permissions],
36
- };
34
+ // Empty {} supersedes other permissions in _OR merge
35
+ if (strategy === 'or' && ((0, lodash_1.isEqual)(currentPerm.permissions, {}) || (0, lodash_1.isEqual)(newPerm.permissions, {}))) {
36
+ permissions = {};
37
+ }
38
+ else {
39
+ permissions = {
40
+ [logicalKey]: [currentPerm.permissions, newPerm.permissions],
41
+ };
42
+ }
37
43
  }
38
44
  else {
39
45
  permissions = {
@@ -51,9 +57,15 @@ function mergePermission(strategy, currentPerm, newPerm) {
51
57
  };
52
58
  }
53
59
  else if (currentPerm.validation) {
54
- validation = {
55
- [logicalKey]: [currentPerm.validation, newPerm.validation],
56
- };
60
+ // Empty {} supersedes other validations in _OR merge
61
+ if (strategy === 'or' && ((0, lodash_1.isEqual)(currentPerm.validation, {}) || (0, lodash_1.isEqual)(newPerm.validation, {}))) {
62
+ validation = {};
63
+ }
64
+ else {
65
+ validation = {
66
+ [logicalKey]: [currentPerm.validation, newPerm.validation],
67
+ };
68
+ }
57
69
  }
58
70
  else {
59
71
  validation = {
package/example.env CHANGED
@@ -1,6 +1,7 @@
1
1
  ####################################################################################################
2
2
  # General
3
3
 
4
+ HOST="0.0.0.0"
4
5
  PORT=8055
5
6
  PUBLIC_URL="http://localhost:8055"
6
7
  LOG_LEVEL="info"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "directus",
3
- "version": "9.5.2",
3
+ "version": "9.7.1",
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.",
@@ -65,7 +65,7 @@
65
65
  "cli": "cross-env NODE_ENV=development SERVE_APP=false ts-node --script-mode --transpile-only src/cli/run.ts",
66
66
  "test": "jest",
67
67
  "test:coverage": "jest --coverage",
68
- "test:watch": "jest --watchAll"
68
+ "test:watch": "jest --watch"
69
69
  },
70
70
  "engines": {
71
71
  "node": ">=12.20.0"
@@ -78,23 +78,22 @@
78
78
  ],
79
79
  "dependencies": {
80
80
  "@aws-sdk/client-ses": "^3.40.0",
81
- "@directus/app": "9.5.2",
82
- "@directus/drive": "9.5.2",
83
- "@directus/drive-azure": "9.5.2",
84
- "@directus/drive-gcs": "9.5.2",
85
- "@directus/drive-s3": "9.5.2",
86
- "@directus/extensions-sdk": "9.5.2",
87
- "@directus/format-title": "9.5.2",
88
- "@directus/schema": "9.5.2",
89
- "@directus/shared": "9.5.2",
90
- "@directus/specs": "9.5.2",
81
+ "@directus/app": "9.7.1",
82
+ "@directus/drive": "9.7.1",
83
+ "@directus/drive-azure": "9.7.1",
84
+ "@directus/drive-gcs": "9.7.1",
85
+ "@directus/drive-s3": "9.7.1",
86
+ "@directus/extensions-sdk": "9.7.1",
87
+ "@directus/format-title": "9.7.1",
88
+ "@directus/schema": "9.7.1",
89
+ "@directus/shared": "9.7.1",
90
+ "@directus/specs": "9.7.1",
91
91
  "@godaddy/terminus": "^4.9.0",
92
92
  "@rollup/plugin-alias": "^3.1.9",
93
93
  "@rollup/plugin-virtual": "^2.0.3",
94
94
  "argon2": "^0.28.2",
95
95
  "async": "^3.2.0",
96
96
  "async-mutex": "^0.3.1",
97
- "atob": "^2.1.2",
98
97
  "axios": "^0.24.0",
99
98
  "busboy": "^0.3.1",
100
99
  "camelcase": "^6.2.0",
@@ -154,6 +153,7 @@
154
153
  "sharp": "^0.29.0",
155
154
  "stream-json": "^1.7.1",
156
155
  "supertest": "^6.1.6",
156
+ "tmp-promise": "^3.0.3",
157
157
  "update-check": "^1.5.4",
158
158
  "uuid": "^8.3.2",
159
159
  "uuid-validate": "0.0.3",
@@ -173,10 +173,9 @@
173
173
  "sqlite3": "^5.0.2",
174
174
  "tedious": "^13.0.0"
175
175
  },
176
- "gitHead": "47a5da78fb5e31d1657c25103adcb63542396b61",
176
+ "gitHead": "7b1594727686ab8bfac416d851b1f0063f38f893",
177
177
  "devDependencies": {
178
178
  "@types/async": "3.2.10",
179
- "@types/atob": "2.1.2",
180
179
  "@types/body-parser": "1.19.2",
181
180
  "@types/busboy": "0.3.1",
182
181
  "@types/cookie-parser": "1.4.2",
@@ -189,7 +188,7 @@
189
188
  "@types/flat": "5.0.2",
190
189
  "@types/fs-extra": "9.0.13",
191
190
  "@types/inquirer": "8.1.3",
192
- "@types/jest": "27.0.3",
191
+ "@types/jest": "27.4.1",
193
192
  "@types/js-yaml": "4.0.5",
194
193
  "@types/json2csv": "5.0.3",
195
194
  "@types/jsonwebtoken": "8.5.6",
@@ -215,9 +214,9 @@
215
214
  "@types/wellknown": "0.5.1",
216
215
  "copyfiles": "2.4.1",
217
216
  "cross-env": "7.0.3",
218
- "jest": "27.3.1",
217
+ "jest": "27.5.1",
219
218
  "knex-mock-client": "1.6.1",
220
- "ts-jest": "27.0.7",
219
+ "ts-jest": "27.1.3",
221
220
  "ts-node-dev": "1.1.8",
222
221
  "typescript": "4.5.2"
223
222
  }
@@ -1,6 +0,0 @@
1
- /// <reference types="jest" />
2
- export declare const cache: {
3
- get: jest.Mock<any, any>;
4
- set: jest.Mock<any, any>;
5
- };
6
- export declare const getCache: jest.Mock<any, any>;
@@ -1,8 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getCache = exports.cache = void 0;
4
- exports.cache = {
5
- get: jest.fn().mockResolvedValue(undefined),
6
- set: jest.fn().mockResolvedValue(true),
7
- };
8
- exports.getCache = jest.fn().mockReturnValue({ cache: exports.cache });
@@ -1,13 +0,0 @@
1
- /// <reference types="node" />
2
- import { Knex } from 'knex';
3
- import { AbstractServiceOptions } from '../types';
4
- import { Accountability, SchemaOverview } from '@directus/shared/types';
5
- export declare class ImportService {
6
- knex: Knex;
7
- accountability: Accountability | null;
8
- schema: SchemaOverview;
9
- constructor(options: AbstractServiceOptions);
10
- import(collection: string, mimetype: string, stream: NodeJS.ReadableStream): Promise<void>;
11
- importJSON(collection: string, stream: NodeJS.ReadableStream): Promise<void>;
12
- importCSV(collection: string, stream: NodeJS.ReadableStream): Promise<void>;
13
- }
@@ -1,118 +0,0 @@
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.ImportService = void 0;
7
- const database_1 = __importDefault(require("../database"));
8
- const exceptions_1 = require("../exceptions");
9
- const StreamArray_1 = __importDefault(require("stream-json/streamers/StreamArray"));
10
- const items_1 = require("./items");
11
- const async_1 = require("async");
12
- const destroy_1 = __importDefault(require("destroy"));
13
- const csv_parser_1 = __importDefault(require("csv-parser"));
14
- const lodash_1 = require("lodash");
15
- class ImportService {
16
- constructor(options) {
17
- this.knex = options.knex || (0, database_1.default)();
18
- this.accountability = options.accountability || null;
19
- this.schema = options.schema;
20
- }
21
- async import(collection, mimetype, stream) {
22
- var _a, _b, _c, _d, _e;
23
- if (collection.startsWith('directus_'))
24
- throw new exceptions_1.ForbiddenException();
25
- const createPermissions = (_b = (_a = this.accountability) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.find((permission) => permission.collection === collection && permission.action === 'create');
26
- const updatePermissions = (_d = (_c = this.accountability) === null || _c === void 0 ? void 0 : _c.permissions) === null || _d === void 0 ? void 0 : _d.find((permission) => permission.collection === collection && permission.action === 'update');
27
- if (((_e = this.accountability) === null || _e === void 0 ? void 0 : _e.admin) !== true && (!createPermissions || !updatePermissions)) {
28
- throw new exceptions_1.ForbiddenException();
29
- }
30
- switch (mimetype) {
31
- case 'application/json':
32
- return await this.importJSON(collection, stream);
33
- case 'text/csv':
34
- case 'application/vnd.ms-excel':
35
- return await this.importCSV(collection, stream);
36
- default:
37
- throw new exceptions_1.UnsupportedMediaTypeException(`Can't import files of type "${mimetype}"`);
38
- }
39
- }
40
- importJSON(collection, stream) {
41
- const extractJSON = StreamArray_1.default.withParser();
42
- return this.knex.transaction((trx) => {
43
- const service = new items_1.ItemsService(collection, {
44
- knex: trx,
45
- schema: this.schema,
46
- accountability: this.accountability,
47
- });
48
- const saveQueue = (0, async_1.queue)(async (value) => {
49
- return await service.upsertOne(value);
50
- });
51
- return new Promise((resolve, reject) => {
52
- stream.pipe(extractJSON);
53
- extractJSON.on('data', ({ value }) => {
54
- saveQueue.push(value);
55
- });
56
- extractJSON.on('error', (err) => {
57
- (0, destroy_1.default)(stream);
58
- (0, destroy_1.default)(extractJSON);
59
- reject(new exceptions_1.InvalidPayloadException(err.message));
60
- });
61
- saveQueue.error((err) => {
62
- reject(err);
63
- });
64
- extractJSON.on('end', () => {
65
- saveQueue.drain(() => {
66
- return resolve();
67
- });
68
- });
69
- });
70
- });
71
- }
72
- importCSV(collection, stream) {
73
- return this.knex.transaction((trx) => {
74
- const service = new items_1.ItemsService(collection, {
75
- knex: trx,
76
- schema: this.schema,
77
- accountability: this.accountability,
78
- });
79
- const saveQueue = (0, async_1.queue)(async (value) => {
80
- return await service.upsertOne(value);
81
- });
82
- return new Promise((resolve, reject) => {
83
- stream
84
- .pipe((0, csv_parser_1.default)())
85
- .on('data', (value) => {
86
- const obj = (0, lodash_1.transform)(value, (result, value, key) => {
87
- if (value.length === 0) {
88
- delete result[key];
89
- }
90
- else {
91
- try {
92
- const parsedJson = JSON.parse(value);
93
- (0, lodash_1.set)(result, key, parsedJson);
94
- }
95
- catch {
96
- (0, lodash_1.set)(result, key, value);
97
- }
98
- }
99
- });
100
- saveQueue.push(obj);
101
- })
102
- .on('error', (err) => {
103
- (0, destroy_1.default)(stream);
104
- reject(new exceptions_1.InvalidPayloadException(err.message));
105
- })
106
- .on('end', () => {
107
- saveQueue.drain(() => {
108
- return resolve();
109
- });
110
- });
111
- saveQueue.error((err) => {
112
- reject(err);
113
- });
114
- });
115
- });
116
- }
117
- }
118
- exports.ImportService = ImportService;