@directus/api 18.2.0 → 19.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 +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/controllers/activity.js +1 -1
- package/dist/controllers/auth.js +7 -6
- package/dist/controllers/extensions.js +30 -0
- package/dist/controllers/fields.js +1 -3
- 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/extensions/manager.d.ts +1 -0
- package/dist/extensions/manager.js +4 -1
- package/dist/middleware/authenticate.js +1 -1
- package/dist/services/extensions.d.ts +3 -0
- package/dist/services/extensions.js +40 -9
- package/dist/services/fields.d.ts +2 -1
- package/dist/services/fields.js +33 -4
- package/dist/services/graphql/index.js +1 -1
- package/dist/services/relations.js +6 -0
- package/dist/services/webhooks.d.ts +7 -4
- package/dist/services/webhooks.js +15 -12
- 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-schema.d.ts +1 -1
- package/dist/utils/get-schema.js +52 -29
- package/dist/websocket/controllers/base.d.ts +1 -3
- package/dist/websocket/controllers/base.js +12 -3
- package/license +1 -1
- package/package.json +36 -34
- package/dist/webhooks.d.ts +0 -4
- package/dist/webhooks.js +0 -80
package/dist/services/fields.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { KNEX_TYPES, REGEX_BETWEEN_PARENS } from '@directus/constants';
|
|
2
|
+
import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
|
|
2
3
|
import { createInspector } from '@directus/schema';
|
|
3
4
|
import { addFieldFlag, toArray } from '@directus/utils';
|
|
4
5
|
import { isEqual, isNil, merge } from 'lodash-es';
|
|
@@ -8,16 +9,15 @@ import { translateDatabaseError } from '../database/errors/translate.js';
|
|
|
8
9
|
import { getHelpers } from '../database/helpers/index.js';
|
|
9
10
|
import getDatabase, { getSchemaInspector } from '../database/index.js';
|
|
10
11
|
import emitter from '../emitter.js';
|
|
11
|
-
import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
|
|
12
|
-
import { ItemsService } from './items.js';
|
|
13
|
-
import { PayloadService } from './payload.js';
|
|
14
12
|
import getDefaultValue from '../utils/get-default-value.js';
|
|
13
|
+
import { getSystemFieldRowsWithAuthProviders } from '../utils/get-field-system-rows.js';
|
|
15
14
|
import getLocalType from '../utils/get-local-type.js';
|
|
16
15
|
import { getSchema } from '../utils/get-schema.js';
|
|
17
16
|
import { sanitizeColumn } from '../utils/sanitize-schema.js';
|
|
18
17
|
import { shouldClearCache } from '../utils/should-clear-cache.js';
|
|
18
|
+
import { ItemsService } from './items.js';
|
|
19
|
+
import { PayloadService } from './payload.js';
|
|
19
20
|
import { RelationsService } from './relations.js';
|
|
20
|
-
import { getSystemFieldRowsWithAuthProviders } from '../utils/get-field-system-rows.js';
|
|
21
21
|
const systemFieldRows = getSystemFieldRowsWithAuthProviders();
|
|
22
22
|
export class FieldsService {
|
|
23
23
|
knex;
|
|
@@ -406,6 +406,35 @@ export class FieldsService {
|
|
|
406
406
|
}
|
|
407
407
|
}
|
|
408
408
|
}
|
|
409
|
+
async updateFields(collection, fields, opts) {
|
|
410
|
+
const nestedActionEvents = [];
|
|
411
|
+
try {
|
|
412
|
+
const fieldNames = [];
|
|
413
|
+
for (const field of fields) {
|
|
414
|
+
fieldNames.push(await this.updateField(collection, field, {
|
|
415
|
+
autoPurgeCache: false,
|
|
416
|
+
autoPurgeSystemCache: false,
|
|
417
|
+
bypassEmitAction: (params) => nestedActionEvents.push(params),
|
|
418
|
+
}));
|
|
419
|
+
}
|
|
420
|
+
return fieldNames;
|
|
421
|
+
}
|
|
422
|
+
finally {
|
|
423
|
+
if (shouldClearCache(this.cache, opts)) {
|
|
424
|
+
await this.cache.clear();
|
|
425
|
+
}
|
|
426
|
+
if (opts?.autoPurgeSystemCache !== false) {
|
|
427
|
+
await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
|
|
428
|
+
}
|
|
429
|
+
if (opts?.emitEvents !== false && nestedActionEvents.length > 0) {
|
|
430
|
+
const updatedSchema = await getSchema();
|
|
431
|
+
for (const nestedActionEvent of nestedActionEvents) {
|
|
432
|
+
nestedActionEvent.context.schema = updatedSchema;
|
|
433
|
+
emitter.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
409
438
|
async deleteField(collection, field, opts) {
|
|
410
439
|
if (this.accountability && this.accountability.admin !== true) {
|
|
411
440
|
throw new ForbiddenError();
|
|
@@ -105,7 +105,7 @@ export class GraphQLService {
|
|
|
105
105
|
return formattedResult;
|
|
106
106
|
}
|
|
107
107
|
getSchema(type = 'schema') {
|
|
108
|
-
const key = `${type}_${this.accountability?.role}_${this.accountability?.user}`;
|
|
108
|
+
const key = `${this.scope}_${type}_${this.accountability?.role}_${this.accountability?.user}`;
|
|
109
109
|
const cachedSchema = cache.get(key);
|
|
110
110
|
if (cachedSchema)
|
|
111
111
|
return cachedSchema;
|
|
@@ -161,6 +161,9 @@ export class RelationsService {
|
|
|
161
161
|
if (relation.schema?.on_delete) {
|
|
162
162
|
builder.onDelete(relation.schema.on_delete);
|
|
163
163
|
}
|
|
164
|
+
if (relation.schema?.on_update) {
|
|
165
|
+
builder.onUpdate(relation.schema.on_update);
|
|
166
|
+
}
|
|
164
167
|
});
|
|
165
168
|
}
|
|
166
169
|
const relationsItemService = new ItemsService('directus_relations', {
|
|
@@ -236,6 +239,9 @@ export class RelationsService {
|
|
|
236
239
|
if (relation.schema?.on_delete) {
|
|
237
240
|
builder.onDelete(relation.schema.on_delete);
|
|
238
241
|
}
|
|
242
|
+
if (relation.schema?.on_update) {
|
|
243
|
+
builder.onUpdate(relation.schema.on_update);
|
|
244
|
+
}
|
|
239
245
|
});
|
|
240
246
|
}
|
|
241
247
|
const relationsItemService = new ItemsService('directus_relations', {
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { type DirectusError } from '@directus/errors';
|
|
1
2
|
import type { Bus } from '@directus/memory';
|
|
2
|
-
import type { AbstractServiceOptions,
|
|
3
|
+
import type { AbstractServiceOptions, MutationOptions, PrimaryKey, Webhook } from '../types/index.js';
|
|
3
4
|
import { ItemsService } from './items.js';
|
|
4
5
|
export declare class WebhooksService extends ItemsService<Webhook> {
|
|
5
6
|
messenger: Bus;
|
|
7
|
+
errorDeprecation: DirectusError;
|
|
6
8
|
constructor(options: AbstractServiceOptions);
|
|
7
|
-
createOne(
|
|
8
|
-
createMany(
|
|
9
|
-
|
|
9
|
+
createOne(): Promise<PrimaryKey>;
|
|
10
|
+
createMany(): Promise<PrimaryKey[]>;
|
|
11
|
+
updateBatch(): Promise<PrimaryKey[]>;
|
|
12
|
+
updateMany(): Promise<PrimaryKey[]>;
|
|
10
13
|
deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
11
14
|
}
|
|
@@ -1,25 +1,28 @@
|
|
|
1
|
+
import { ErrorCode, createError } from '@directus/errors';
|
|
1
2
|
import { useBus } from '../bus/index.js';
|
|
3
|
+
import { useLogger } from '../logger.js';
|
|
2
4
|
import { ItemsService } from './items.js';
|
|
5
|
+
const logger = useLogger();
|
|
3
6
|
export class WebhooksService extends ItemsService {
|
|
4
7
|
messenger;
|
|
8
|
+
errorDeprecation;
|
|
5
9
|
constructor(options) {
|
|
6
10
|
super('directus_webhooks', options);
|
|
7
11
|
this.messenger = useBus();
|
|
12
|
+
this.errorDeprecation = new (createError(ErrorCode.MethodNotAllowed, 'Webhooks are deprecated, use Flows instead', 405))();
|
|
13
|
+
logger.warn('Webhooks are deprecated and the WebhooksService will be removed in an upcoming release. Creating/Updating Webhooks is disabled, use Flows instead');
|
|
8
14
|
}
|
|
9
|
-
async createOne(
|
|
10
|
-
|
|
11
|
-
this.messenger.publish('webhooks', { type: 'reload' });
|
|
12
|
-
return result;
|
|
15
|
+
async createOne() {
|
|
16
|
+
throw this.errorDeprecation;
|
|
13
17
|
}
|
|
14
|
-
async createMany(
|
|
15
|
-
|
|
16
|
-
this.messenger.publish('webhooks', { type: 'reload' });
|
|
17
|
-
return result;
|
|
18
|
+
async createMany() {
|
|
19
|
+
throw this.errorDeprecation;
|
|
18
20
|
}
|
|
19
|
-
async
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
async updateBatch() {
|
|
22
|
+
throw this.errorDeprecation;
|
|
23
|
+
}
|
|
24
|
+
async updateMany() {
|
|
25
|
+
throw this.errorDeprecation;
|
|
23
26
|
}
|
|
24
27
|
async deleteMany(keys, opts) {
|
|
25
28
|
const result = await super.deleteMany(keys, opts);
|
|
@@ -73,7 +73,7 @@ export default async function getASTFromQuery(collection, query, schema, options
|
|
|
73
73
|
for (const fieldKey of fields) {
|
|
74
74
|
let name = fieldKey;
|
|
75
75
|
if (query.alias) {
|
|
76
|
-
// check for field alias (is
|
|
76
|
+
// check for field alias (is one of the key)
|
|
77
77
|
if (name in query.alias) {
|
|
78
78
|
name = query.alias[fieldKey];
|
|
79
79
|
}
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import { useEnv } from '@directus/env';
|
|
2
2
|
import { toArray } from '@directus/utils';
|
|
3
|
-
export function getAuthProviders() {
|
|
3
|
+
export function getAuthProviders({ sessionOnly } = { sessionOnly: false }) {
|
|
4
4
|
const env = useEnv();
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
.
|
|
5
|
+
let providers = toArray(env['AUTH_PROVIDERS']).filter((provider) => provider && env[`AUTH_${provider.toUpperCase()}_DRIVER`]);
|
|
6
|
+
if (sessionOnly) {
|
|
7
|
+
providers = providers.filter((provider) => {
|
|
8
|
+
const driver = env[`AUTH_${provider.toUpperCase()}_DRIVER`];
|
|
9
|
+
// only the following 3 drivers require a mode selection
|
|
10
|
+
if (['oauth2', 'openid', 'saml'].includes(driver)) {
|
|
11
|
+
const mode = env[`AUTH_${provider.toUpperCase()}_MODE`];
|
|
12
|
+
// if mode is not defined it defaults to session
|
|
13
|
+
return !mode || mode === 'session';
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return providers.map((provider) => ({
|
|
8
19
|
name: provider,
|
|
9
20
|
label: env[`AUTH_${provider.toUpperCase()}_LABEL`],
|
|
10
21
|
driver: env[`AUTH_${provider.toUpperCase()}_DRIVER`],
|
package/dist/utils/get-schema.js
CHANGED
|
@@ -1,47 +1,70 @@
|
|
|
1
1
|
import { useEnv } from '@directus/env';
|
|
2
2
|
import { createInspector } from '@directus/schema';
|
|
3
|
+
import { systemCollectionRows } from '@directus/system-data';
|
|
3
4
|
import { parseJSON, toArray } from '@directus/utils';
|
|
4
5
|
import { mapValues } from 'lodash-es';
|
|
6
|
+
import { useBus } from '../bus/index.js';
|
|
5
7
|
import { getSchemaCache, setSchemaCache } from '../cache.js';
|
|
6
8
|
import { ALIAS_TYPES } from '../constants.js';
|
|
7
9
|
import getDatabase from '../database/index.js';
|
|
10
|
+
import { useLock } from '../lock/index.js';
|
|
8
11
|
import { useLogger } from '../logger.js';
|
|
9
12
|
import { RelationsService } from '../services/relations.js';
|
|
10
13
|
import getDefaultValue from './get-default-value.js';
|
|
11
|
-
import getLocalType from './get-local-type.js';
|
|
12
|
-
import { systemCollectionRows } from '@directus/system-data';
|
|
13
14
|
import { getSystemFieldRowsWithAuthProviders } from './get-field-system-rows.js';
|
|
15
|
+
import getLocalType from './get-local-type.js';
|
|
14
16
|
const logger = useLogger();
|
|
15
|
-
export async function getSchema(options) {
|
|
17
|
+
export async function getSchema(options, attempt = 0) {
|
|
18
|
+
const MAX_ATTEMPTS = 3;
|
|
16
19
|
const env = useEnv();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
let result;
|
|
20
|
-
if (!options?.bypassCache && env['CACHE_SCHEMA'] !== false) {
|
|
21
|
-
let cachedSchema;
|
|
22
|
-
try {
|
|
23
|
-
cachedSchema = await getSchemaCache();
|
|
24
|
-
}
|
|
25
|
-
catch (err) {
|
|
26
|
-
logger.warn(err, `[schema-cache] Couldn't retrieve cache. ${err}`);
|
|
27
|
-
}
|
|
28
|
-
if (cachedSchema) {
|
|
29
|
-
result = cachedSchema;
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
result = await getDatabaseSchema(database, schemaInspector);
|
|
33
|
-
try {
|
|
34
|
-
await setSchemaCache(result);
|
|
35
|
-
}
|
|
36
|
-
catch (err) {
|
|
37
|
-
logger.warn(err, `[schema-cache] Couldn't save cache. ${err}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
20
|
+
if (attempt >= MAX_ATTEMPTS) {
|
|
21
|
+
throw new Error(`Failed to get Schema information: hit infinite loop`);
|
|
40
22
|
}
|
|
41
|
-
|
|
42
|
-
|
|
23
|
+
if (options?.bypassCache || env['CACHE_SCHEMA'] === false) {
|
|
24
|
+
const database = options?.database || getDatabase();
|
|
25
|
+
const schemaInspector = createInspector(database);
|
|
26
|
+
return await getDatabaseSchema(database, schemaInspector);
|
|
27
|
+
}
|
|
28
|
+
const cached = await getSchemaCache();
|
|
29
|
+
if (cached) {
|
|
30
|
+
return cached;
|
|
31
|
+
}
|
|
32
|
+
const lock = useLock();
|
|
33
|
+
const bus = useBus();
|
|
34
|
+
const lockKey = 'schemaCache--preparing';
|
|
35
|
+
const messageKey = 'schemaCache--done';
|
|
36
|
+
const processId = await lock.increment(lockKey);
|
|
37
|
+
const currentProcessShouldHandleOperation = processId === 1;
|
|
38
|
+
if (currentProcessShouldHandleOperation === false) {
|
|
39
|
+
logger.trace('Schema cache is prepared in another process, waiting for result.');
|
|
40
|
+
return new Promise((resolve) => {
|
|
41
|
+
const TIMEOUT = 10000;
|
|
42
|
+
let timeout;
|
|
43
|
+
const callback = async () => {
|
|
44
|
+
if (timeout)
|
|
45
|
+
clearTimeout(timeout);
|
|
46
|
+
const schema = await getSchema(options, attempt + 1);
|
|
47
|
+
resolve(schema);
|
|
48
|
+
bus.unsubscribe(messageKey, callback);
|
|
49
|
+
};
|
|
50
|
+
bus.subscribe(messageKey, callback);
|
|
51
|
+
timeout = setTimeout(async () => {
|
|
52
|
+
logger.trace('Did not receive schema callback message in time. Pulling schema...');
|
|
53
|
+
callback();
|
|
54
|
+
}, TIMEOUT);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const database = options?.database || getDatabase();
|
|
59
|
+
const schemaInspector = createInspector(database);
|
|
60
|
+
const schema = await getDatabaseSchema(database, schemaInspector);
|
|
61
|
+
await setSchemaCache(schema);
|
|
62
|
+
return schema;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await lock.delete(lockKey);
|
|
66
|
+
bus.publish(messageKey, { ready: true });
|
|
43
67
|
}
|
|
44
|
-
return result;
|
|
45
68
|
}
|
|
46
69
|
async function getDatabaseSchema(database, schemaInspector) {
|
|
47
70
|
const env = useEnv();
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
/// <reference types="node" resolution-mode="require"/>
|
|
3
3
|
/// <reference types="node" resolution-mode="require"/>
|
|
4
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
5
4
|
/// <reference types="node/http.js" />
|
|
6
5
|
/// <reference types="pino-http" />
|
|
7
6
|
import type { IncomingMessage, Server as httpServer } from 'http';
|
|
8
|
-
import type { ParsedUrlQuery } from 'querystring';
|
|
9
7
|
import type { RateLimiterAbstract } from 'rate-limiter-flexible';
|
|
10
8
|
import type internal from 'stream';
|
|
11
9
|
import WebSocket from 'ws';
|
|
@@ -34,7 +32,7 @@ export default abstract class SocketController {
|
|
|
34
32
|
protected getRateLimiter(): RateLimiterAbstract | null;
|
|
35
33
|
private catchInvalidMessages;
|
|
36
34
|
protected handleUpgrade(request: IncomingMessage, socket: internal.Duplex, head: Buffer): Promise<void>;
|
|
37
|
-
protected
|
|
35
|
+
protected handleTokenUpgrade({ request, socket, head }: UpgradeContext, token: string): Promise<void>;
|
|
38
36
|
protected handleHandshakeUpgrade({ request, socket, head }: UpgradeContext): Promise<void>;
|
|
39
37
|
createClient(ws: WebSocket, { accountability, expires_at }: AuthenticationState): WebSocketClient;
|
|
40
38
|
protected parseMessage(data: string): WebSocketMessage;
|
|
@@ -16,6 +16,7 @@ import { getExpiresAtForToken } from '../utils/get-expires-at-for-token.js';
|
|
|
16
16
|
import { getMessageType } from '../utils/message.js';
|
|
17
17
|
import { waitForAnyMessage, waitForMessageType } from '../utils/wait-for-message.js';
|
|
18
18
|
import { registerWebSocketEvents } from './hooks.js';
|
|
19
|
+
import cookie from 'cookie';
|
|
19
20
|
const TOKEN_CHECK_INTERVAL = 15 * 60 * 1000; // 15 minutes
|
|
20
21
|
const logger = useLogger();
|
|
21
22
|
export default class SocketController {
|
|
@@ -96,9 +97,18 @@ export default class SocketController {
|
|
|
96
97
|
socket.destroy();
|
|
97
98
|
return;
|
|
98
99
|
}
|
|
100
|
+
const env = useEnv();
|
|
101
|
+
const cookies = request.headers.cookie ? cookie.parse(request.headers.cookie) : {};
|
|
99
102
|
const context = { request, socket, head };
|
|
103
|
+
const sessionCookieName = env['SESSION_COOKIE_NAME'];
|
|
104
|
+
if (cookies[sessionCookieName]) {
|
|
105
|
+
const token = cookies[sessionCookieName];
|
|
106
|
+
await this.handleTokenUpgrade(context, token);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
100
109
|
if (this.authentication.mode === 'strict') {
|
|
101
|
-
|
|
110
|
+
const token = query['access_token'];
|
|
111
|
+
await this.handleTokenUpgrade(context, token);
|
|
102
112
|
return;
|
|
103
113
|
}
|
|
104
114
|
if (this.authentication.mode === 'handshake') {
|
|
@@ -111,10 +121,9 @@ export default class SocketController {
|
|
|
111
121
|
this.server.emit('connection', ws, state);
|
|
112
122
|
});
|
|
113
123
|
}
|
|
114
|
-
async
|
|
124
|
+
async handleTokenUpgrade({ request, socket, head }, token) {
|
|
115
125
|
let accountability, expires_at;
|
|
116
126
|
try {
|
|
117
|
-
const token = query['access_token'];
|
|
118
127
|
accountability = await getAccountabilityForToken(token);
|
|
119
128
|
expires_at = getExpiresAtForToken(token);
|
|
120
129
|
}
|
package/license
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Licensor: Monospace, Inc.
|
|
2
2
|
|
|
3
3
|
Licensed Work: Directus
|
|
4
|
-
The Licensed Work is Copyright ©
|
|
4
|
+
The Licensed Work is Copyright © 2024 Monospace, Inc.
|
|
5
5
|
|
|
6
6
|
Additional Use Grant: You may use the Licensed Work in production as long as
|
|
7
7
|
your Total Finances do not exceed US $5,000,000 for the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "19.0.0",
|
|
4
4
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"directus",
|
|
@@ -59,12 +59,12 @@
|
|
|
59
59
|
],
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@authenio/samlify-node-xmllint": "2.0.0",
|
|
62
|
-
"@aws-sdk/client-ses": "3.
|
|
63
|
-
"@directus/format-title": "10.1.0",
|
|
62
|
+
"@aws-sdk/client-ses": "3.533.0",
|
|
64
63
|
"@godaddy/terminus": "4.12.1",
|
|
65
64
|
"@rollup/plugin-alias": "5.1.0",
|
|
66
65
|
"@rollup/plugin-node-resolve": "15.2.3",
|
|
67
66
|
"@rollup/plugin-virtual": "3.0.2",
|
|
67
|
+
"@types/cookie": "0.6.0",
|
|
68
68
|
"argon2": "0.40.1",
|
|
69
69
|
"async": "3.2.5",
|
|
70
70
|
"axios": "1.6.7",
|
|
@@ -75,10 +75,11 @@
|
|
|
75
75
|
"chokidar": "3.6.0",
|
|
76
76
|
"commander": "12.0.0",
|
|
77
77
|
"content-disposition": "0.5.4",
|
|
78
|
+
"cookie": "0.6.0",
|
|
78
79
|
"cookie-parser": "1.4.6",
|
|
79
80
|
"cors": "2.8.5",
|
|
80
81
|
"cron-parser": "4.9.0",
|
|
81
|
-
"date-fns": "3.
|
|
82
|
+
"date-fns": "3.6.0",
|
|
82
83
|
"deep-diff": "1.0.2",
|
|
83
84
|
"destroy": "1.2.0",
|
|
84
85
|
"dotenv": "16.4.5",
|
|
@@ -86,7 +87,7 @@
|
|
|
86
87
|
"eventemitter2": "6.4.9",
|
|
87
88
|
"execa": "8.0.1",
|
|
88
89
|
"exif-reader": "2.0.1",
|
|
89
|
-
"express": "4.
|
|
90
|
+
"express": "4.19.2",
|
|
90
91
|
"flat": "6.0.1",
|
|
91
92
|
"fs-extra": "11.2.0",
|
|
92
93
|
"glob-to-regexp": "0.4.1",
|
|
@@ -95,7 +96,7 @@
|
|
|
95
96
|
"graphql-ws": "5.15.0",
|
|
96
97
|
"helmet": "7.1.0",
|
|
97
98
|
"icc": "3.0.0",
|
|
98
|
-
"inquirer": "9.2.
|
|
99
|
+
"inquirer": "9.2.16",
|
|
99
100
|
"ioredis": "5.3.2",
|
|
100
101
|
"ip-matching": "2.1.2",
|
|
101
102
|
"isolated-vm": "4.7.2",
|
|
@@ -109,7 +110,7 @@
|
|
|
109
110
|
"ldapjs": "2.3.3",
|
|
110
111
|
"liquidjs": "10.10.1",
|
|
111
112
|
"lodash-es": "4.17.21",
|
|
112
|
-
"marked": "12.0.
|
|
113
|
+
"marked": "12.0.1",
|
|
113
114
|
"micromustache": "8.0.3",
|
|
114
115
|
"mime-types": "2.1.35",
|
|
115
116
|
"minimatch": "9.0.3",
|
|
@@ -118,7 +119,7 @@
|
|
|
118
119
|
"nanoid": "5.0.6",
|
|
119
120
|
"node-machine-id": "1.1.12",
|
|
120
121
|
"node-schedule": "2.1.1",
|
|
121
|
-
"nodemailer": "6.9.
|
|
122
|
+
"nodemailer": "6.9.13",
|
|
122
123
|
"object-hash": "3.0.0",
|
|
123
124
|
"openapi3-ts": "4.2.2",
|
|
124
125
|
"openid-client": "5.6.5",
|
|
@@ -135,7 +136,7 @@
|
|
|
135
136
|
"rate-limiter-flexible": "5.0.0",
|
|
136
137
|
"rollup": "4.12.0",
|
|
137
138
|
"samlify": "2.8.11",
|
|
138
|
-
"sanitize-html": "2.
|
|
139
|
+
"sanitize-html": "2.13.0",
|
|
139
140
|
"sharp": "0.33.2",
|
|
140
141
|
"snappy": "7.2.2",
|
|
141
142
|
"stream-json": "1.8.0",
|
|
@@ -145,28 +146,29 @@
|
|
|
145
146
|
"ws": "8.16.0",
|
|
146
147
|
"zod": "3.22.4",
|
|
147
148
|
"zod-validation-error": "3.0.3",
|
|
148
|
-
"@directus/app": "
|
|
149
|
-
"@directus/env": "1.1.
|
|
150
|
-
"@directus/constants": "11.0.3",
|
|
149
|
+
"@directus/app": "12.0.0",
|
|
150
|
+
"@directus/env": "1.1.1",
|
|
151
151
|
"@directus/errors": "0.2.4",
|
|
152
|
-
"@directus/
|
|
153
|
-
"@directus/extensions": "1.0.
|
|
154
|
-
"@directus/extensions-sdk": "11.0.
|
|
155
|
-
"@directus/
|
|
156
|
-
"@directus/
|
|
157
|
-
"@directus/
|
|
152
|
+
"@directus/constants": "11.0.3",
|
|
153
|
+
"@directus/extensions-registry": "1.0.2",
|
|
154
|
+
"@directus/extensions-sdk": "11.0.2",
|
|
155
|
+
"@directus/extensions": "1.0.2",
|
|
156
|
+
"@directus/format-title": "10.1.1",
|
|
157
|
+
"@directus/memory": "1.0.6",
|
|
158
|
+
"@directus/pressure": "1.0.18",
|
|
158
159
|
"@directus/schema": "11.0.1",
|
|
160
|
+
"@directus/specs": "10.2.8",
|
|
159
161
|
"@directus/storage": "10.0.11",
|
|
160
|
-
"@directus/storage-driver-
|
|
161
|
-
"@directus/storage-driver-
|
|
162
|
-
"@directus/storage-driver-gcs": "10.0.
|
|
163
|
-
"@directus/storage-driver-s3": "10.0.19",
|
|
162
|
+
"@directus/storage-driver-cloudinary": "10.0.19",
|
|
163
|
+
"@directus/storage-driver-azure": "10.0.19",
|
|
164
|
+
"@directus/storage-driver-gcs": "10.0.19",
|
|
164
165
|
"@directus/storage-driver-local": "10.0.18",
|
|
165
|
-
"@directus/storage-driver-
|
|
166
|
-
"@directus/
|
|
167
|
-
"@directus/utils": "11.0.
|
|
168
|
-
"directus": "
|
|
169
|
-
"@directus/validation": "0.0.
|
|
166
|
+
"@directus/storage-driver-s3": "10.0.20",
|
|
167
|
+
"@directus/storage-driver-supabase": "1.0.11",
|
|
168
|
+
"@directus/utils": "11.0.7",
|
|
169
|
+
"@directus/system-data": "1.0.2",
|
|
170
|
+
"@directus/validation": "0.0.14",
|
|
171
|
+
"directus": "10.10.5"
|
|
170
172
|
},
|
|
171
173
|
"devDependencies": {
|
|
172
174
|
"@ngneat/falso": "7.2.0",
|
|
@@ -191,34 +193,34 @@
|
|
|
191
193
|
"@types/lodash-es": "4.17.12",
|
|
192
194
|
"@types/mime-types": "2.1.4",
|
|
193
195
|
"@types/ms": "0.7.34",
|
|
194
|
-
"@types/node": "18.19.
|
|
196
|
+
"@types/node": "18.19.26",
|
|
195
197
|
"@types/node-schedule": "2.1.6",
|
|
196
198
|
"@types/nodemailer": "6.4.14",
|
|
197
199
|
"@types/object-hash": "3.0.6",
|
|
198
200
|
"@types/papaparse": "5.3.14",
|
|
199
|
-
"@types/qs": "6.9.
|
|
201
|
+
"@types/qs": "6.9.14",
|
|
200
202
|
"@types/sanitize-html": "2.11.0",
|
|
201
203
|
"@types/stream-json": "1.7.7",
|
|
202
204
|
"@types/tar": "6.1.11",
|
|
203
205
|
"@types/wellknown": "0.5.8",
|
|
204
206
|
"@types/ws": "8.5.10",
|
|
205
|
-
"@vitest/coverage-v8": "1.
|
|
207
|
+
"@vitest/coverage-v8": "1.4.0",
|
|
206
208
|
"copyfiles": "2.4.1",
|
|
207
209
|
"form-data": "4.0.0",
|
|
208
210
|
"knex-mock-client": "2.0.1",
|
|
209
211
|
"typescript": "5.3.3",
|
|
210
212
|
"vitest": "1.3.1",
|
|
211
213
|
"@directus/random": "0.2.7",
|
|
212
|
-
"@directus/
|
|
213
|
-
"@directus/
|
|
214
|
+
"@directus/tsconfig": "1.0.1",
|
|
215
|
+
"@directus/types": "11.0.8"
|
|
214
216
|
},
|
|
215
217
|
"optionalDependencies": {
|
|
216
218
|
"@keyv/redis": "2.8.4",
|
|
217
219
|
"mysql": "2.18.1",
|
|
218
220
|
"nodemailer-mailgun-transport": "2.1.5",
|
|
219
221
|
"nodemailer-sendgrid": "1.0.3",
|
|
220
|
-
"oracledb": "6.
|
|
221
|
-
"pg": "8.11.
|
|
222
|
+
"oracledb": "6.4.0",
|
|
223
|
+
"pg": "8.11.4",
|
|
222
224
|
"sqlite3": "5.1.7",
|
|
223
225
|
"tedious": "17.0.0"
|
|
224
226
|
},
|
package/dist/webhooks.d.ts
DELETED
package/dist/webhooks.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { useBus } from './bus/index.js';
|
|
2
|
-
import getDatabase from './database/index.js';
|
|
3
|
-
import emitter from './emitter.js';
|
|
4
|
-
import { useLogger } from './logger.js';
|
|
5
|
-
import { getAxios } from './request/index.js';
|
|
6
|
-
import { WebhooksService } from './services/webhooks.js';
|
|
7
|
-
import { getSchema } from './utils/get-schema.js';
|
|
8
|
-
import { JobQueue } from './utils/job-queue.js';
|
|
9
|
-
let registered = [];
|
|
10
|
-
const reloadQueue = new JobQueue();
|
|
11
|
-
export async function init() {
|
|
12
|
-
await register();
|
|
13
|
-
const messenger = useBus();
|
|
14
|
-
messenger.subscribe('webhooks', (event) => {
|
|
15
|
-
if (event['type'] === 'reload') {
|
|
16
|
-
reloadQueue.enqueue(async () => {
|
|
17
|
-
await reload();
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
export async function reload() {
|
|
23
|
-
unregister();
|
|
24
|
-
await register();
|
|
25
|
-
}
|
|
26
|
-
export async function register() {
|
|
27
|
-
const webhookService = new WebhooksService({ knex: getDatabase(), schema: await getSchema() });
|
|
28
|
-
const webhooks = await webhookService.readByQuery({ filter: { status: { _eq: 'active' } } });
|
|
29
|
-
for (const webhook of webhooks) {
|
|
30
|
-
for (const action of webhook.actions) {
|
|
31
|
-
const event = `items.${action}`;
|
|
32
|
-
const handler = createHandler(webhook, event);
|
|
33
|
-
emitter.onAction(event, handler);
|
|
34
|
-
registered.push({ event, handler });
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
export function unregister() {
|
|
39
|
-
for (const { event, handler } of registered) {
|
|
40
|
-
emitter.offAction(event, handler);
|
|
41
|
-
}
|
|
42
|
-
registered = [];
|
|
43
|
-
}
|
|
44
|
-
function createHandler(webhook, event) {
|
|
45
|
-
const logger = useLogger();
|
|
46
|
-
return async (meta, context) => {
|
|
47
|
-
if (webhook.collections.includes(meta['collection']) === false)
|
|
48
|
-
return;
|
|
49
|
-
const axios = await getAxios();
|
|
50
|
-
const webhookPayload = {
|
|
51
|
-
event,
|
|
52
|
-
accountability: context.accountability
|
|
53
|
-
? {
|
|
54
|
-
user: context.accountability.user,
|
|
55
|
-
role: context.accountability.role,
|
|
56
|
-
}
|
|
57
|
-
: null,
|
|
58
|
-
...meta,
|
|
59
|
-
};
|
|
60
|
-
try {
|
|
61
|
-
await axios({
|
|
62
|
-
url: webhook.url,
|
|
63
|
-
method: webhook.method,
|
|
64
|
-
data: webhook.data ? webhookPayload : null,
|
|
65
|
-
headers: mergeHeaders(webhook.headers),
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
logger.warn(`Webhook "${webhook.name}" (id: ${webhook.id}) failed`);
|
|
70
|
-
logger.warn(error);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
function mergeHeaders(headerArray) {
|
|
75
|
-
const headers = {};
|
|
76
|
-
for (const { header, value } of headerArray ?? []) {
|
|
77
|
-
headers[header] = value;
|
|
78
|
-
}
|
|
79
|
-
return headers;
|
|
80
|
-
}
|