directus 9.1.1 → 9.2.2
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/database/install.js +2 -4
- package/dist/cli/commands/schema/apply.js +26 -10
- 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/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.js +17 -2
- 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 +13 -11
- 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/utils/apply-query.js +9 -12
- package/dist/utils/apply-snapshot.js +27 -28
- 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
|
@@ -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.js
CHANGED
|
@@ -31,6 +31,7 @@ const database_1 = __importDefault(require("./database"));
|
|
|
31
31
|
const emitter_1 = __importDefault(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");
|
|
@@ -231,7 +232,14 @@ class ExtensionManager {
|
|
|
231
232
|
}
|
|
232
233
|
},
|
|
233
234
|
};
|
|
234
|
-
register(registerFunctions, {
|
|
235
|
+
register(registerFunctions, {
|
|
236
|
+
services,
|
|
237
|
+
exceptions: { ...exceptions, ...sharedExceptions },
|
|
238
|
+
env: env_1.default,
|
|
239
|
+
database: (0, database_1.default)(),
|
|
240
|
+
logger: logger_1.default,
|
|
241
|
+
getSchema: get_schema_1.getSchema,
|
|
242
|
+
});
|
|
235
243
|
}
|
|
236
244
|
registerEndpoint(endpoint, router) {
|
|
237
245
|
const endpointPath = path_1.default.resolve(endpoint.path, endpoint.entrypoint || '');
|
|
@@ -241,7 +249,14 @@ class ExtensionManager {
|
|
|
241
249
|
const routeName = typeof mod === 'function' ? endpoint.name : mod.id;
|
|
242
250
|
const scopedRouter = express_1.default.Router();
|
|
243
251
|
router.use(`/${routeName}`, scopedRouter);
|
|
244
|
-
register(scopedRouter, {
|
|
252
|
+
register(scopedRouter, {
|
|
253
|
+
services,
|
|
254
|
+
exceptions: { ...exceptions, ...sharedExceptions },
|
|
255
|
+
env: env_1.default,
|
|
256
|
+
database: (0, database_1.default)(),
|
|
257
|
+
logger: logger_1.default,
|
|
258
|
+
getSchema: get_schema_1.getSchema,
|
|
259
|
+
});
|
|
245
260
|
this.apiEndpoints.push({
|
|
246
261
|
path: endpointPath,
|
|
247
262
|
});
|
|
@@ -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) {
|
|
@@ -109,15 +109,17 @@ class FilesService extends items_1.ItemsService {
|
|
|
109
109
|
if (this.cache && env_1.default.CACHE_AUTO_PURGE) {
|
|
110
110
|
await this.cache.clear();
|
|
111
111
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
112
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false) {
|
|
113
|
+
emitter_1.default.emitAction('files.upload', {
|
|
114
|
+
payload,
|
|
115
|
+
key: primaryKey,
|
|
116
|
+
collection: this.collection,
|
|
117
|
+
}, {
|
|
118
|
+
database: this.knex,
|
|
119
|
+
schema: this.schema,
|
|
120
|
+
accountability: this.accountability,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
121
123
|
return primaryKey;
|
|
122
124
|
}
|
|
123
125
|
/**
|
|
@@ -126,7 +128,7 @@ class FilesService extends items_1.ItemsService {
|
|
|
126
128
|
async importOne(importURL, body) {
|
|
127
129
|
var _a, _b, _c;
|
|
128
130
|
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) {
|
|
131
|
+
if (this.accountability && ((_c = this.accountability) === null || _c === void 0 ? void 0 : _c.admin) !== true && !fileCreatePermissions) {
|
|
130
132
|
throw new exceptions_1.ForbiddenException();
|
|
131
133
|
}
|
|
132
134
|
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
|
},
|
package/dist/services/items.js
CHANGED
|
@@ -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:
|
|
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
|
|
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
|
|
234
|
-
|
|
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
|
-
|
|
251
|
+
async readMany(keys, query = {}, opts) {
|
|
252
|
+
var _a;
|
|
253
253
|
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
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);
|
package/dist/services/payload.js
CHANGED
|
@@ -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
|
|
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) =>
|
|
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) {
|
package/dist/services/users.js
CHANGED
|
@@ -19,6 +19,7 @@ const mail_1 = require("./mail");
|
|
|
19
19
|
const settings_1 = require("./settings");
|
|
20
20
|
const stall_1 = require("../utils/stall");
|
|
21
21
|
const perf_hooks_1 = require("perf_hooks");
|
|
22
|
+
const utils_2 = require("@directus/shared/utils");
|
|
22
23
|
class UsersService extends items_1.ItemsService {
|
|
23
24
|
constructor(options) {
|
|
24
25
|
super('directus_users', options);
|
|
@@ -251,7 +252,7 @@ class UsersService extends items_1.ItemsService {
|
|
|
251
252
|
}
|
|
252
253
|
const STALL_TIME = 500;
|
|
253
254
|
const timeStart = perf_hooks_1.performance.now();
|
|
254
|
-
const user = await this.knex.select('status').from('directus_users').where({ email }).first();
|
|
255
|
+
const user = await this.knex.select('status', 'password').from('directus_users').where({ email }).first();
|
|
255
256
|
if ((user === null || user === void 0 ? void 0 : user.status) !== 'active') {
|
|
256
257
|
await (0, stall_1.stall)(STALL_TIME, timeStart);
|
|
257
258
|
throw new exceptions_2.ForbiddenException();
|
|
@@ -261,7 +262,7 @@ class UsersService extends items_1.ItemsService {
|
|
|
261
262
|
knex: this.knex,
|
|
262
263
|
accountability: this.accountability,
|
|
263
264
|
});
|
|
264
|
-
const payload = { email, scope: 'password-reset' };
|
|
265
|
+
const payload = { email, scope: 'password-reset', hash: (0, utils_2.getSimpleHash)('' + user.password) };
|
|
265
266
|
const token = jsonwebtoken_1.default.sign(payload, env_1.default.SECRET, { expiresIn: '1d', issuer: 'directus' });
|
|
266
267
|
const acceptURL = url ? `${url}?token=${token}` : `${env_1.default.PUBLIC_URL}/admin/reset-password?token=${token}`;
|
|
267
268
|
const subjectLine = subject ? subject : 'Password Reset Request';
|
|
@@ -279,11 +280,12 @@ class UsersService extends items_1.ItemsService {
|
|
|
279
280
|
await (0, stall_1.stall)(STALL_TIME, timeStart);
|
|
280
281
|
}
|
|
281
282
|
async resetPassword(token, password) {
|
|
282
|
-
const { email, scope } = jsonwebtoken_1.default.verify(token, env_1.default.SECRET, { issuer: 'directus' });
|
|
283
|
-
if (scope !== 'password-reset')
|
|
283
|
+
const { email, scope, hash } = jsonwebtoken_1.default.verify(token, env_1.default.SECRET, { issuer: 'directus' });
|
|
284
|
+
if (scope !== 'password-reset' || !hash)
|
|
284
285
|
throw new exceptions_2.ForbiddenException();
|
|
285
|
-
|
|
286
|
-
|
|
286
|
+
await this.checkPasswordPolicy([password]);
|
|
287
|
+
const user = await this.knex.select('id', 'status', 'password').from('directus_users').where({ email }).first();
|
|
288
|
+
if ((user === null || user === void 0 ? void 0 : user.status) !== 'active' || hash !== (0, utils_2.getSimpleHash)('' + user.password)) {
|
|
287
289
|
throw new exceptions_2.ForbiddenException();
|
|
288
290
|
}
|
|
289
291
|
// Allow unauthenticated update
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
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 knex_1 = __importDefault(require("knex"));
|
|
7
|
+
const knex_mock_client_1 = require("knex-mock-client");
|
|
8
|
+
const run_1 = __importDefault(require("../../../database/migrations/run"));
|
|
9
|
+
describe('run', () => {
|
|
10
|
+
let db;
|
|
11
|
+
let tracker;
|
|
12
|
+
beforeAll(() => {
|
|
13
|
+
db = (0, knex_1.default)({ client: knex_mock_client_1.MockClient });
|
|
14
|
+
tracker = (0, knex_mock_client_1.getTracker)();
|
|
15
|
+
});
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
tracker.reset();
|
|
18
|
+
});
|
|
19
|
+
describe('when passed the argument up', () => {
|
|
20
|
+
it('returns "Nothing To Updage" if no directus_migrations', async () => {
|
|
21
|
+
// note the difference between an empty array and ['Empty']
|
|
22
|
+
tracker.on.select('directus_migrations').response(['Empty']);
|
|
23
|
+
await (0, run_1.default)(db, 'up').catch((e) => {
|
|
24
|
+
expect(e).toBeInstanceOf(Error);
|
|
25
|
+
expect(e.message).toBe('Nothing to upgrade');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|