directus 9.1.2 → 9.3.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.
- package/dist/auth/drivers/ldap.js +11 -2
- package/dist/auth/drivers/oauth2.d.ts +1 -1
- package/dist/auth/drivers/oauth2.js +46 -19
- package/dist/auth/drivers/openid.d.ts +1 -1
- package/dist/auth/drivers/openid.js +34 -17
- package/dist/auth.js +5 -3
- package/dist/cli/commands/bootstrap/index.js +3 -2
- package/dist/cli/commands/database/install.js +2 -4
- package/dist/cli/commands/init/index.js +3 -7
- package/dist/cli/commands/schema/apply.js +26 -10
- package/dist/cli/utils/defaults.d.ts +11 -0
- package/dist/cli/utils/defaults.js +14 -0
- package/dist/controllers/assets.js +0 -27
- package/dist/controllers/auth.js +7 -2
- package/dist/controllers/extensions.js +1 -1
- package/dist/database/{functions/types.d.ts → helpers/date/dialects/mssql.d.ts} +2 -1
- package/dist/database/{functions → helpers/date}/dialects/mssql.js +4 -6
- package/dist/database/{functions → helpers/date}/dialects/mysql.d.ts +2 -4
- package/dist/database/{functions → helpers/date}/dialects/mysql.js +4 -6
- package/dist/database/{functions/dialects/mssql.d.ts → helpers/date/dialects/oracle.d.ts} +2 -4
- package/dist/database/{functions → helpers/date}/dialects/oracle.js +4 -6
- package/dist/database/helpers/date/dialects/postgres.d.ts +12 -0
- package/dist/database/{functions → helpers/date}/dialects/postgres.js +4 -6
- package/dist/database/{functions → helpers/date}/dialects/sqlite.d.ts +3 -4
- package/dist/database/helpers/date/dialects/sqlite.js +35 -0
- package/dist/database/helpers/date/index.d.ts +6 -0
- package/dist/database/helpers/date/index.js +15 -0
- package/dist/database/helpers/date/types.d.ts +13 -0
- package/dist/database/helpers/date/types.js +10 -0
- package/dist/database/helpers/geometry/dialects/mssql.d.ts +14 -0
- package/dist/database/helpers/geometry/dialects/mssql.js +36 -0
- package/dist/database/helpers/geometry/dialects/mysql.d.ts +7 -0
- package/dist/database/helpers/geometry/dialects/mysql.js +16 -0
- package/dist/database/helpers/geometry/dialects/oracle.d.ts +15 -0
- package/dist/database/helpers/geometry/dialects/oracle.js +39 -0
- package/dist/database/helpers/geometry/dialects/postgres.d.ts +10 -0
- package/dist/database/helpers/geometry/dialects/postgres.js +23 -0
- package/dist/database/helpers/geometry/dialects/redshift.d.ts +7 -0
- package/dist/database/helpers/geometry/dialects/redshift.js +16 -0
- package/dist/database/helpers/geometry/dialects/sqlite.d.ts +6 -0
- package/dist/database/helpers/geometry/dialects/sqlite.js +14 -0
- package/dist/database/helpers/geometry/index.d.ts +6 -0
- package/dist/database/helpers/geometry/index.js +15 -0
- package/dist/database/helpers/{geometry.d.ts → geometry/types.d.ts} +3 -7
- package/dist/database/helpers/geometry/types.js +54 -0
- package/dist/database/helpers/index.d.ts +8 -0
- package/dist/database/helpers/index.js +33 -0
- package/dist/database/helpers/types.d.ts +5 -0
- package/dist/database/helpers/types.js +9 -0
- package/dist/database/index.js +6 -6
- package/dist/database/run-ast.js +5 -5
- package/dist/database/seeds/run.js +3 -3
- package/dist/database/system-data/fields/notifications.yaml +1 -0
- package/dist/emitter.d.ts +3 -2
- package/dist/emitter.js +13 -6
- package/dist/env.js +1 -0
- package/dist/exceptions/index.d.ts +2 -0
- package/dist/exceptions/index.js +2 -0
- package/dist/exceptions/invalid-token.d.ts +4 -0
- package/dist/exceptions/invalid-token.js +10 -0
- package/dist/exceptions/unexpected-response.d.ts +4 -0
- package/dist/exceptions/unexpected-response.js +10 -0
- package/dist/extensions.d.ts +1 -0
- package/dist/extensions.js +22 -3
- package/dist/middleware/sanitize-query.js +1 -1
- package/dist/services/activity.js +7 -2
- package/dist/services/assets.js +14 -0
- package/dist/services/fields.d.ts +2 -0
- package/dist/services/fields.js +57 -26
- package/dist/services/files.d.ts +1 -1
- package/dist/services/files.js +27 -19
- package/dist/services/graphql.js +3 -0
- package/dist/services/items.js +18 -29
- package/dist/services/payload.d.ts +2 -0
- package/dist/services/payload.js +3 -3
- package/dist/services/users.js +8 -6
- package/dist/tests/database/migrations/run.test.d.ts +1 -0
- package/dist/tests/database/migrations/run.test.js +29 -0
- package/dist/types/extensions.d.ts +2 -0
- package/dist/utils/apply-query.js +9 -12
- package/dist/utils/apply-snapshot.js +91 -37
- package/dist/utils/get-column.js +2 -2
- package/dist/utils/get-default-index-name.js +2 -2
- package/dist/utils/get-local-type.js +1 -12
- package/dist/utils/get-permissions.d.ts +2 -2
- package/dist/utils/get-permissions.js +103 -66
- package/dist/utils/sanitize-query.js +1 -12
- package/dist/utils/validate-query.js +1 -1
- package/dist/webhooks.js +16 -24
- package/package.json +15 -14
- package/dist/database/functions/dialects/oracle.d.ts +0 -14
- package/dist/database/functions/dialects/postgres.d.ts +0 -14
- package/dist/database/functions/dialects/sqlite.js +0 -33
- package/dist/database/functions/index.d.ts +0 -3
- package/dist/database/functions/index.js +0 -26
- package/dist/database/functions/types.js +0 -2
- package/dist/database/helpers/date.d.ts +0 -8
- package/dist/database/helpers/date.js +0 -44
- package/dist/database/helpers/geometry.js +0 -189
- package/dist/utils/get-simple-hash.d.ts +0 -5
- package/dist/utils/get-simple-hash.js +0 -15
package/dist/database/index.js
CHANGED
|
@@ -15,7 +15,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
15
15
|
const path_1 = __importDefault(require("path"));
|
|
16
16
|
const lodash_1 = require("lodash");
|
|
17
17
|
const util_1 = require("util");
|
|
18
|
-
const
|
|
18
|
+
const helpers_1 = require("./helpers");
|
|
19
19
|
let database = null;
|
|
20
20
|
let inspector = null;
|
|
21
21
|
function getDatabase() {
|
|
@@ -197,11 +197,11 @@ exports.validateMigrations = validateMigrations;
|
|
|
197
197
|
*/
|
|
198
198
|
async function validateDatabaseExtensions() {
|
|
199
199
|
const database = getDatabase();
|
|
200
|
-
const
|
|
201
|
-
const
|
|
202
|
-
const geometrySupport = await
|
|
200
|
+
const client = getDatabaseClient(database);
|
|
201
|
+
const helpers = (0, helpers_1.getHelpers)(database);
|
|
202
|
+
const geometrySupport = await helpers.st.supported();
|
|
203
203
|
if (!geometrySupport) {
|
|
204
|
-
switch (
|
|
204
|
+
switch (client) {
|
|
205
205
|
case 'postgres':
|
|
206
206
|
logger_1.default.warn(`PostGIS isn't installed. Geometry type support will be limited.`);
|
|
207
207
|
break;
|
|
@@ -209,7 +209,7 @@ async function validateDatabaseExtensions() {
|
|
|
209
209
|
logger_1.default.warn(`Spatialite isn't installed. Geometry type support will be limited.`);
|
|
210
210
|
break;
|
|
211
211
|
default:
|
|
212
|
-
logger_1.default.warn(`Geometry type not supported on ${
|
|
212
|
+
logger_1.default.warn(`Geometry type not supported on ${client}`);
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
}
|
package/dist/database/run-ast.js
CHANGED
|
@@ -10,14 +10,14 @@ const apply_query_1 = __importDefault(require("../utils/apply-query"));
|
|
|
10
10
|
const get_column_1 = require("../utils/get-column");
|
|
11
11
|
const strip_function_1 = require("../utils/strip-function");
|
|
12
12
|
const utils_1 = require("@directus/shared/utils");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const _1 = __importDefault(require("."));
|
|
14
|
+
const helpers_1 = require("../database/helpers");
|
|
15
15
|
/**
|
|
16
16
|
* Execute a given AST using Knex. Returns array of items based on requested AST.
|
|
17
17
|
*/
|
|
18
18
|
async function runAST(originalAST, schema, options) {
|
|
19
19
|
const ast = (0, lodash_1.cloneDeep)(originalAST);
|
|
20
|
-
const knex = (options === null || options === void 0 ? void 0 : options.knex) || (0,
|
|
20
|
+
const knex = (options === null || options === void 0 ? void 0 : options.knex) || (0, _1.default)();
|
|
21
21
|
if (ast.type === 'm2a') {
|
|
22
22
|
const results = {};
|
|
23
23
|
for (const collection of ast.names) {
|
|
@@ -111,7 +111,7 @@ async function parseCurrentLevel(schema, collection, children, query) {
|
|
|
111
111
|
return { fieldNodes, nestedCollectionNodes, primaryKeyField };
|
|
112
112
|
}
|
|
113
113
|
function getColumnPreprocessor(knex, schema, table) {
|
|
114
|
-
const
|
|
114
|
+
const helpers = (0, helpers_1.getHelpers)(knex);
|
|
115
115
|
return function (fieldNode) {
|
|
116
116
|
let field;
|
|
117
117
|
if (fieldNode.type === 'field') {
|
|
@@ -125,7 +125,7 @@ function getColumnPreprocessor(knex, schema, table) {
|
|
|
125
125
|
alias = fieldNode.fieldKey;
|
|
126
126
|
}
|
|
127
127
|
if (field.type.startsWith('geometry')) {
|
|
128
|
-
return
|
|
128
|
+
return helpers.st.asText(table, field.field);
|
|
129
129
|
}
|
|
130
130
|
return (0, get_column_1.getColumn)(knex, table, fieldNode.name, alias);
|
|
131
131
|
};
|
|
@@ -7,8 +7,9 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
7
7
|
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
8
8
|
const lodash_1 = require("lodash");
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const
|
|
10
|
+
const helpers_1 = require("../helpers");
|
|
11
11
|
async function runSeed(database) {
|
|
12
|
+
const helpers = (0, helpers_1.getHelpers)(database);
|
|
12
13
|
const exists = await database.schema.hasTable('directus_collections');
|
|
13
14
|
if (exists) {
|
|
14
15
|
throw new Error('Database is already installed');
|
|
@@ -38,8 +39,7 @@ async function runSeed(database) {
|
|
|
38
39
|
column = tableBuilder.string(columnName, 255);
|
|
39
40
|
}
|
|
40
41
|
else if ((_a = columnInfo.type) === null || _a === void 0 ? void 0 : _a.startsWith('geometry')) {
|
|
41
|
-
|
|
42
|
-
column = helper.createColumn(tableBuilder, { field: columnName, type: columnInfo.type });
|
|
42
|
+
column = helpers.st.createColumn(tableBuilder, { field: columnName, type: columnInfo.type });
|
|
43
43
|
}
|
|
44
44
|
else {
|
|
45
45
|
// @ts-ignore
|
package/dist/emitter.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ActionHandler, FilterHandler, HookContext, InitHandler } from './types';
|
|
2
|
-
declare class Emitter {
|
|
2
|
+
export declare class Emitter {
|
|
3
3
|
private filterEmitter;
|
|
4
4
|
private actionEmitter;
|
|
5
5
|
private initEmitter;
|
|
6
6
|
constructor();
|
|
7
|
-
eventsToEmit(event: string, meta: Record<string, any>): string[];
|
|
8
7
|
emitFilter<T>(event: string, payload: T, meta: Record<string, any>, context: HookContext): Promise<T>;
|
|
9
8
|
emitAction(event: string, meta: Record<string, any>, context: HookContext): void;
|
|
10
9
|
emitInit(event: string, meta: Record<string, any>): Promise<void>;
|
|
@@ -14,6 +13,8 @@ declare class Emitter {
|
|
|
14
13
|
offFilter(event: string, handler: FilterHandler): void;
|
|
15
14
|
offAction(event: string, handler: ActionHandler): void;
|
|
16
15
|
offInit(event: string, handler: InitHandler): void;
|
|
16
|
+
offAll(): void;
|
|
17
|
+
private eventsToEmit;
|
|
17
18
|
}
|
|
18
19
|
declare const emitter: Emitter;
|
|
19
20
|
export default emitter;
|
package/dist/emitter.js
CHANGED
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Emitter = void 0;
|
|
6
7
|
const eventemitter2_1 = require("eventemitter2");
|
|
7
8
|
const logger_1 = __importDefault(require("./logger"));
|
|
8
9
|
class Emitter {
|
|
@@ -18,12 +19,6 @@ class Emitter {
|
|
|
18
19
|
this.actionEmitter = new eventemitter2_1.EventEmitter2(emitterOptions);
|
|
19
20
|
this.initEmitter = new eventemitter2_1.EventEmitter2(emitterOptions);
|
|
20
21
|
}
|
|
21
|
-
eventsToEmit(event, meta) {
|
|
22
|
-
if (event.startsWith('items')) {
|
|
23
|
-
return [event, `${meta.collection}.${event}`];
|
|
24
|
-
}
|
|
25
|
-
return [event];
|
|
26
|
-
}
|
|
27
22
|
async emitFilter(event, payload, meta, context) {
|
|
28
23
|
const events = this.eventsToEmit(event, meta);
|
|
29
24
|
const listeners = events.flatMap((event) => this.filterEmitter.listeners(event));
|
|
@@ -72,6 +67,18 @@ class Emitter {
|
|
|
72
67
|
offInit(event, handler) {
|
|
73
68
|
this.initEmitter.off(event, handler);
|
|
74
69
|
}
|
|
70
|
+
offAll() {
|
|
71
|
+
this.filterEmitter.removeAllListeners();
|
|
72
|
+
this.actionEmitter.removeAllListeners();
|
|
73
|
+
this.initEmitter.removeAllListeners();
|
|
74
|
+
}
|
|
75
|
+
eventsToEmit(event, meta) {
|
|
76
|
+
if (event.startsWith('items')) {
|
|
77
|
+
return [event, `${meta.collection}.${event}`];
|
|
78
|
+
}
|
|
79
|
+
return [event];
|
|
80
|
+
}
|
|
75
81
|
}
|
|
82
|
+
exports.Emitter = Emitter;
|
|
76
83
|
const emitter = new Emitter();
|
|
77
84
|
exports.default = emitter;
|
package/dist/env.js
CHANGED
|
@@ -8,9 +8,11 @@ export * from './invalid-ip';
|
|
|
8
8
|
export * from './invalid-otp';
|
|
9
9
|
export * from './invalid-payload';
|
|
10
10
|
export * from './invalid-query';
|
|
11
|
+
export * from './invalid-token';
|
|
11
12
|
export * from './method-not-allowed';
|
|
12
13
|
export * from './range-not-satisfiable';
|
|
13
14
|
export * from './route-not-found';
|
|
14
15
|
export * from './service-unavailable';
|
|
15
16
|
export * from './unprocessable-entity';
|
|
16
17
|
export * from './user-suspended';
|
|
18
|
+
export * from './unexpected-response';
|
package/dist/exceptions/index.js
CHANGED
|
@@ -20,9 +20,11 @@ __exportStar(require("./invalid-ip"), exports);
|
|
|
20
20
|
__exportStar(require("./invalid-otp"), exports);
|
|
21
21
|
__exportStar(require("./invalid-payload"), exports);
|
|
22
22
|
__exportStar(require("./invalid-query"), exports);
|
|
23
|
+
__exportStar(require("./invalid-token"), exports);
|
|
23
24
|
__exportStar(require("./method-not-allowed"), exports);
|
|
24
25
|
__exportStar(require("./range-not-satisfiable"), exports);
|
|
25
26
|
__exportStar(require("./route-not-found"), exports);
|
|
26
27
|
__exportStar(require("./service-unavailable"), exports);
|
|
27
28
|
__exportStar(require("./unprocessable-entity"), exports);
|
|
28
29
|
__exportStar(require("./user-suspended"), exports);
|
|
30
|
+
__exportStar(require("./unexpected-response"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvalidTokenException = void 0;
|
|
4
|
+
const exceptions_1 = require("@directus/shared/exceptions");
|
|
5
|
+
class InvalidTokenException extends exceptions_1.BaseException {
|
|
6
|
+
constructor(message = 'Invalid token') {
|
|
7
|
+
super(message, 403, 'INVALID_TOKEN');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.InvalidTokenException = InvalidTokenException;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnexpectedResponseException = void 0;
|
|
4
|
+
const exceptions_1 = require("@directus/shared/exceptions");
|
|
5
|
+
class UnexpectedResponseException extends exceptions_1.BaseException {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message, 503, 'UNEXPECTED_RESPONSE');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.UnexpectedResponseException = UnexpectedResponseException;
|
package/dist/extensions.d.ts
CHANGED
package/dist/extensions.js
CHANGED
|
@@ -28,9 +28,10 @@ const path_1 = __importDefault(require("path"));
|
|
|
28
28
|
const node_1 = require("@directus/shared/utils/node");
|
|
29
29
|
const constants_1 = require("@directus/shared/constants");
|
|
30
30
|
const database_1 = __importDefault(require("./database"));
|
|
31
|
-
const emitter_1 =
|
|
31
|
+
const emitter_1 = __importStar(require("./emitter"));
|
|
32
32
|
const env_1 = __importDefault(require("./env"));
|
|
33
33
|
const exceptions = __importStar(require("./exceptions"));
|
|
34
|
+
const sharedExceptions = __importStar(require("@directus/shared/exceptions"));
|
|
34
35
|
const logger_1 = __importDefault(require("./logger"));
|
|
35
36
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
36
37
|
const get_schema_1 = require("./utils/get-schema");
|
|
@@ -60,6 +61,7 @@ class ExtensionManager {
|
|
|
60
61
|
this.apiHooks = [];
|
|
61
62
|
this.apiEndpoints = [];
|
|
62
63
|
this.isScheduleHookEnabled = true;
|
|
64
|
+
this.apiEmitter = new emitter_1.Emitter();
|
|
63
65
|
this.endpointRouter = (0, express_1.Router)();
|
|
64
66
|
}
|
|
65
67
|
async initialize({ schedule } = { schedule: true }) {
|
|
@@ -91,6 +93,7 @@ class ExtensionManager {
|
|
|
91
93
|
logger_1.default.info('Reloading extensions');
|
|
92
94
|
this.unregisterHooks();
|
|
93
95
|
this.unregisterEndpoints();
|
|
96
|
+
this.apiEmitter.offAll();
|
|
94
97
|
if (env_1.default.SERVE_APP) {
|
|
95
98
|
this.appExtensions = {};
|
|
96
99
|
}
|
|
@@ -231,7 +234,15 @@ class ExtensionManager {
|
|
|
231
234
|
}
|
|
232
235
|
},
|
|
233
236
|
};
|
|
234
|
-
register(registerFunctions, {
|
|
237
|
+
register(registerFunctions, {
|
|
238
|
+
services,
|
|
239
|
+
exceptions: { ...exceptions, ...sharedExceptions },
|
|
240
|
+
env: env_1.default,
|
|
241
|
+
database: (0, database_1.default)(),
|
|
242
|
+
emitter: this.apiEmitter,
|
|
243
|
+
logger: logger_1.default,
|
|
244
|
+
getSchema: get_schema_1.getSchema,
|
|
245
|
+
});
|
|
235
246
|
}
|
|
236
247
|
registerEndpoint(endpoint, router) {
|
|
237
248
|
const endpointPath = path_1.default.resolve(endpoint.path, endpoint.entrypoint || '');
|
|
@@ -241,7 +252,15 @@ class ExtensionManager {
|
|
|
241
252
|
const routeName = typeof mod === 'function' ? endpoint.name : mod.id;
|
|
242
253
|
const scopedRouter = express_1.default.Router();
|
|
243
254
|
router.use(`/${routeName}`, scopedRouter);
|
|
244
|
-
register(scopedRouter, {
|
|
255
|
+
register(scopedRouter, {
|
|
256
|
+
services,
|
|
257
|
+
exceptions: { ...exceptions, ...sharedExceptions },
|
|
258
|
+
env: env_1.default,
|
|
259
|
+
database: (0, database_1.default)(),
|
|
260
|
+
emitter: this.apiEmitter,
|
|
261
|
+
logger: logger_1.default,
|
|
262
|
+
getSchema: get_schema_1.getSchema,
|
|
263
|
+
});
|
|
245
264
|
this.apiEndpoints.push({
|
|
246
265
|
path: endpointPath,
|
|
247
266
|
});
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
const sanitize_query_1 = require("../utils/sanitize-query");
|
|
8
8
|
const validate_query_1 = require("../utils/validate-query");
|
|
9
|
-
const sanitizeQueryMiddleware = (req,
|
|
9
|
+
const sanitizeQueryMiddleware = (req, _res, next) => {
|
|
10
10
|
req.sanitizedQuery = {};
|
|
11
11
|
if (!req.query)
|
|
12
12
|
return;
|
|
@@ -15,6 +15,7 @@ const logger_1 = __importDefault(require("../logger"));
|
|
|
15
15
|
const user_name_1 = require("../utils/user-name");
|
|
16
16
|
const lodash_1 = require("lodash");
|
|
17
17
|
const env_1 = __importDefault(require("../env"));
|
|
18
|
+
const uuid_validate_1 = __importDefault(require("uuid-validate"));
|
|
18
19
|
class ActivityService extends index_1.ItemsService {
|
|
19
20
|
constructor(options) {
|
|
20
21
|
super('directus_activity', options);
|
|
@@ -55,9 +56,13 @@ class ActivityService extends index_1.ItemsService {
|
|
|
55
56
|
}, {});
|
|
56
57
|
let comment = data.comment;
|
|
57
58
|
for (const mention of mentions) {
|
|
58
|
-
|
|
59
|
+
const uuid = mention.substring(1);
|
|
60
|
+
// We only match on UUIDs in the first place. This is just an extra sanity check
|
|
61
|
+
if ((0, uuid_validate_1.default)(uuid) === false)
|
|
62
|
+
continue;
|
|
63
|
+
comment = comment.replace(new RegExp(mention, 'gm'), (_h = userPreviews[uuid]) !== null && _h !== void 0 ? _h : '@Unknown User');
|
|
59
64
|
}
|
|
60
|
-
comment = `> ${comment}`;
|
|
65
|
+
comment = `> ${comment.replace(/\n+/gm, '\n> ')}`;
|
|
61
66
|
const message = `
|
|
62
67
|
Hello ${(0, user_name_1.userName)(user)},
|
|
63
68
|
|
package/dist/services/assets.js
CHANGED
|
@@ -34,6 +34,7 @@ const exceptions_1 = require("../exceptions");
|
|
|
34
34
|
const storage_1 = __importDefault(require("../storage"));
|
|
35
35
|
const authorization_1 = require("./authorization");
|
|
36
36
|
const TransformationUtils = __importStar(require("../utils/transformations"));
|
|
37
|
+
const uuid_validate_1 = __importDefault(require("uuid-validate"));
|
|
37
38
|
sharp_1.default.concurrency(1);
|
|
38
39
|
// Note: don't put this in the service. The service can be initialized in multiple places, but they
|
|
39
40
|
// should all share the same semaphore instance.
|
|
@@ -54,7 +55,20 @@ class AssetsService {
|
|
|
54
55
|
if (systemPublicKeys.includes(id) === false && ((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) !== true) {
|
|
55
56
|
await this.authorizationService.checkAccess('read', 'directus_files', id);
|
|
56
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* This is a little annoying. Postgres will error out if you're trying to search in `where`
|
|
60
|
+
* with a wrong type. In case of directus_files where id is a uuid, we'll have to verify the
|
|
61
|
+
* validity of the uuid ahead of time.
|
|
62
|
+
*/
|
|
63
|
+
const isValidUUID = (0, uuid_validate_1.default)(id, 4);
|
|
64
|
+
if (isValidUUID === false)
|
|
65
|
+
throw new exceptions_1.ForbiddenException();
|
|
57
66
|
const file = (await this.knex.select('*').from('directus_files').where({ id }).first());
|
|
67
|
+
if (!file)
|
|
68
|
+
throw new exceptions_1.ForbiddenException();
|
|
69
|
+
const { exists } = await storage_1.default.disk(file.storage).exists(file.filename_disk);
|
|
70
|
+
if (!exists)
|
|
71
|
+
throw new exceptions_1.ForbiddenException();
|
|
58
72
|
if (range) {
|
|
59
73
|
if (range.start >= file.filesize || (range.end && range.end >= file.filesize)) {
|
|
60
74
|
throw new exceptions_1.RangeNotSatisfiableException(range);
|
|
@@ -6,9 +6,11 @@ import { PayloadService } from '../services/payload';
|
|
|
6
6
|
import { AbstractServiceOptions, SchemaOverview } from '../types';
|
|
7
7
|
import { Accountability } from '@directus/shared/types';
|
|
8
8
|
import { Field, RawField, Type } from '@directus/shared/types';
|
|
9
|
+
import { Helpers } from '../database/helpers';
|
|
9
10
|
import Keyv from 'keyv';
|
|
10
11
|
export declare class FieldsService {
|
|
11
12
|
knex: Knex;
|
|
13
|
+
helpers: Helpers;
|
|
12
14
|
accountability: Accountability | null;
|
|
13
15
|
itemsService: ItemsService;
|
|
14
16
|
payloadService: PayloadService;
|
package/dist/services/fields.js
CHANGED
|
@@ -39,10 +39,11 @@ const get_local_type_1 = __importDefault(require("../utils/get-local-type"));
|
|
|
39
39
|
const utils_1 = require("@directus/shared/utils");
|
|
40
40
|
const lodash_1 = require("lodash");
|
|
41
41
|
const relations_1 = require("./relations");
|
|
42
|
-
const
|
|
42
|
+
const helpers_1 = require("../database/helpers");
|
|
43
43
|
class FieldsService {
|
|
44
44
|
constructor(options) {
|
|
45
45
|
this.knex = options.knex || (0, database_1.default)();
|
|
46
|
+
this.helpers = (0, helpers_1.getHelpers)(this.knex);
|
|
46
47
|
this.schemaInspector = options.knex ? (0, schema_1.default)(options.knex) : (0, database_1.getSchemaInspector)();
|
|
47
48
|
this.accountability = options.accountability || null;
|
|
48
49
|
this.itemsService = new items_1.ItemsService('directus_fields', options);
|
|
@@ -211,23 +212,39 @@ class FieldsService {
|
|
|
211
212
|
accountability: this.accountability,
|
|
212
213
|
schema: this.schema,
|
|
213
214
|
});
|
|
214
|
-
|
|
215
|
+
const hookAdjustedField = await emitter_1.default.emitFilter(`fields.create`, field, {
|
|
216
|
+
collection: collection,
|
|
217
|
+
}, {
|
|
218
|
+
database: trx,
|
|
219
|
+
schema: this.schema,
|
|
220
|
+
accountability: this.accountability,
|
|
221
|
+
});
|
|
222
|
+
if (hookAdjustedField.type && constants_1.ALIAS_TYPES.includes(hookAdjustedField.type) === false) {
|
|
215
223
|
if (table) {
|
|
216
|
-
this.addColumnToTable(table,
|
|
224
|
+
this.addColumnToTable(table, hookAdjustedField);
|
|
217
225
|
}
|
|
218
226
|
else {
|
|
219
227
|
await trx.schema.alterTable(collection, (table) => {
|
|
220
|
-
this.addColumnToTable(table,
|
|
228
|
+
this.addColumnToTable(table, hookAdjustedField);
|
|
221
229
|
});
|
|
222
230
|
}
|
|
223
231
|
}
|
|
224
|
-
if (
|
|
232
|
+
if (hookAdjustedField.meta) {
|
|
225
233
|
await itemsService.createOne({
|
|
226
|
-
...
|
|
234
|
+
...hookAdjustedField.meta,
|
|
227
235
|
collection: collection,
|
|
228
|
-
field:
|
|
229
|
-
});
|
|
236
|
+
field: hookAdjustedField.field,
|
|
237
|
+
}, { emitEvents: false });
|
|
230
238
|
}
|
|
239
|
+
emitter_1.default.emitAction(`fields.create`, {
|
|
240
|
+
payload: hookAdjustedField,
|
|
241
|
+
key: hookAdjustedField.field,
|
|
242
|
+
collection: collection,
|
|
243
|
+
}, {
|
|
244
|
+
database: (0, database_1.default)(),
|
|
245
|
+
schema: this.schema,
|
|
246
|
+
accountability: this.accountability,
|
|
247
|
+
});
|
|
231
248
|
});
|
|
232
249
|
if (this.cache && env_1.default.CACHE_AUTO_PURGE) {
|
|
233
250
|
await this.cache.clear();
|
|
@@ -238,12 +255,23 @@ class FieldsService {
|
|
|
238
255
|
if (this.accountability && this.accountability.admin !== true) {
|
|
239
256
|
throw new exceptions_1.ForbiddenException();
|
|
240
257
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
258
|
+
const hookAdjustedField = await emitter_1.default.emitFilter(`fields.update`, field, {
|
|
259
|
+
keys: [field.field],
|
|
260
|
+
collection: collection,
|
|
261
|
+
}, {
|
|
262
|
+
database: this.knex,
|
|
263
|
+
schema: this.schema,
|
|
264
|
+
accountability: this.accountability,
|
|
265
|
+
});
|
|
266
|
+
const record = field.meta
|
|
267
|
+
? await this.knex.select('id').from('directus_fields').where({ collection, field: field.field }).first()
|
|
268
|
+
: null;
|
|
269
|
+
if (hookAdjustedField.schema) {
|
|
270
|
+
const existingColumn = await this.schemaInspector.columnInfo(collection, hookAdjustedField.field);
|
|
271
|
+
if (!(0, lodash_1.isEqual)(existingColumn, hookAdjustedField.schema)) {
|
|
244
272
|
try {
|
|
245
273
|
await this.knex.schema.alterTable(collection, (table) => {
|
|
246
|
-
if (!
|
|
274
|
+
if (!hookAdjustedField.schema)
|
|
247
275
|
return;
|
|
248
276
|
this.addColumnToTable(table, field, existingColumn);
|
|
249
277
|
});
|
|
@@ -253,31 +281,35 @@ class FieldsService {
|
|
|
253
281
|
}
|
|
254
282
|
}
|
|
255
283
|
}
|
|
256
|
-
if (
|
|
257
|
-
const record = await this.knex
|
|
258
|
-
.select('id')
|
|
259
|
-
.from('directus_fields')
|
|
260
|
-
.where({ collection, field: field.field })
|
|
261
|
-
.first();
|
|
284
|
+
if (hookAdjustedField.meta) {
|
|
262
285
|
if (record) {
|
|
263
286
|
await this.itemsService.updateOne(record.id, {
|
|
264
|
-
...
|
|
287
|
+
...hookAdjustedField.meta,
|
|
265
288
|
collection: collection,
|
|
266
|
-
field:
|
|
267
|
-
});
|
|
289
|
+
field: hookAdjustedField.field,
|
|
290
|
+
}, { emitEvents: false });
|
|
268
291
|
}
|
|
269
292
|
else {
|
|
270
293
|
await this.itemsService.createOne({
|
|
271
|
-
...
|
|
294
|
+
...hookAdjustedField.meta,
|
|
272
295
|
collection: collection,
|
|
273
|
-
field:
|
|
274
|
-
});
|
|
296
|
+
field: hookAdjustedField.field,
|
|
297
|
+
}, { emitEvents: false });
|
|
275
298
|
}
|
|
276
299
|
}
|
|
277
300
|
if (this.cache && env_1.default.CACHE_AUTO_PURGE) {
|
|
278
301
|
await this.cache.clear();
|
|
279
302
|
}
|
|
280
303
|
await this.systemCache.clear();
|
|
304
|
+
emitter_1.default.emitAction(`fields.update`, {
|
|
305
|
+
payload: hookAdjustedField,
|
|
306
|
+
keys: [hookAdjustedField.field],
|
|
307
|
+
collection: collection,
|
|
308
|
+
}, {
|
|
309
|
+
database: (0, database_1.default)(),
|
|
310
|
+
schema: this.schema,
|
|
311
|
+
accountability: this.accountability,
|
|
312
|
+
});
|
|
281
313
|
return field.field;
|
|
282
314
|
}
|
|
283
315
|
async deleteField(collection, field) {
|
|
@@ -402,8 +434,7 @@ class FieldsService {
|
|
|
402
434
|
column = table.timestamp(field.field, { useTz: true });
|
|
403
435
|
}
|
|
404
436
|
else if (field.type.startsWith('geometry')) {
|
|
405
|
-
|
|
406
|
-
column = helper.createColumn(table, field);
|
|
437
|
+
column = this.helpers.st.createColumn(table, field);
|
|
407
438
|
}
|
|
408
439
|
else {
|
|
409
440
|
// @ts-ignore
|
package/dist/services/files.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare class FilesService extends ItemsService {
|
|
|
9
9
|
uploadOne(stream: NodeJS.ReadableStream, data: Partial<File> & {
|
|
10
10
|
filename_download: string;
|
|
11
11
|
storage: string;
|
|
12
|
-
}, primaryKey?: PrimaryKey): Promise<PrimaryKey>;
|
|
12
|
+
}, primaryKey?: PrimaryKey, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
13
13
|
/**
|
|
14
14
|
* Import a single file from an external URL
|
|
15
15
|
*/
|
package/dist/services/files.js
CHANGED
|
@@ -26,7 +26,7 @@ class FilesService extends items_1.ItemsService {
|
|
|
26
26
|
/**
|
|
27
27
|
* Upload a single new file to the configured storage adapter
|
|
28
28
|
*/
|
|
29
|
-
async uploadOne(stream, data, primaryKey) {
|
|
29
|
+
async uploadOne(stream, data, primaryKey, opts) {
|
|
30
30
|
var _a, _b, _c, _d, _e, _f;
|
|
31
31
|
const payload = (0, lodash_1.clone)(data);
|
|
32
32
|
if ('folder' in payload === false) {
|
|
@@ -64,14 +64,20 @@ class FilesService extends items_1.ItemsService {
|
|
|
64
64
|
payload.filesize = size;
|
|
65
65
|
if (['image/jpeg', 'image/png', 'image/webp', 'image/gif', 'image/tiff'].includes(payload.type)) {
|
|
66
66
|
const buffer = await storage_1.default.disk(data.storage).getBuffer(payload.filename_disk);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
try {
|
|
68
|
+
const meta = await (0, sharp_1.default)(buffer.content, {}).metadata();
|
|
69
|
+
if (meta.orientation && meta.orientation >= 5) {
|
|
70
|
+
payload.height = meta.width;
|
|
71
|
+
payload.width = meta.height;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
payload.width = meta.width;
|
|
75
|
+
payload.height = meta.height;
|
|
76
|
+
}
|
|
71
77
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
catch (err) {
|
|
79
|
+
logger_1.default.warn(`Couldn't extract sharp metadata from file`);
|
|
80
|
+
logger_1.default.warn(err);
|
|
75
81
|
}
|
|
76
82
|
payload.metadata = {};
|
|
77
83
|
try {
|
|
@@ -95,7 +101,7 @@ class FilesService extends items_1.ItemsService {
|
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
103
|
catch (err) {
|
|
98
|
-
logger_1.default.warn(`Couldn't extract metadata from file`);
|
|
104
|
+
logger_1.default.warn(`Couldn't extract EXIF metadata from file`);
|
|
99
105
|
logger_1.default.warn(err);
|
|
100
106
|
}
|
|
101
107
|
}
|
|
@@ -109,15 +115,17 @@ class FilesService extends items_1.ItemsService {
|
|
|
109
115
|
if (this.cache && env_1.default.CACHE_AUTO_PURGE) {
|
|
110
116
|
await this.cache.clear();
|
|
111
117
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false) {
|
|
119
|
+
emitter_1.default.emitAction('files.upload', {
|
|
120
|
+
payload,
|
|
121
|
+
key: primaryKey,
|
|
122
|
+
collection: this.collection,
|
|
123
|
+
}, {
|
|
124
|
+
database: this.knex,
|
|
125
|
+
schema: this.schema,
|
|
126
|
+
accountability: this.accountability,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
121
129
|
return primaryKey;
|
|
122
130
|
}
|
|
123
131
|
/**
|
|
@@ -126,7 +134,7 @@ class FilesService extends items_1.ItemsService {
|
|
|
126
134
|
async importOne(importURL, body) {
|
|
127
135
|
var _a, _b, _c;
|
|
128
136
|
const fileCreatePermissions = (_b = (_a = this.accountability) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.find((permission) => permission.collection === 'directus_files' && permission.action === 'create');
|
|
129
|
-
if (((_c = this.accountability) === null || _c === void 0 ? void 0 : _c.admin) !== true && !fileCreatePermissions) {
|
|
137
|
+
if (this.accountability && ((_c = this.accountability) === null || _c === void 0 ? void 0 : _c.admin) !== true && !fileCreatePermissions) {
|
|
130
138
|
throw new exceptions_1.ForbiddenException();
|
|
131
139
|
}
|
|
132
140
|
let fileResponse;
|
package/dist/services/graphql.js
CHANGED
|
@@ -726,6 +726,9 @@ class GraphQLService {
|
|
|
726
726
|
args: {
|
|
727
727
|
groupBy: new graphql_1.GraphQLList(graphql_1.GraphQLString),
|
|
728
728
|
filter: ReadableCollectionFilterTypes[collection.collection],
|
|
729
|
+
limit: {
|
|
730
|
+
type: graphql_1.GraphQLInt,
|
|
731
|
+
},
|
|
729
732
|
search: {
|
|
730
733
|
type: graphql_1.GraphQLString,
|
|
731
734
|
},
|