@directus/api 11.1.0 → 12.0.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/app.js +3 -4
- package/dist/auth/auth.d.ts +4 -4
- package/dist/auth/auth.js +2 -2
- package/dist/auth/drivers/ldap.js +20 -17
- package/dist/auth/drivers/local.js +5 -5
- package/dist/auth/drivers/oauth2.js +16 -16
- package/dist/auth/drivers/openid.js +18 -17
- package/dist/auth/drivers/saml.js +6 -7
- package/dist/auth.js +3 -2
- package/dist/cache.js +3 -13
- package/dist/cli/utils/create-env/env-stub.liquid +5 -7
- package/dist/controllers/activity.js +7 -6
- package/dist/controllers/assets.js +25 -12
- package/dist/controllers/auth.js +8 -7
- package/dist/controllers/collections.js +4 -3
- package/dist/controllers/dashboards.js +5 -4
- package/dist/controllers/extensions.js +3 -3
- package/dist/controllers/fields.js +9 -8
- package/dist/controllers/files.js +11 -11
- package/dist/controllers/flows.js +5 -4
- package/dist/controllers/folders.js +5 -4
- package/dist/controllers/items.js +14 -13
- package/dist/controllers/not-found.js +2 -2
- package/dist/controllers/notifications.js +5 -4
- package/dist/controllers/operations.js +5 -4
- package/dist/controllers/panels.js +5 -4
- package/dist/controllers/permissions.js +5 -4
- package/dist/controllers/presets.js +5 -4
- package/dist/controllers/relations.js +6 -5
- package/dist/controllers/roles.js +5 -4
- package/dist/controllers/schema.js +8 -8
- package/dist/controllers/server.js +2 -2
- package/dist/controllers/settings.js +3 -2
- package/dist/controllers/shares.js +7 -6
- package/dist/controllers/translations.js +6 -5
- package/dist/controllers/users.js +22 -21
- package/dist/controllers/utils.js +10 -10
- package/dist/controllers/webhooks.js +5 -4
- package/dist/{exceptions/database → database/errors}/dialects/mssql.js +8 -18
- package/dist/{exceptions/database → database/errors}/dialects/mysql.js +9 -19
- package/dist/{exceptions/database → database/errors}/dialects/oracle.js +2 -2
- package/dist/{exceptions/database → database/errors}/dialects/postgres.js +7 -18
- package/dist/{exceptions/database → database/errors}/dialects/sqlite.js +7 -10
- package/dist/{exceptions/database → database/errors}/translate.js +1 -1
- package/dist/database/migrations/run.js +10 -1
- package/dist/env.js +6 -13
- package/dist/errors/codes.d.ts +29 -0
- package/dist/errors/codes.js +30 -0
- package/dist/errors/contains-null-values.d.ts +7 -0
- package/dist/errors/contains-null-values.js +4 -0
- package/dist/errors/content-too-large.d.ts +1 -0
- package/dist/errors/content-too-large.js +3 -0
- package/dist/errors/forbidden.d.ts +1 -0
- package/dist/errors/forbidden.js +3 -0
- package/dist/errors/hit-rate-limit.d.ts +6 -0
- package/dist/errors/hit-rate-limit.js +8 -0
- package/dist/errors/illegal-asset-transformation.d.ts +4 -0
- package/dist/errors/illegal-asset-transformation.js +3 -0
- package/dist/errors/index.d.ts +28 -0
- package/dist/errors/index.js +28 -0
- package/dist/errors/invalid-credentials.d.ts +1 -0
- package/dist/errors/invalid-credentials.js +3 -0
- package/dist/errors/invalid-foreign-key.d.ts +6 -0
- package/dist/errors/invalid-foreign-key.js +14 -0
- package/dist/errors/invalid-ip.d.ts +1 -0
- package/dist/errors/invalid-ip.js +3 -0
- package/dist/errors/invalid-otp.d.ts +1 -0
- package/dist/errors/invalid-otp.js +3 -0
- package/dist/errors/invalid-payload.d.ts +5 -0
- package/dist/errors/invalid-payload.js +4 -0
- package/dist/errors/invalid-provider-config.d.ts +5 -0
- package/dist/errors/invalid-provider-config.js +3 -0
- package/dist/errors/invalid-provider.d.ts +1 -0
- package/dist/errors/invalid-provider.js +3 -0
- package/dist/errors/invalid-query.d.ts +5 -0
- package/dist/errors/invalid-query.js +4 -0
- package/dist/errors/invalid-token.d.ts +1 -0
- package/dist/errors/invalid-token.js +3 -0
- package/dist/errors/method-not-allowed.d.ts +6 -0
- package/dist/errors/method-not-allowed.js +6 -0
- package/dist/errors/not-null-violation.d.ts +6 -0
- package/dist/errors/not-null-violation.js +14 -0
- package/dist/errors/range-not-satisfiable.d.ts +7 -0
- package/dist/errors/range-not-satisfiable.js +7 -0
- package/dist/errors/record-not-unique.d.ts +6 -0
- package/dist/errors/record-not-unique.js +14 -0
- package/dist/errors/route-not-found.d.ts +5 -0
- package/dist/errors/route-not-found.js +4 -0
- package/dist/errors/service-unavailable.d.ts +7 -0
- package/dist/errors/service-unavailable.js +4 -0
- package/dist/errors/token-expired.d.ts +1 -0
- package/dist/errors/token-expired.js +3 -0
- package/dist/errors/unexpected-response.d.ts +1 -0
- package/dist/errors/unexpected-response.js +3 -0
- package/dist/errors/unprocessable-content.d.ts +5 -0
- package/dist/errors/unprocessable-content.js +4 -0
- package/dist/errors/unsupported-media-type.d.ts +6 -0
- package/dist/errors/unsupported-media-type.js +4 -0
- package/dist/errors/user-suspended.d.ts +1 -0
- package/dist/errors/user-suspended.js +3 -0
- package/dist/errors/value-out-of-range.d.ts +6 -0
- package/dist/errors/value-out-of-range.js +14 -0
- package/dist/errors/value-too-long.d.ts +6 -0
- package/dist/errors/value-too-long.js +14 -0
- package/dist/extensions.js +0 -4
- package/dist/flows.js +6 -8
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/messenger.js +4 -4
- package/dist/middleware/authenticate.js +1 -1
- package/dist/middleware/check-ip.js +2 -2
- package/dist/middleware/collection-exists.js +2 -2
- package/dist/middleware/error-handler.js +7 -7
- package/dist/middleware/graphql.js +11 -9
- package/dist/middleware/rate-limiter-global.d.ts +2 -2
- package/dist/middleware/rate-limiter-global.js +2 -3
- package/dist/middleware/rate-limiter-ip.d.ts +2 -2
- package/dist/middleware/rate-limiter-ip.js +2 -3
- package/dist/middleware/validate-batch.js +3 -4
- package/dist/rate-limiter.js +2 -9
- package/dist/services/activity.js +3 -2
- package/dist/services/assets.js +9 -10
- package/dist/services/authentication.js +12 -11
- package/dist/services/authorization.d.ts +1 -1
- package/dist/services/authorization.js +16 -16
- package/dist/services/collections.js +17 -16
- package/dist/services/fields.js +16 -14
- package/dist/services/files.js +7 -6
- package/dist/services/graphql/errors/execution.d.ts +6 -0
- package/dist/services/graphql/errors/execution.js +2 -0
- package/dist/services/graphql/errors/index.d.ts +2 -0
- package/dist/services/graphql/errors/index.js +2 -0
- package/dist/services/graphql/errors/validation.d.ts +6 -0
- package/dist/services/graphql/errors/validation.js +2 -0
- package/dist/services/graphql/index.d.ts +2 -2
- package/dist/services/graphql/index.js +30 -12
- package/dist/services/graphql/utils/process-error.js +3 -3
- package/dist/services/import-export.js +7 -7
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/items.js +14 -13
- package/dist/services/mail/index.js +3 -3
- package/dist/services/meta.js +3 -3
- package/dist/services/payload.js +11 -7
- package/dist/services/relations.js +32 -22
- package/dist/services/revisions.js +3 -3
- package/dist/services/roles.js +10 -9
- package/dist/services/schema.js +5 -5
- package/dist/services/shares.js +4 -4
- package/dist/services/tfa.js +6 -6
- package/dist/services/translations.d.ts +2 -2
- package/dist/services/translations.js +4 -4
- package/dist/services/users.js +26 -29
- package/dist/services/utils.js +4 -4
- package/dist/synchronization.js +3 -3
- package/dist/types/items.d.ts +2 -2
- package/dist/utils/apply-diff.js +2 -2
- package/dist/utils/apply-query.js +17 -7
- package/dist/utils/get-accountability-for-role.js +1 -2
- package/dist/utils/get-accountability-for-token.js +3 -3
- package/dist/utils/get-column-path.js +5 -3
- package/dist/utils/get-column.js +3 -3
- package/dist/utils/get-service.d.ts +1 -1
- package/dist/utils/get-service.js +1 -1
- package/dist/utils/jwt.js +5 -5
- package/dist/utils/validate-diff.js +23 -9
- package/dist/utils/validate-keys.js +3 -3
- package/dist/utils/validate-query.d.ts +2 -0
- package/dist/utils/validate-query.js +27 -21
- package/dist/utils/validate-snapshot.js +11 -5
- package/dist/websocket/authenticate.js +12 -15
- package/dist/websocket/controllers/base.js +18 -15
- package/dist/websocket/controllers/graphql.js +2 -2
- package/dist/websocket/controllers/index.js +3 -7
- package/dist/websocket/controllers/rest.js +3 -3
- package/dist/websocket/{exceptions.d.ts → errors.d.ts} +5 -5
- package/dist/websocket/{exceptions.js → errors.js} +10 -10
- package/dist/websocket/handlers/items.js +5 -5
- package/dist/websocket/handlers/subscribe.js +8 -8
- package/package.json +15 -15
- package/dist/exceptions/content-too-large.d.ts +0 -4
- package/dist/exceptions/content-too-large.js +0 -6
- package/dist/exceptions/database/contains-null-values.d.ts +0 -9
- package/dist/exceptions/database/contains-null-values.js +0 -6
- package/dist/exceptions/database/invalid-foreign-key.d.ts +0 -10
- package/dist/exceptions/database/invalid-foreign-key.js +0 -11
- package/dist/exceptions/database/not-null-violation.d.ts +0 -9
- package/dist/exceptions/database/not-null-violation.js +0 -6
- package/dist/exceptions/database/record-not-unique.d.ts +0 -10
- package/dist/exceptions/database/record-not-unique.js +0 -11
- package/dist/exceptions/database/value-out-of-range.d.ts +0 -10
- package/dist/exceptions/database/value-out-of-range.js +0 -11
- package/dist/exceptions/database/value-too-long.d.ts +0 -9
- package/dist/exceptions/database/value-too-long.js +0 -11
- package/dist/exceptions/forbidden.d.ts +0 -6
- package/dist/exceptions/forbidden.js +0 -13
- package/dist/exceptions/graphql-validation.d.ts +0 -4
- package/dist/exceptions/graphql-validation.js +0 -6
- package/dist/exceptions/hit-rate-limit.d.ts +0 -9
- package/dist/exceptions/hit-rate-limit.js +0 -6
- package/dist/exceptions/illegal-asset-transformation.d.ts +0 -4
- package/dist/exceptions/illegal-asset-transformation.js +0 -6
- package/dist/exceptions/index.d.ts +0 -21
- package/dist/exceptions/index.js +0 -21
- package/dist/exceptions/invalid-config.d.ts +0 -4
- package/dist/exceptions/invalid-config.js +0 -6
- package/dist/exceptions/invalid-credentials.d.ts +0 -4
- package/dist/exceptions/invalid-credentials.js +0 -6
- package/dist/exceptions/invalid-ip.d.ts +0 -4
- package/dist/exceptions/invalid-ip.js +0 -6
- package/dist/exceptions/invalid-otp.d.ts +0 -4
- package/dist/exceptions/invalid-otp.js +0 -6
- package/dist/exceptions/invalid-payload.d.ts +0 -4
- package/dist/exceptions/invalid-payload.js +0 -6
- package/dist/exceptions/invalid-provider.d.ts +0 -4
- package/dist/exceptions/invalid-provider.js +0 -6
- package/dist/exceptions/invalid-query.d.ts +0 -4
- package/dist/exceptions/invalid-query.js +0 -6
- package/dist/exceptions/invalid-token.d.ts +0 -4
- package/dist/exceptions/invalid-token.js +0 -6
- package/dist/exceptions/method-not-allowed.d.ts +0 -8
- package/dist/exceptions/method-not-allowed.js +0 -6
- package/dist/exceptions/range-not-satisfiable.d.ts +0 -5
- package/dist/exceptions/range-not-satisfiable.js +0 -9
- package/dist/exceptions/route-not-found.d.ts +0 -4
- package/dist/exceptions/route-not-found.js +0 -6
- package/dist/exceptions/service-unavailable.d.ts +0 -9
- package/dist/exceptions/service-unavailable.js +0 -6
- package/dist/exceptions/token-expired.d.ts +0 -4
- package/dist/exceptions/token-expired.js +0 -6
- package/dist/exceptions/unexpected-response.d.ts +0 -4
- package/dist/exceptions/unexpected-response.js +0 -6
- package/dist/exceptions/unprocessable-entity.d.ts +0 -4
- package/dist/exceptions/unprocessable-entity.js +0 -6
- package/dist/exceptions/unsupported-media-type.d.ts +0 -4
- package/dist/exceptions/unsupported-media-type.js +0 -6
- package/dist/exceptions/user-suspended.d.ts +0 -4
- package/dist/exceptions/user-suspended.js +0 -6
- /package/dist/{exceptions/database → database/errors}/dialects/mssql.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/mysql.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/oracle.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/postgres.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/sqlite.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/types.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/types.js +0 -0
- /package/dist/{exceptions/database → database/errors}/translate.d.ts +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Action } from '@directus/constants';
|
|
2
|
+
import { isDirectusError } from '@directus/errors';
|
|
2
3
|
import express from 'express';
|
|
3
4
|
import Joi from 'joi';
|
|
4
|
-
import {
|
|
5
|
+
import { ErrorCode, ForbiddenError, InvalidPayloadError } from '../errors/index.js';
|
|
5
6
|
import { respond } from '../middleware/respond.js';
|
|
6
7
|
import useCollection from '../middleware/use-collection.js';
|
|
7
8
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -62,7 +63,7 @@ router.post('/comment', asyncHandler(async (req, res, next) => {
|
|
|
62
63
|
});
|
|
63
64
|
const { error } = createCommentSchema.validate(req.body);
|
|
64
65
|
if (error) {
|
|
65
|
-
throw new
|
|
66
|
+
throw new InvalidPayloadError({ reason: error.message });
|
|
66
67
|
}
|
|
67
68
|
const primaryKey = await service.createOne({
|
|
68
69
|
...req.body,
|
|
@@ -79,7 +80,7 @@ router.post('/comment', asyncHandler(async (req, res, next) => {
|
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
82
|
catch (error) {
|
|
82
|
-
if (error
|
|
83
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
83
84
|
return next();
|
|
84
85
|
}
|
|
85
86
|
throw error;
|
|
@@ -96,7 +97,7 @@ router.patch('/comment/:pk', asyncHandler(async (req, res, next) => {
|
|
|
96
97
|
});
|
|
97
98
|
const { error } = updateCommentSchema.validate(req.body);
|
|
98
99
|
if (error) {
|
|
99
|
-
throw new
|
|
100
|
+
throw new InvalidPayloadError({ reason: error.message });
|
|
100
101
|
}
|
|
101
102
|
const primaryKey = await service.updateOne(req.params['pk'], req.body);
|
|
102
103
|
try {
|
|
@@ -106,7 +107,7 @@ router.patch('/comment/:pk', asyncHandler(async (req, res, next) => {
|
|
|
106
107
|
};
|
|
107
108
|
}
|
|
108
109
|
catch (error) {
|
|
109
|
-
if (error
|
|
110
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
110
111
|
return next();
|
|
111
112
|
}
|
|
112
113
|
throw error;
|
|
@@ -123,7 +124,7 @@ router.delete('/comment/:pk', asyncHandler(async (req, _res, next) => {
|
|
|
123
124
|
});
|
|
124
125
|
const item = await adminService.readOne(req.params['pk'], { fields: ['action'] });
|
|
125
126
|
if (!item || item['action'] !== Action.COMMENT) {
|
|
126
|
-
throw new
|
|
127
|
+
throw new ForbiddenError();
|
|
127
128
|
}
|
|
128
129
|
await service.deleteOne(req.params['pk']);
|
|
129
130
|
return next();
|
|
@@ -5,7 +5,7 @@ import { merge, pick } from 'lodash-es';
|
|
|
5
5
|
import { ASSET_TRANSFORM_QUERY_KEYS, SYSTEM_ASSET_ALLOW_LIST } from '../constants.js';
|
|
6
6
|
import getDatabase from '../database/index.js';
|
|
7
7
|
import env from '../env.js';
|
|
8
|
-
import {
|
|
8
|
+
import { InvalidQueryError, RangeNotSatisfiableError } from '../errors/index.js';
|
|
9
9
|
import logger from '../logger.js';
|
|
10
10
|
import useCollection from '../middleware/use-collection.js';
|
|
11
11
|
import { AssetsService } from '../services/assets.js';
|
|
@@ -33,7 +33,9 @@ asyncHandler(async (req, res, next) => {
|
|
|
33
33
|
const assetSettings = savedAssetSettings || defaults;
|
|
34
34
|
const transformation = pick(req.query, ASSET_TRANSFORM_QUERY_KEYS);
|
|
35
35
|
if ('key' in transformation && Object.keys(transformation).length > 1) {
|
|
36
|
-
throw new
|
|
36
|
+
throw new InvalidQueryError({
|
|
37
|
+
reason: `You can't combine the "key" query parameter with any other transformation`,
|
|
38
|
+
});
|
|
37
39
|
}
|
|
38
40
|
if ('transforms' in transformation) {
|
|
39
41
|
let transforms;
|
|
@@ -42,21 +44,29 @@ asyncHandler(async (req, res, next) => {
|
|
|
42
44
|
transforms = parseJSON(transformation['transforms']);
|
|
43
45
|
}
|
|
44
46
|
catch {
|
|
45
|
-
throw new
|
|
47
|
+
throw new InvalidQueryError({
|
|
48
|
+
reason: `"transforms" Parameter needs to be a JSON array of allowed transformations`,
|
|
49
|
+
});
|
|
46
50
|
}
|
|
47
51
|
// Check if it is actually an array.
|
|
48
52
|
if (!Array.isArray(transforms)) {
|
|
49
|
-
throw new
|
|
53
|
+
throw new InvalidQueryError({
|
|
54
|
+
reason: `"transforms" Parameter needs to be a JSON array of allowed transformations`,
|
|
55
|
+
});
|
|
50
56
|
}
|
|
51
57
|
// Check against ASSETS_TRANSFORM_MAX_OPERATIONS
|
|
52
58
|
if (transforms.length > Number(env['ASSETS_TRANSFORM_MAX_OPERATIONS'])) {
|
|
53
|
-
throw new
|
|
59
|
+
throw new InvalidQueryError({
|
|
60
|
+
reason: `"transforms" Parameter is only allowed ${env['ASSETS_TRANSFORM_MAX_OPERATIONS']} transformations`,
|
|
61
|
+
});
|
|
54
62
|
}
|
|
55
63
|
// Check the transformations are valid
|
|
56
64
|
transforms.forEach((transform) => {
|
|
57
65
|
const name = transform[0];
|
|
58
66
|
if (!TransformationMethods.includes(name)) {
|
|
59
|
-
throw new
|
|
67
|
+
throw new InvalidQueryError({
|
|
68
|
+
reason: `"transforms" Parameter does not allow "${name}" as a transformation`,
|
|
69
|
+
});
|
|
60
70
|
}
|
|
61
71
|
});
|
|
62
72
|
transformation['transforms'] = transforms;
|
|
@@ -75,19 +85,19 @@ asyncHandler(async (req, res, next) => {
|
|
|
75
85
|
}
|
|
76
86
|
if (assetSettings.storage_asset_transform === 'all') {
|
|
77
87
|
if (transformation['key'] && allKeys.includes(transformation['key']) === false) {
|
|
78
|
-
throw new
|
|
88
|
+
throw new InvalidQueryError({ reason: `Key "${transformation['key']}" isn't configured` });
|
|
79
89
|
}
|
|
80
90
|
return next();
|
|
81
91
|
}
|
|
82
92
|
else if (assetSettings.storage_asset_transform === 'presets') {
|
|
83
93
|
if (allKeys.includes(transformation['key']))
|
|
84
94
|
return next();
|
|
85
|
-
throw new
|
|
95
|
+
throw new InvalidQueryError({ reason: `Only configured presets can be used in asset generation` });
|
|
86
96
|
}
|
|
87
97
|
else {
|
|
88
98
|
if (transformation['key'] && systemKeys.includes(transformation['key']))
|
|
89
99
|
return next();
|
|
90
|
-
throw new
|
|
100
|
+
throw new InvalidQueryError({ reason: `Dynamic asset generation has been disabled for this project` });
|
|
91
101
|
}
|
|
92
102
|
}), asyncHandler(async (req, res, next) => {
|
|
93
103
|
const helmet = await import('helmet');
|
|
@@ -123,16 +133,19 @@ asyncHandler(async (req, res) => {
|
|
|
123
133
|
if (req.headers.range) {
|
|
124
134
|
const rangeParts = /bytes=([0-9]*)-([0-9]*)/.exec(req.headers.range);
|
|
125
135
|
if (rangeParts && rangeParts.length > 1) {
|
|
126
|
-
range = {
|
|
136
|
+
range = {
|
|
137
|
+
start: undefined,
|
|
138
|
+
end: undefined,
|
|
139
|
+
};
|
|
127
140
|
if (rangeParts[1]) {
|
|
128
141
|
range.start = Number(rangeParts[1]);
|
|
129
142
|
if (Number.isNaN(range.start))
|
|
130
|
-
throw new
|
|
143
|
+
throw new RangeNotSatisfiableError({ range });
|
|
131
144
|
}
|
|
132
145
|
if (rangeParts[2]) {
|
|
133
146
|
range.end = Number(rangeParts[2]);
|
|
134
147
|
if (Number.isNaN(range.end))
|
|
135
|
-
throw new
|
|
148
|
+
throw new RangeNotSatisfiableError({ range });
|
|
136
149
|
}
|
|
137
150
|
}
|
|
138
151
|
}
|
package/dist/controllers/auth.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
1
2
|
import { Router } from 'express';
|
|
2
3
|
import { createLDAPAuthRouter, createLocalAuthRouter, createOAuth2AuthRouter, createOpenIDAuthRouter, createSAMLAuthRouter, } from '../auth/drivers/index.js';
|
|
3
4
|
import { COOKIE_OPTIONS, DEFAULT_AUTH_PROVIDER } from '../constants.js';
|
|
4
5
|
import env from '../env.js';
|
|
5
|
-
import {
|
|
6
|
+
import { ErrorCode, InvalidPayloadError } from '../errors/index.js';
|
|
6
7
|
import logger from '../logger.js';
|
|
7
8
|
import { respond } from '../middleware/respond.js';
|
|
8
9
|
import { AuthenticationService } from '../services/authentication.js';
|
|
@@ -57,7 +58,7 @@ router.post('/refresh', asyncHandler(async (req, res, next) => {
|
|
|
57
58
|
});
|
|
58
59
|
const currentRefreshToken = req.body.refresh_token || req.cookies[env['REFRESH_TOKEN_COOKIE_NAME']];
|
|
59
60
|
if (!currentRefreshToken) {
|
|
60
|
-
throw new
|
|
61
|
+
throw new InvalidPayloadError({ reason: `"refresh_token" is required in either the JSON payload or Cookie` });
|
|
61
62
|
}
|
|
62
63
|
const mode = req.body.mode || (req.body.refresh_token ? 'json' : 'cookie');
|
|
63
64
|
const { accessToken, refreshToken, expires } = await authenticationService.refresh(currentRefreshToken);
|
|
@@ -90,7 +91,7 @@ router.post('/logout', asyncHandler(async (req, res, next) => {
|
|
|
90
91
|
});
|
|
91
92
|
const currentRefreshToken = req.body.refresh_token || req.cookies[env['REFRESH_TOKEN_COOKIE_NAME']];
|
|
92
93
|
if (!currentRefreshToken) {
|
|
93
|
-
throw new
|
|
94
|
+
throw new InvalidPayloadError({ reason: `"refresh_token" is required in either the JSON payload or Cookie` });
|
|
94
95
|
}
|
|
95
96
|
await authenticationService.logout(currentRefreshToken);
|
|
96
97
|
if (req.cookies[env['REFRESH_TOKEN_COOKIE_NAME']]) {
|
|
@@ -105,7 +106,7 @@ router.post('/logout', asyncHandler(async (req, res, next) => {
|
|
|
105
106
|
}), respond);
|
|
106
107
|
router.post('/password/request', asyncHandler(async (req, _res, next) => {
|
|
107
108
|
if (typeof req.body.email !== 'string') {
|
|
108
|
-
throw new
|
|
109
|
+
throw new InvalidPayloadError({ reason: `"email" field is required` });
|
|
109
110
|
}
|
|
110
111
|
const accountability = {
|
|
111
112
|
ip: getIPFromReq(req),
|
|
@@ -123,7 +124,7 @@ router.post('/password/request', asyncHandler(async (req, _res, next) => {
|
|
|
123
124
|
return next();
|
|
124
125
|
}
|
|
125
126
|
catch (err) {
|
|
126
|
-
if (err
|
|
127
|
+
if (isDirectusError(err, ErrorCode.InvalidPayload)) {
|
|
127
128
|
throw err;
|
|
128
129
|
}
|
|
129
130
|
else {
|
|
@@ -134,10 +135,10 @@ router.post('/password/request', asyncHandler(async (req, _res, next) => {
|
|
|
134
135
|
}), respond);
|
|
135
136
|
router.post('/password/reset', asyncHandler(async (req, _res, next) => {
|
|
136
137
|
if (typeof req.body.token !== 'string') {
|
|
137
|
-
throw new
|
|
138
|
+
throw new InvalidPayloadError({ reason: `"token" field is required` });
|
|
138
139
|
}
|
|
139
140
|
if (typeof req.body.password !== 'string') {
|
|
140
|
-
throw new
|
|
141
|
+
throw new InvalidPayloadError({ reason: `"password" field is required` });
|
|
141
142
|
}
|
|
142
143
|
const accountability = {
|
|
143
144
|
ip: getIPFromReq(req),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
1
2
|
import { Router } from 'express';
|
|
2
|
-
import {
|
|
3
|
+
import { ErrorCode } from '../errors/index.js';
|
|
3
4
|
import { respond } from '../middleware/respond.js';
|
|
4
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
5
6
|
import { CollectionsService } from '../services/collections.js';
|
|
@@ -65,7 +66,7 @@ router.patch('/', asyncHandler(async (req, res, next) => {
|
|
|
65
66
|
res.locals['payload'] = { data: collections || null };
|
|
66
67
|
}
|
|
67
68
|
catch (error) {
|
|
68
|
-
if (error
|
|
69
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
69
70
|
return next();
|
|
70
71
|
}
|
|
71
72
|
throw error;
|
|
@@ -83,7 +84,7 @@ router.patch('/:collection', asyncHandler(async (req, res, next) => {
|
|
|
83
84
|
res.locals['payload'] = { data: collection || null };
|
|
84
85
|
}
|
|
85
86
|
catch (error) {
|
|
86
|
-
if (error
|
|
87
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
87
88
|
return next();
|
|
88
89
|
}
|
|
89
90
|
throw error;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
1
2
|
import express from 'express';
|
|
2
|
-
import {
|
|
3
|
+
import { ErrorCode } from '../errors/index.js';
|
|
3
4
|
import { respond } from '../middleware/respond.js';
|
|
4
5
|
import useCollection from '../middleware/use-collection.js';
|
|
5
6
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -34,7 +35,7 @@ router.post('/', asyncHandler(async (req, res, next) => {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
catch (error) {
|
|
37
|
-
if (error
|
|
38
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
38
39
|
return next();
|
|
39
40
|
}
|
|
40
41
|
throw error;
|
|
@@ -87,7 +88,7 @@ router.patch('/', validateBatch('update'), asyncHandler(async (req, res, next) =
|
|
|
87
88
|
res.locals['payload'] = { data: result };
|
|
88
89
|
}
|
|
89
90
|
catch (error) {
|
|
90
|
-
if (error
|
|
91
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
91
92
|
return next();
|
|
92
93
|
}
|
|
93
94
|
throw error;
|
|
@@ -105,7 +106,7 @@ router.patch('/:pk', asyncHandler(async (req, res, next) => {
|
|
|
105
106
|
res.locals['payload'] = { data: item || null };
|
|
106
107
|
}
|
|
107
108
|
catch (error) {
|
|
108
|
-
if (error
|
|
109
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
109
110
|
return next();
|
|
110
111
|
}
|
|
111
112
|
throw error;
|
|
@@ -2,7 +2,7 @@ import { EXTENSION_TYPES } from '@directus/constants';
|
|
|
2
2
|
import { depluralize, isIn } from '@directus/utils';
|
|
3
3
|
import { Router } from 'express';
|
|
4
4
|
import env from '../env.js';
|
|
5
|
-
import {
|
|
5
|
+
import { RouteNotFoundError } from '../errors/index.js';
|
|
6
6
|
import { getExtensionManager } from '../extensions.js';
|
|
7
7
|
import { respond } from '../middleware/respond.js';
|
|
8
8
|
import asyncHandler from '../utils/async-handler.js';
|
|
@@ -12,7 +12,7 @@ const router = Router();
|
|
|
12
12
|
router.get('/:type', asyncHandler(async (req, res, next) => {
|
|
13
13
|
const type = depluralize(req.params['type']);
|
|
14
14
|
if (!isIn(type, EXTENSION_TYPES)) {
|
|
15
|
-
throw new
|
|
15
|
+
throw new RouteNotFoundError({ path: req.path });
|
|
16
16
|
}
|
|
17
17
|
const extensionManager = getExtensionManager();
|
|
18
18
|
const extensions = extensionManager.getExtensionsList(type);
|
|
@@ -32,7 +32,7 @@ router.get('/sources/:chunk', asyncHandler(async (req, res) => {
|
|
|
32
32
|
source = extensionManager.getAppExtensionChunk(chunk);
|
|
33
33
|
}
|
|
34
34
|
if (source === null) {
|
|
35
|
-
throw new
|
|
35
|
+
throw new RouteNotFoundError({ path: req.path });
|
|
36
36
|
}
|
|
37
37
|
res.setHeader('Content-Type', 'application/javascript; charset=UTF-8');
|
|
38
38
|
res.setHeader('Cache-Control', getCacheControlHeader(req, getMilliseconds(env['EXTENSIONS_CACHE_TTL']), false, false));
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { TYPES } from '@directus/constants';
|
|
2
|
+
import { isDirectusError } from '@directus/errors';
|
|
2
3
|
import { Router } from 'express';
|
|
3
4
|
import Joi from 'joi';
|
|
4
5
|
import { ALIAS_TYPES } from '../constants.js';
|
|
5
|
-
import {
|
|
6
|
+
import { ErrorCode, InvalidPayloadError } from '../errors/index.js';
|
|
6
7
|
import validateCollection from '../middleware/collection-exists.js';
|
|
7
8
|
import { respond } from '../middleware/respond.js';
|
|
8
9
|
import useCollection from '../middleware/use-collection.js';
|
|
@@ -60,7 +61,7 @@ router.post('/:collection', validateCollection, asyncHandler(async (req, res, ne
|
|
|
60
61
|
});
|
|
61
62
|
const { error } = newFieldSchema.validate(req.body);
|
|
62
63
|
if (error) {
|
|
63
|
-
throw new
|
|
64
|
+
throw new InvalidPayloadError({ reason: error.message });
|
|
64
65
|
}
|
|
65
66
|
const field = req.body;
|
|
66
67
|
await service.createField(req.params['collection'], field);
|
|
@@ -69,7 +70,7 @@ router.post('/:collection', validateCollection, asyncHandler(async (req, res, ne
|
|
|
69
70
|
res.locals['payload'] = { data: createdField || null };
|
|
70
71
|
}
|
|
71
72
|
catch (error) {
|
|
72
|
-
if (error
|
|
73
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
73
74
|
return next();
|
|
74
75
|
}
|
|
75
76
|
throw error;
|
|
@@ -82,7 +83,7 @@ router.patch('/:collection', validateCollection, asyncHandler(async (req, res, n
|
|
|
82
83
|
schema: req.schema,
|
|
83
84
|
});
|
|
84
85
|
if (Array.isArray(req.body) === false) {
|
|
85
|
-
throw new
|
|
86
|
+
throw new InvalidPayloadError({ reason: 'Submitted body has to be an array' });
|
|
86
87
|
}
|
|
87
88
|
for (const field of req.body) {
|
|
88
89
|
await service.updateField(req.params['collection'], field);
|
|
@@ -96,7 +97,7 @@ router.patch('/:collection', validateCollection, asyncHandler(async (req, res, n
|
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
catch (error) {
|
|
99
|
-
if (error
|
|
100
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
100
101
|
return next();
|
|
101
102
|
}
|
|
102
103
|
throw error;
|
|
@@ -123,10 +124,10 @@ router.patch('/:collection/:field', validateCollection, asyncHandler(async (req,
|
|
|
123
124
|
});
|
|
124
125
|
const { error } = updateSchema.validate(req.body);
|
|
125
126
|
if (error) {
|
|
126
|
-
throw new
|
|
127
|
+
throw new InvalidPayloadError({ reason: error.message });
|
|
127
128
|
}
|
|
128
129
|
if (req.body.schema && !req.body.type) {
|
|
129
|
-
throw new
|
|
130
|
+
throw new InvalidPayloadError({ reason: `You need to provide "type" when providing "schema"` });
|
|
130
131
|
}
|
|
131
132
|
const fieldData = req.body;
|
|
132
133
|
if (!fieldData.field)
|
|
@@ -137,7 +138,7 @@ router.patch('/:collection/:field', validateCollection, asyncHandler(async (req,
|
|
|
137
138
|
res.locals['payload'] = { data: updatedField || null };
|
|
138
139
|
}
|
|
139
140
|
catch (error) {
|
|
140
|
-
if (error
|
|
141
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
141
142
|
return next();
|
|
142
143
|
}
|
|
143
144
|
throw error;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
1
2
|
import formatTitle from '@directus/format-title';
|
|
2
3
|
import { toArray } from '@directus/utils';
|
|
3
4
|
import Busboy from 'busboy';
|
|
@@ -7,8 +8,7 @@ import Joi from 'joi';
|
|
|
7
8
|
import { minimatch } from 'minimatch';
|
|
8
9
|
import path from 'path';
|
|
9
10
|
import env from '../env.js';
|
|
10
|
-
import {
|
|
11
|
-
import { ForbiddenException, InvalidPayloadException } from '../exceptions/index.js';
|
|
11
|
+
import { ContentTooLargeError, ErrorCode, InvalidPayloadError } from '../errors/index.js';
|
|
12
12
|
import { respond } from '../middleware/respond.js';
|
|
13
13
|
import useCollection from '../middleware/use-collection.js';
|
|
14
14
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -64,12 +64,12 @@ export const multipartHandler = (req, res, next) => {
|
|
|
64
64
|
});
|
|
65
65
|
busboy.on('file', async (_fieldname, fileStream, { filename, mimeType }) => {
|
|
66
66
|
if (!filename) {
|
|
67
|
-
return busboy.emit('error', new
|
|
67
|
+
return busboy.emit('error', new InvalidPayloadError({ reason: `File is missing filename` }));
|
|
68
68
|
}
|
|
69
69
|
const allowedPatterns = toArray(env['FILES_MIME_TYPE_ALLOW_LIST']);
|
|
70
70
|
const mimeTypeAllowed = allowedPatterns.some((pattern) => minimatch(mimeType, pattern));
|
|
71
71
|
if (mimeTypeAllowed === false) {
|
|
72
|
-
return busboy.emit('error', new
|
|
72
|
+
return busboy.emit('error', new InvalidPayloadError({ reason: `File is of invalid content type` }));
|
|
73
73
|
}
|
|
74
74
|
fileCount++;
|
|
75
75
|
if (!existingPrimaryKey) {
|
|
@@ -86,7 +86,7 @@ export const multipartHandler = (req, res, next) => {
|
|
|
86
86
|
// Clear the payload for the next to-be-uploaded file
|
|
87
87
|
payload = {};
|
|
88
88
|
fileStream.on('limit', () => {
|
|
89
|
-
const error = new
|
|
89
|
+
const error = new ContentTooLargeError();
|
|
90
90
|
next(error);
|
|
91
91
|
});
|
|
92
92
|
try {
|
|
@@ -109,7 +109,7 @@ export const multipartHandler = (req, res, next) => {
|
|
|
109
109
|
function tryDone() {
|
|
110
110
|
if (savedFiles.length === fileCount) {
|
|
111
111
|
if (fileCount === 0) {
|
|
112
|
-
return next(new
|
|
112
|
+
return next(new InvalidPayloadError({ reason: `No files were included in the body` }));
|
|
113
113
|
}
|
|
114
114
|
res.locals['savedFiles'] = savedFiles;
|
|
115
115
|
return next();
|
|
@@ -144,7 +144,7 @@ router.post('/', asyncHandler(multipartHandler), asyncHandler(async (req, res, n
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
catch (error) {
|
|
147
|
-
if (error
|
|
147
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
148
148
|
return next();
|
|
149
149
|
}
|
|
150
150
|
throw error;
|
|
@@ -158,7 +158,7 @@ const importSchema = Joi.object({
|
|
|
158
158
|
router.post('/import', asyncHandler(async (req, res, next) => {
|
|
159
159
|
const { error } = importSchema.validate(req.body);
|
|
160
160
|
if (error) {
|
|
161
|
-
throw new
|
|
161
|
+
throw new InvalidPayloadError({ reason: error.message });
|
|
162
162
|
}
|
|
163
163
|
const service = new FilesService({
|
|
164
164
|
accountability: req.accountability,
|
|
@@ -170,7 +170,7 @@ router.post('/import', asyncHandler(async (req, res, next) => {
|
|
|
170
170
|
res.locals['payload'] = { data: record || null };
|
|
171
171
|
}
|
|
172
172
|
catch (error) {
|
|
173
|
-
if (error
|
|
173
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
174
174
|
return next();
|
|
175
175
|
}
|
|
176
176
|
throw error;
|
|
@@ -232,7 +232,7 @@ router.patch('/', validateBatch('update'), asyncHandler(async (req, res, next) =
|
|
|
232
232
|
res.locals['payload'] = { data: result || null };
|
|
233
233
|
}
|
|
234
234
|
catch (error) {
|
|
235
|
-
if (error
|
|
235
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
236
236
|
return next();
|
|
237
237
|
}
|
|
238
238
|
throw error;
|
|
@@ -250,7 +250,7 @@ router.patch('/:pk', asyncHandler(multipartHandler), asyncHandler(async (req, re
|
|
|
250
250
|
res.locals['payload'] = { data: record || null };
|
|
251
251
|
}
|
|
252
252
|
catch (error) {
|
|
253
|
-
if (error
|
|
253
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
254
254
|
return next();
|
|
255
255
|
}
|
|
256
256
|
throw error;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
1
2
|
import express from 'express';
|
|
2
3
|
import { UUID_REGEX } from '../constants.js';
|
|
3
|
-
import {
|
|
4
|
+
import { ErrorCode } from '../errors/index.js';
|
|
4
5
|
import { getFlowManager } from '../flows.js';
|
|
5
6
|
import { respond } from '../middleware/respond.js';
|
|
6
7
|
import useCollection from '../middleware/use-collection.js';
|
|
@@ -56,7 +57,7 @@ router.post('/', asyncHandler(async (req, res, next) => {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
catch (error) {
|
|
59
|
-
if (error
|
|
60
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
60
61
|
return next();
|
|
61
62
|
}
|
|
62
63
|
throw error;
|
|
@@ -109,7 +110,7 @@ router.patch('/', validateBatch('update'), asyncHandler(async (req, res, next) =
|
|
|
109
110
|
res.locals['payload'] = { data: result };
|
|
110
111
|
}
|
|
111
112
|
catch (error) {
|
|
112
|
-
if (error
|
|
113
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
113
114
|
return next();
|
|
114
115
|
}
|
|
115
116
|
throw error;
|
|
@@ -127,7 +128,7 @@ router.patch('/:pk', asyncHandler(async (req, res, next) => {
|
|
|
127
128
|
res.locals['payload'] = { data: item || null };
|
|
128
129
|
}
|
|
129
130
|
catch (error) {
|
|
130
|
-
if (error
|
|
131
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
131
132
|
return next();
|
|
132
133
|
}
|
|
133
134
|
throw error;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
1
2
|
import express from 'express';
|
|
2
|
-
import {
|
|
3
|
+
import { ErrorCode } from '../errors/index.js';
|
|
3
4
|
import { respond } from '../middleware/respond.js';
|
|
4
5
|
import useCollection from '../middleware/use-collection.js';
|
|
5
6
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -34,7 +35,7 @@ router.post('/', asyncHandler(async (req, res, next) => {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
catch (error) {
|
|
37
|
-
if (error
|
|
38
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
38
39
|
return next();
|
|
39
40
|
}
|
|
40
41
|
throw error;
|
|
@@ -96,7 +97,7 @@ router.patch('/', validateBatch('update'), asyncHandler(async (req, res, next) =
|
|
|
96
97
|
res.locals['payload'] = { data: result || null };
|
|
97
98
|
}
|
|
98
99
|
catch (error) {
|
|
99
|
-
if (error
|
|
100
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
100
101
|
return next();
|
|
101
102
|
}
|
|
102
103
|
throw error;
|
|
@@ -114,7 +115,7 @@ router.patch('/:pk', asyncHandler(async (req, res, next) => {
|
|
|
114
115
|
res.locals['payload'] = { data: record || null };
|
|
115
116
|
}
|
|
116
117
|
catch (error) {
|
|
117
|
-
if (error
|
|
118
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
118
119
|
return next();
|
|
119
120
|
}
|
|
120
121
|
throw error;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
1
2
|
import express from 'express';
|
|
2
|
-
import {
|
|
3
|
+
import { ErrorCode, ForbiddenError, RouteNotFoundError } from '../errors/index.js';
|
|
3
4
|
import collectionExists from '../middleware/collection-exists.js';
|
|
4
5
|
import { respond } from '../middleware/respond.js';
|
|
5
6
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -10,9 +11,9 @@ import { sanitizeQuery } from '../utils/sanitize-query.js';
|
|
|
10
11
|
const router = express.Router();
|
|
11
12
|
router.post('/:collection', collectionExists, asyncHandler(async (req, res, next) => {
|
|
12
13
|
if (req.params['collection'].startsWith('directus_'))
|
|
13
|
-
throw new
|
|
14
|
+
throw new ForbiddenError();
|
|
14
15
|
if (req.singleton) {
|
|
15
|
-
throw new
|
|
16
|
+
throw new RouteNotFoundError({ path: req.path });
|
|
16
17
|
}
|
|
17
18
|
const service = new ItemsService(req.collection, {
|
|
18
19
|
accountability: req.accountability,
|
|
@@ -38,7 +39,7 @@ router.post('/:collection', collectionExists, asyncHandler(async (req, res, next
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
catch (error) {
|
|
41
|
-
if (error
|
|
42
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
42
43
|
return next();
|
|
43
44
|
}
|
|
44
45
|
throw error;
|
|
@@ -47,7 +48,7 @@ router.post('/:collection', collectionExists, asyncHandler(async (req, res, next
|
|
|
47
48
|
}), respond);
|
|
48
49
|
const readHandler = asyncHandler(async (req, res, next) => {
|
|
49
50
|
if (req.params['collection'].startsWith('directus_'))
|
|
50
|
-
throw new
|
|
51
|
+
throw new ForbiddenError();
|
|
51
52
|
const service = new ItemsService(req.collection, {
|
|
52
53
|
accountability: req.accountability,
|
|
53
54
|
schema: req.schema,
|
|
@@ -77,7 +78,7 @@ router.search('/:collection', collectionExists, validateBatch('read'), readHandl
|
|
|
77
78
|
router.get('/:collection', collectionExists, readHandler, respond);
|
|
78
79
|
router.get('/:collection/:pk', collectionExists, asyncHandler(async (req, res, next) => {
|
|
79
80
|
if (req.params['collection'].startsWith('directus_'))
|
|
80
|
-
throw new
|
|
81
|
+
throw new ForbiddenError();
|
|
81
82
|
const service = new ItemsService(req.collection, {
|
|
82
83
|
accountability: req.accountability,
|
|
83
84
|
schema: req.schema,
|
|
@@ -90,7 +91,7 @@ router.get('/:collection/:pk', collectionExists, asyncHandler(async (req, res, n
|
|
|
90
91
|
}), respond);
|
|
91
92
|
router.patch('/:collection', collectionExists, validateBatch('update'), asyncHandler(async (req, res, next) => {
|
|
92
93
|
if (req.params['collection'].startsWith('directus_'))
|
|
93
|
-
throw new
|
|
94
|
+
throw new ForbiddenError();
|
|
94
95
|
const service = new ItemsService(req.collection, {
|
|
95
96
|
accountability: req.accountability,
|
|
96
97
|
schema: req.schema,
|
|
@@ -117,7 +118,7 @@ router.patch('/:collection', collectionExists, validateBatch('update'), asyncHan
|
|
|
117
118
|
res.locals['payload'] = { data: result };
|
|
118
119
|
}
|
|
119
120
|
catch (error) {
|
|
120
|
-
if (error
|
|
121
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
121
122
|
return next();
|
|
122
123
|
}
|
|
123
124
|
throw error;
|
|
@@ -126,9 +127,9 @@ router.patch('/:collection', collectionExists, validateBatch('update'), asyncHan
|
|
|
126
127
|
}), respond);
|
|
127
128
|
router.patch('/:collection/:pk', collectionExists, asyncHandler(async (req, res, next) => {
|
|
128
129
|
if (req.params['collection'].startsWith('directus_'))
|
|
129
|
-
throw new
|
|
130
|
+
throw new ForbiddenError();
|
|
130
131
|
if (req.singleton) {
|
|
131
|
-
throw new
|
|
132
|
+
throw new RouteNotFoundError({ path: req.path });
|
|
132
133
|
}
|
|
133
134
|
const service = new ItemsService(req.collection, {
|
|
134
135
|
accountability: req.accountability,
|
|
@@ -140,7 +141,7 @@ router.patch('/:collection/:pk', collectionExists, asyncHandler(async (req, res,
|
|
|
140
141
|
res.locals['payload'] = { data: result || null };
|
|
141
142
|
}
|
|
142
143
|
catch (error) {
|
|
143
|
-
if (error
|
|
144
|
+
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
144
145
|
return next();
|
|
145
146
|
}
|
|
146
147
|
throw error;
|
|
@@ -149,7 +150,7 @@ router.patch('/:collection/:pk', collectionExists, asyncHandler(async (req, res,
|
|
|
149
150
|
}), respond);
|
|
150
151
|
router.delete('/:collection', collectionExists, validateBatch('delete'), asyncHandler(async (req, _res, next) => {
|
|
151
152
|
if (req.params['collection'].startsWith('directus_'))
|
|
152
|
-
throw new
|
|
153
|
+
throw new ForbiddenError();
|
|
153
154
|
const service = new ItemsService(req.collection, {
|
|
154
155
|
accountability: req.accountability,
|
|
155
156
|
schema: req.schema,
|
|
@@ -168,7 +169,7 @@ router.delete('/:collection', collectionExists, validateBatch('delete'), asyncHa
|
|
|
168
169
|
}), respond);
|
|
169
170
|
router.delete('/:collection/:pk', collectionExists, asyncHandler(async (req, _res, next) => {
|
|
170
171
|
if (req.params['collection'].startsWith('directus_'))
|
|
171
|
-
throw new
|
|
172
|
+
throw new ForbiddenError();
|
|
172
173
|
const service = new ItemsService(req.collection, {
|
|
173
174
|
accountability: req.accountability,
|
|
174
175
|
schema: req.schema,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import getDatabase from '../database/index.js';
|
|
2
2
|
import emitter from '../emitter.js';
|
|
3
|
-
import {
|
|
3
|
+
import { RouteNotFoundError } from '../errors/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Handles not found routes.
|
|
6
6
|
*
|
|
@@ -22,7 +22,7 @@ const notFound = async (req, res, next) => {
|
|
|
22
22
|
if (hooksResult) {
|
|
23
23
|
return next();
|
|
24
24
|
}
|
|
25
|
-
next(new
|
|
25
|
+
next(new RouteNotFoundError({ path: req.path }));
|
|
26
26
|
}
|
|
27
27
|
catch (err) {
|
|
28
28
|
next(err);
|