@directus/api 18.2.1 → 19.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +0 -3
- package/dist/auth/drivers/ldap.js +1 -1
- package/dist/auth/drivers/local.js +1 -1
- package/dist/auth/drivers/oauth2.js +1 -1
- package/dist/auth/drivers/openid.js +1 -1
- package/dist/cache.js +1 -1
- package/dist/cli/utils/create-env/env-stub.liquid +2 -2
- package/dist/controllers/activity.js +1 -1
- package/dist/controllers/assets.js +9 -12
- package/dist/controllers/auth.js +7 -6
- package/dist/controllers/collections.js +1 -2
- package/dist/controllers/dashboards.js +1 -2
- package/dist/controllers/extensions.js +30 -0
- package/dist/controllers/fields.js +1 -3
- package/dist/controllers/flows.js +1 -2
- package/dist/controllers/folders.js +1 -2
- package/dist/controllers/items.js +3 -4
- package/dist/controllers/notifications.js +1 -2
- package/dist/controllers/operations.js +1 -2
- package/dist/controllers/panels.js +1 -2
- package/dist/controllers/presets.js +1 -2
- package/dist/controllers/roles.js +1 -2
- package/dist/controllers/translations.js +1 -2
- package/dist/controllers/users.js +1 -2
- package/dist/controllers/webhooks.js +10 -74
- package/dist/database/migrations/20240122A-add-report-url-fields.d.ts +3 -0
- package/dist/database/migrations/20240122A-add-report-url-fields.js +14 -0
- package/dist/database/migrations/20240204A-marketplace.js +17 -5
- package/dist/database/migrations/20240305A-change-useragent-type.d.ts +3 -0
- package/dist/database/migrations/20240305A-change-useragent-type.js +19 -0
- package/dist/database/migrations/20240311A-deprecate-webhooks.d.ts +13 -0
- package/dist/database/migrations/20240311A-deprecate-webhooks.js +125 -0
- package/dist/database/run-ast.js +4 -3
- package/dist/extensions/manager.d.ts +1 -0
- package/dist/extensions/manager.js +4 -1
- package/dist/middleware/authenticate.js +1 -1
- package/dist/services/activity.d.ts +2 -1
- package/dist/services/authorization.d.ts +2 -2
- package/dist/services/collections.d.ts +1 -1
- package/dist/services/collections.js +8 -7
- package/dist/services/extensions.d.ts +3 -0
- package/dist/services/extensions.js +42 -10
- package/dist/services/fields.d.ts +2 -1
- package/dist/services/fields.js +37 -7
- package/dist/services/files.d.ts +2 -2
- package/dist/services/flows.d.ts +2 -2
- package/dist/services/graphql/index.d.ts +2 -2
- package/dist/services/graphql/index.js +5 -0
- package/dist/services/import-export.js +4 -3
- package/dist/services/items.d.ts +2 -2
- package/dist/services/items.js +9 -8
- package/dist/services/notifications.d.ts +2 -2
- package/dist/services/operations.d.ts +2 -2
- package/dist/services/payload.d.ts +2 -2
- package/dist/services/permissions/index.d.ts +2 -2
- package/dist/services/relations.js +10 -3
- package/dist/services/revisions.d.ts +2 -1
- package/dist/services/roles.d.ts +2 -2
- package/dist/services/roles.js +2 -1
- package/dist/services/shares.d.ts +2 -1
- package/dist/services/shares.js +1 -1
- package/dist/services/tfa.d.ts +2 -1
- package/dist/services/tfa.js +1 -1
- package/dist/services/users.d.ts +2 -2
- package/dist/services/users.js +3 -2
- package/dist/services/utils.d.ts +2 -2
- package/dist/services/utils.js +2 -2
- package/dist/services/versions.d.ts +1 -1
- package/dist/services/webhooks.d.ts +8 -4
- package/dist/services/webhooks.js +15 -12
- package/dist/types/items.d.ts +1 -8
- package/dist/types/services.d.ts +1 -2
- package/dist/utils/apply-diff.js +2 -1
- package/dist/utils/get-ast-from-query.js +1 -1
- package/dist/utils/get-auth-providers.d.ts +3 -1
- package/dist/utils/get-auth-providers.js +15 -4
- package/dist/utils/get-cache-headers.js +0 -3
- package/dist/utils/get-schema.d.ts +1 -1
- package/dist/utils/get-schema.js +52 -29
- package/dist/utils/merge-version-data.js +1 -1
- package/dist/utils/transaction.d.ts +9 -0
- package/dist/utils/transaction.js +15 -0
- package/dist/utils/validate-keys.d.ts +1 -2
- package/dist/websocket/controllers/base.d.ts +1 -3
- package/dist/websocket/controllers/base.js +12 -3
- package/dist/websocket/utils/items.d.ts +1 -1
- package/license +1 -1
- package/package.json +39 -37
- package/dist/webhooks.d.ts +0 -4
- package/dist/webhooks.js +0 -80
package/dist/app.js
CHANGED
|
@@ -60,7 +60,6 @@ import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
|
60
60
|
import { Url } from './utils/url.js';
|
|
61
61
|
import { validateEnv } from './utils/validate-env.js';
|
|
62
62
|
import { validateStorage } from './utils/validate-storage.js';
|
|
63
|
-
import { init as initWebhooks } from './webhooks.js';
|
|
64
63
|
const require = createRequire(import.meta.url);
|
|
65
64
|
export default async function createApp() {
|
|
66
65
|
const env = useEnv();
|
|
@@ -240,8 +239,6 @@ export default async function createApp() {
|
|
|
240
239
|
app.use(notFoundHandler);
|
|
241
240
|
app.use(errorHandler);
|
|
242
241
|
await emitter.emitInit('routes.after', { app });
|
|
243
|
-
// Register all webhooks
|
|
244
|
-
await initWebhooks();
|
|
245
242
|
initTelemetry();
|
|
246
243
|
await emitter.emitInit('app.after', { app });
|
|
247
244
|
return app;
|
|
@@ -299,7 +299,7 @@ export function createLDAPAuthRouter(provider) {
|
|
|
299
299
|
ip: getIPFromReq(req),
|
|
300
300
|
role: null,
|
|
301
301
|
};
|
|
302
|
-
const userAgent = req.get('user-agent');
|
|
302
|
+
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
303
303
|
if (userAgent)
|
|
304
304
|
accountability.userAgent = userAgent;
|
|
305
305
|
const origin = req.get('origin');
|
|
@@ -51,7 +51,7 @@ export function createLocalAuthRouter(provider) {
|
|
|
51
51
|
ip: getIPFromReq(req),
|
|
52
52
|
role: null,
|
|
53
53
|
};
|
|
54
|
-
const userAgent = req.get('user-agent');
|
|
54
|
+
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
55
55
|
if (userAgent)
|
|
56
56
|
accountability.userAgent = userAgent;
|
|
57
57
|
const origin = req.get('origin');
|
|
@@ -254,7 +254,7 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
254
254
|
ip: getIPFromReq(req),
|
|
255
255
|
role: null,
|
|
256
256
|
};
|
|
257
|
-
const userAgent = req.get('user-agent');
|
|
257
|
+
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
258
258
|
if (userAgent)
|
|
259
259
|
accountability.userAgent = userAgent;
|
|
260
260
|
const origin = req.get('origin');
|
|
@@ -275,7 +275,7 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
275
275
|
ip: getIPFromReq(req),
|
|
276
276
|
role: null,
|
|
277
277
|
};
|
|
278
|
-
const userAgent = req.get('user-agent');
|
|
278
|
+
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
279
279
|
if (userAgent)
|
|
280
280
|
accountability.userAgent = userAgent;
|
|
281
281
|
const origin = req.get('origin');
|
package/dist/cache.js
CHANGED
|
@@ -80,7 +80,7 @@ export async function getSystemCache(key) {
|
|
|
80
80
|
}
|
|
81
81
|
export async function setSchemaCache(schema) {
|
|
82
82
|
const { localSchemaCache, sharedSchemaCache } = getCache();
|
|
83
|
-
const schemaHash =
|
|
83
|
+
const schemaHash = getSimpleHash(JSON.stringify(schema));
|
|
84
84
|
await sharedSchemaCache.set('hash', schemaHash);
|
|
85
85
|
await localSchemaCache.set('schema', schema);
|
|
86
86
|
await localSchemaCache.set('hash', schemaHash);
|
|
@@ -312,8 +312,8 @@ EXTENSIONS_AUTO_RELOAD=false
|
|
|
312
312
|
####################################################################################################
|
|
313
313
|
### Email
|
|
314
314
|
|
|
315
|
-
# Email address from which emails are sent ["no-reply@
|
|
316
|
-
EMAIL_FROM="no-reply@
|
|
315
|
+
# Email address from which emails are sent ["no-reply@example.com"]
|
|
316
|
+
EMAIL_FROM="no-reply@example.com"
|
|
317
317
|
|
|
318
318
|
# What to use to send emails. One of
|
|
319
319
|
# sendmail, smtp, mailgun, sendgrid, ses.
|
|
@@ -70,7 +70,7 @@ router.post('/comment', asyncHandler(async (req, res, next) => {
|
|
|
70
70
|
action: Action.COMMENT,
|
|
71
71
|
user: req.accountability?.user,
|
|
72
72
|
ip: getIPFromReq(req),
|
|
73
|
-
user_agent: req.
|
|
73
|
+
user_agent: req.accountability?.userAgent,
|
|
74
74
|
origin: req.get('origin'),
|
|
75
75
|
});
|
|
76
76
|
try {
|
|
@@ -180,17 +180,10 @@ asyncHandler(async (req, res) => {
|
|
|
180
180
|
res.setHeader('Content-Length', stat.size);
|
|
181
181
|
return res.end();
|
|
182
182
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
res.
|
|
187
|
-
});
|
|
188
|
-
stream.on('end', () => {
|
|
189
|
-
res.end();
|
|
190
|
-
});
|
|
191
|
-
stream.on('error', (e) => {
|
|
192
|
-
logger.error(e, `Couldn't stream file ${file.id} to the client`);
|
|
193
|
-
if (!isDataSent) {
|
|
183
|
+
stream
|
|
184
|
+
.on('error', (error) => {
|
|
185
|
+
logger.error(error, `Couldn't stream file ${file.id} to the client`);
|
|
186
|
+
if (!res.headersSent) {
|
|
194
187
|
res.removeHeader('Content-Type');
|
|
195
188
|
res.removeHeader('Content-Disposition');
|
|
196
189
|
res.removeHeader('Cache-Control');
|
|
@@ -205,7 +198,11 @@ asyncHandler(async (req, res) => {
|
|
|
205
198
|
],
|
|
206
199
|
});
|
|
207
200
|
}
|
|
208
|
-
|
|
201
|
+
else {
|
|
202
|
+
res.end();
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
.pipe(res);
|
|
209
206
|
return undefined;
|
|
210
207
|
}));
|
|
211
208
|
export default router;
|
package/dist/controllers/auth.js
CHANGED
|
@@ -74,7 +74,7 @@ router.post('/refresh', asyncHandler(async (req, res, next) => {
|
|
|
74
74
|
ip: getIPFromReq(req),
|
|
75
75
|
role: null,
|
|
76
76
|
};
|
|
77
|
-
const userAgent = req.get('user-agent');
|
|
77
|
+
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
78
78
|
if (userAgent)
|
|
79
79
|
accountability.userAgent = userAgent;
|
|
80
80
|
const origin = req.get('origin');
|
|
@@ -114,7 +114,7 @@ router.post('/logout', asyncHandler(async (req, res, next) => {
|
|
|
114
114
|
ip: getIPFromReq(req),
|
|
115
115
|
role: null,
|
|
116
116
|
};
|
|
117
|
-
const userAgent = req.get('user-agent');
|
|
117
|
+
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
118
118
|
if (userAgent)
|
|
119
119
|
accountability.userAgent = userAgent;
|
|
120
120
|
const origin = req.get('origin');
|
|
@@ -148,7 +148,7 @@ router.post('/password/request', asyncHandler(async (req, _res, next) => {
|
|
|
148
148
|
ip: getIPFromReq(req),
|
|
149
149
|
role: null,
|
|
150
150
|
};
|
|
151
|
-
const userAgent = req.get('user-agent');
|
|
151
|
+
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
152
152
|
if (userAgent)
|
|
153
153
|
accountability.userAgent = userAgent;
|
|
154
154
|
const origin = req.get('origin');
|
|
@@ -180,7 +180,7 @@ router.post('/password/reset', asyncHandler(async (req, _res, next) => {
|
|
|
180
180
|
ip: getIPFromReq(req),
|
|
181
181
|
role: null,
|
|
182
182
|
};
|
|
183
|
-
const userAgent = req.get('user-agent');
|
|
183
|
+
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
184
184
|
if (userAgent)
|
|
185
185
|
accountability.userAgent = userAgent;
|
|
186
186
|
const origin = req.get('origin');
|
|
@@ -190,9 +190,10 @@ router.post('/password/reset', asyncHandler(async (req, _res, next) => {
|
|
|
190
190
|
await service.resetPassword(req.body.token, req.body.password);
|
|
191
191
|
return next();
|
|
192
192
|
}), respond);
|
|
193
|
-
router.get('/', asyncHandler(async (
|
|
193
|
+
router.get('/', asyncHandler(async (req, res, next) => {
|
|
194
|
+
const sessionOnly = 'sessionOnly' in req.query && (req.query['sessionOnly'] === '' || Boolean(req.query['sessionOnly']));
|
|
194
195
|
res.locals['payload'] = {
|
|
195
|
-
data: getAuthProviders(),
|
|
196
|
+
data: getAuthProviders({ sessionOnly }),
|
|
196
197
|
disableDefault: env['AUTH_DISABLE_DEFAULT'],
|
|
197
198
|
};
|
|
198
199
|
return next();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import { Router } from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
6
5
|
import { CollectionsService } from '../services/collections.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -101,6 +101,36 @@ router.post('/registry/install', asyncHandler(async (req, _res, next) => {
|
|
|
101
101
|
await service.install(extension, version);
|
|
102
102
|
return next();
|
|
103
103
|
}), respond);
|
|
104
|
+
router.post('/registry/reinstall', asyncHandler(async (req, _res, next) => {
|
|
105
|
+
if (req.accountability && req.accountability.admin !== true) {
|
|
106
|
+
throw new ForbiddenError();
|
|
107
|
+
}
|
|
108
|
+
const { extension } = req.body;
|
|
109
|
+
if (!extension) {
|
|
110
|
+
throw new ForbiddenError();
|
|
111
|
+
}
|
|
112
|
+
const service = new ExtensionsService({
|
|
113
|
+
accountability: req.accountability,
|
|
114
|
+
schema: req.schema,
|
|
115
|
+
});
|
|
116
|
+
await service.reinstall(extension);
|
|
117
|
+
return next();
|
|
118
|
+
}), respond);
|
|
119
|
+
router.delete(`/registry/uninstall/:pk(${UUID_REGEX})`, asyncHandler(async (req, _res, next) => {
|
|
120
|
+
if (req.accountability && req.accountability.admin !== true) {
|
|
121
|
+
throw new ForbiddenError();
|
|
122
|
+
}
|
|
123
|
+
const pk = req.params['pk'];
|
|
124
|
+
if (typeof pk !== 'string') {
|
|
125
|
+
throw new ForbiddenError();
|
|
126
|
+
}
|
|
127
|
+
const service = new ExtensionsService({
|
|
128
|
+
accountability: req.accountability,
|
|
129
|
+
schema: req.schema,
|
|
130
|
+
});
|
|
131
|
+
await service.uninstall(pk);
|
|
132
|
+
return next();
|
|
133
|
+
}), respond);
|
|
104
134
|
router.patch(`/:pk(${UUID_REGEX})`, asyncHandler(async (req, res, next) => {
|
|
105
135
|
if (req.accountability && req.accountability.admin !== true) {
|
|
106
136
|
throw new ForbiddenError();
|
|
@@ -85,9 +85,7 @@ router.patch('/:collection', validateCollection, asyncHandler(async (req, res, n
|
|
|
85
85
|
if (Array.isArray(req.body) === false) {
|
|
86
86
|
throw new InvalidPayloadError({ reason: 'Submitted body has to be an array' });
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
await service.updateField(req.params['collection'], field);
|
|
90
|
-
}
|
|
88
|
+
await service.updateFields(req.params['collection'], req.body);
|
|
91
89
|
try {
|
|
92
90
|
const results = [];
|
|
93
91
|
for (const field of req.body) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import { UUID_REGEX } from '../constants.js';
|
|
4
|
-
import { ErrorCode } from '@directus/errors';
|
|
5
4
|
import { getFlowManager } from '../flows.js';
|
|
6
5
|
import { respond } from '../middleware/respond.js';
|
|
7
6
|
import useCollection from '../middleware/use-collection.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, ForbiddenError, RouteNotFoundError, isDirectusError } from '@directus/errors';
|
|
2
|
+
import { isSystemCollection } from '@directus/system-data';
|
|
2
3
|
import express from 'express';
|
|
3
|
-
import { ErrorCode, ForbiddenError, RouteNotFoundError } from '@directus/errors';
|
|
4
4
|
import collectionExists from '../middleware/collection-exists.js';
|
|
5
|
+
import { mergeContentVersions } from '../middleware/merge-content-versions.js';
|
|
5
6
|
import { respond } from '../middleware/respond.js';
|
|
6
7
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
7
|
-
import { mergeContentVersions } from '../middleware/merge-content-versions.js';
|
|
8
8
|
import { ItemsService } from '../services/items.js';
|
|
9
9
|
import { MetaService } from '../services/meta.js';
|
|
10
10
|
import asyncHandler from '../utils/async-handler.js';
|
|
11
11
|
import { sanitizeQuery } from '../utils/sanitize-query.js';
|
|
12
|
-
import { isSystemCollection } from '@directus/system-data';
|
|
13
12
|
const router = express.Router();
|
|
14
13
|
router.post('/:collection', collectionExists, asyncHandler(async (req, res, next) => {
|
|
15
14
|
if (isSystemCollection(req.params['collection']))
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
1
2
|
import express from 'express';
|
|
2
|
-
import { isDirectusError } from '@directus/errors';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { isDirectusError } from '@directus/errors';
|
|
1
|
+
import { ErrorCode, ForbiddenError, InvalidCredentialsError, InvalidPayloadError, isDirectusError, } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import Joi from 'joi';
|
|
4
|
-
import { ErrorCode, ForbiddenError, InvalidCredentialsError, InvalidPayloadError } from '@directus/errors';
|
|
5
4
|
import { respond } from '../middleware/respond.js';
|
|
6
5
|
import useCollection from '../middleware/use-collection.js';
|
|
7
6
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ErrorCode, createError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { ErrorCode } from '@directus/errors';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -10,37 +9,9 @@ import asyncHandler from '../utils/async-handler.js';
|
|
|
10
9
|
import { sanitizeQuery } from '../utils/sanitize-query.js';
|
|
11
10
|
const router = express.Router();
|
|
12
11
|
router.use(useCollection('directus_webhooks'));
|
|
13
|
-
router.post('/', asyncHandler(async (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
schema: req.schema,
|
|
17
|
-
});
|
|
18
|
-
const savedKeys = [];
|
|
19
|
-
if (Array.isArray(req.body)) {
|
|
20
|
-
const keys = await service.createMany(req.body);
|
|
21
|
-
savedKeys.push(...keys);
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
const key = await service.createOne(req.body);
|
|
25
|
-
savedKeys.push(key);
|
|
26
|
-
}
|
|
27
|
-
try {
|
|
28
|
-
if (Array.isArray(req.body)) {
|
|
29
|
-
const items = await service.readMany(savedKeys, req.sanitizedQuery);
|
|
30
|
-
res.locals['payload'] = { data: items };
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
const item = await service.readOne(savedKeys[0], req.sanitizedQuery);
|
|
34
|
-
res.locals['payload'] = { data: item };
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
39
|
-
return next();
|
|
40
|
-
}
|
|
41
|
-
throw error;
|
|
42
|
-
}
|
|
43
|
-
return next();
|
|
12
|
+
router.post('/', asyncHandler(async (_req, _res, _next) => {
|
|
13
|
+
// Disallow creation of new Webhooks as part of the deprecation, see https://github.com/directus/directus/issues/15553
|
|
14
|
+
throw new (createError(ErrorCode.MethodNotAllowed, 'Webhooks are deprecated, use Flows instead', 405))();
|
|
44
15
|
}), respond);
|
|
45
16
|
const readHandler = asyncHandler(async (req, res, next) => {
|
|
46
17
|
const service = new WebhooksService({
|
|
@@ -67,48 +38,13 @@ router.get('/:pk', asyncHandler(async (req, res, next) => {
|
|
|
67
38
|
res.locals['payload'] = { data: record || null };
|
|
68
39
|
return next();
|
|
69
40
|
}), respond);
|
|
70
|
-
router.patch('/', validateBatch('update'), asyncHandler(async (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
schema: req.schema,
|
|
74
|
-
});
|
|
75
|
-
let keys = [];
|
|
76
|
-
if (req.body.keys) {
|
|
77
|
-
keys = await service.updateMany(req.body.keys, req.body.data);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
const sanitizedQuery = sanitizeQuery(req.body.query, req.accountability);
|
|
81
|
-
keys = await service.updateByQuery(sanitizedQuery, req.body.data);
|
|
82
|
-
}
|
|
83
|
-
try {
|
|
84
|
-
const result = await service.readMany(keys, req.sanitizedQuery);
|
|
85
|
-
res.locals['payload'] = { data: result };
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
89
|
-
return next();
|
|
90
|
-
}
|
|
91
|
-
throw error;
|
|
92
|
-
}
|
|
93
|
-
return next();
|
|
41
|
+
router.patch('/', validateBatch('update'), asyncHandler(async (_req, _res, _next) => {
|
|
42
|
+
// Disallow patching of Webhooks as part of the deprecation, see https://github.com/directus/directus/issues/15553
|
|
43
|
+
throw new (createError(ErrorCode.MethodNotAllowed, 'Webhooks are deprecated, use Flows instead', 405))();
|
|
94
44
|
}), respond);
|
|
95
|
-
router.patch('/:pk', asyncHandler(async (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
schema: req.schema,
|
|
99
|
-
});
|
|
100
|
-
const primaryKey = await service.updateOne(req.params['pk'], req.body);
|
|
101
|
-
try {
|
|
102
|
-
const item = await service.readOne(primaryKey, req.sanitizedQuery);
|
|
103
|
-
res.locals['payload'] = { data: item || null };
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
107
|
-
return next();
|
|
108
|
-
}
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
return next();
|
|
45
|
+
router.patch('/:pk', asyncHandler(async (_req, _res, _next) => {
|
|
46
|
+
// Disallow patching of Webhooks as part of the deprecation, see https://github.com/directus/directus/issues/15553
|
|
47
|
+
throw new (createError(ErrorCode.MethodNotAllowed, 'Webhooks are deprecated, use Flows instead', 405))();
|
|
112
48
|
}), respond);
|
|
113
49
|
router.delete('/', asyncHandler(async (req, _res, next) => {
|
|
114
50
|
const service = new WebhooksService({
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export async function up(knex) {
|
|
2
|
+
await knex.schema.alterTable('directus_settings', (table) => {
|
|
3
|
+
table.string('report_error_url').nullable();
|
|
4
|
+
table.string('report_bug_url').nullable();
|
|
5
|
+
table.string('report_feature_url').nullable();
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
export async function down(knex) {
|
|
9
|
+
await knex.schema.alterTable('directus_settings', (table) => {
|
|
10
|
+
table.dropColumn('report_error_url');
|
|
11
|
+
table.dropColumn('report_bug_url');
|
|
12
|
+
table.dropColumn('report_feature_url');
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -32,7 +32,7 @@ export async function up(knex) {
|
|
|
32
32
|
source = 'local';
|
|
33
33
|
}
|
|
34
34
|
await knex('directus_extensions').update({ id, source, folder: name }).where({ name });
|
|
35
|
-
idMap.set(name, id);
|
|
35
|
+
idMap.set(name, { id, source });
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
for (const { name } of installedExtensions) {
|
|
@@ -44,16 +44,28 @@ export async function up(knex) {
|
|
|
44
44
|
continue;
|
|
45
45
|
const isScopedModuleBundleChild = name.startsWith('@') && splittedName.length > 2;
|
|
46
46
|
const bundleParentName = isScopedModuleBundleParent || isScopedModuleBundleChild ? splittedName.slice(0, 2).join('/') : splittedName[0];
|
|
47
|
-
const
|
|
48
|
-
if (!
|
|
47
|
+
const bundleParent = idMap.get(bundleParentName);
|
|
48
|
+
if (!bundleParent)
|
|
49
49
|
continue;
|
|
50
50
|
await knex('directus_extensions')
|
|
51
|
-
.update({
|
|
51
|
+
.update({
|
|
52
|
+
bundle: bundleParent.id,
|
|
53
|
+
folder: name.substring(bundleParentName.length + 1),
|
|
54
|
+
source: bundleParent.source,
|
|
55
|
+
})
|
|
52
56
|
.where({ folder: name });
|
|
53
57
|
}
|
|
58
|
+
await knex.schema.alterTable('directus_extensions', (table) => {
|
|
59
|
+
table.uuid('id').alter().notNullable();
|
|
60
|
+
});
|
|
61
|
+
await knex.transaction(async (trx) => {
|
|
62
|
+
await trx.schema.alterTable('directus_extensions', (table) => {
|
|
63
|
+
table.dropPrimary();
|
|
64
|
+
table.primary(['id']);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
54
67
|
await knex.schema.alterTable('directus_extensions', (table) => {
|
|
55
68
|
table.dropColumn('name');
|
|
56
|
-
table.uuid('id').alter().primary().notNullable();
|
|
57
69
|
table.string('source').alter().notNullable();
|
|
58
70
|
table.string('folder').alter().notNullable();
|
|
59
71
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getHelpers } from '../helpers/index.js';
|
|
2
|
+
export async function up(knex) {
|
|
3
|
+
const helper = getHelpers(knex).schema;
|
|
4
|
+
await Promise.all([
|
|
5
|
+
helper.changeToType('directus_activity', 'user_agent', 'text'),
|
|
6
|
+
helper.changeToType('directus_sessions', 'user_agent', 'text'),
|
|
7
|
+
]);
|
|
8
|
+
}
|
|
9
|
+
export async function down(knex) {
|
|
10
|
+
const helper = await getHelpers(knex).schema;
|
|
11
|
+
const opts = {
|
|
12
|
+
nullable: false,
|
|
13
|
+
length: 255,
|
|
14
|
+
};
|
|
15
|
+
await Promise.all([
|
|
16
|
+
helper.changeToType('directus_activity', 'user_agent', 'string', opts),
|
|
17
|
+
helper.changeToType('directus_sessions', 'user_agent', 'string', opts),
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Knex } from 'knex';
|
|
2
|
+
/**
|
|
3
|
+
* 0. Identify and persist which webhooks were active before deprecation
|
|
4
|
+
* 1. Migrate existing webhooks over to identically behaving Flows
|
|
5
|
+
* 2. Disable existing webhooks
|
|
6
|
+
* 3. Dont drop webhooks yet
|
|
7
|
+
*/
|
|
8
|
+
export declare function up(knex: Knex): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Dont completely drop Webhooks yet.
|
|
11
|
+
* Lets preserve the data and drop them in the next release to be extra safe with users data.
|
|
12
|
+
*/
|
|
13
|
+
export declare function down(knex: Knex): Promise<void>;
|