@directus/api 32.2.0 → 33.1.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/ai/chat/controllers/chat.post.js +19 -4
- package/dist/ai/chat/lib/create-ui-stream.d.ts +8 -7
- package/dist/ai/chat/lib/create-ui-stream.js +28 -25
- package/dist/ai/chat/middleware/load-settings.js +31 -7
- package/dist/ai/chat/models/chat-request.d.ts +135 -2
- package/dist/ai/chat/models/chat-request.js +56 -2
- package/dist/ai/chat/models/providers.d.ts +16 -2
- package/dist/ai/chat/models/providers.js +16 -2
- package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.js +3 -4
- package/dist/ai/chat/utils/format-context.d.ts +5 -0
- package/dist/ai/chat/utils/format-context.js +122 -0
- package/dist/ai/mcp/server.d.ts +27 -1
- package/dist/ai/providers/index.d.ts +3 -0
- package/dist/ai/providers/index.js +3 -0
- package/dist/ai/providers/options.d.ts +14 -0
- package/dist/ai/providers/options.js +26 -0
- package/dist/ai/providers/registry.d.ts +6 -0
- package/dist/ai/providers/registry.js +65 -0
- package/dist/ai/providers/types.d.ts +34 -0
- package/dist/ai/providers/types.js +1 -0
- package/dist/ai/tools/assets/index.js +1 -1
- package/dist/ai/tools/collections/index.js +2 -2
- package/dist/ai/tools/fields/index.js +2 -2
- package/dist/ai/tools/files/index.js +1 -1
- package/dist/ai/tools/flows/index.js +1 -1
- package/dist/ai/tools/folders/index.js +1 -1
- package/dist/ai/tools/items/index.js +6 -3
- package/dist/ai/tools/items/prompt.md +7 -9
- package/dist/ai/tools/relations/index.js +1 -1
- package/dist/ai/tools/schema.js +1 -1
- package/dist/ai/tools/trigger-flow/index.js +1 -1
- package/dist/app.js +12 -8
- package/dist/auth/drivers/ldap.d.ts +1 -1
- package/dist/auth/drivers/ldap.js +144 -139
- package/dist/auth/drivers/local.js +1 -1
- package/dist/auth/drivers/oauth2.d.ts +1 -2
- package/dist/auth/drivers/oauth2.js +22 -17
- package/dist/auth/drivers/openid.d.ts +1 -2
- package/dist/auth/drivers/openid.js +18 -13
- package/dist/auth/drivers/saml.js +3 -3
- package/dist/auth/utils/generate-callback-url.d.ts +11 -0
- package/dist/auth/utils/generate-callback-url.js +40 -0
- package/dist/auth/utils/is-login-redirect-allowed.d.ts +7 -0
- package/dist/{utils → auth/utils}/is-login-redirect-allowed.js +12 -9
- package/dist/cache.d.ts +12 -0
- package/dist/cache.js +27 -3
- package/dist/cli/commands/bootstrap/index.js +2 -2
- package/dist/cli/commands/database/install.js +1 -1
- package/dist/cli/commands/database/migrate.js +1 -1
- package/dist/cli/commands/init/index.js +2 -2
- package/dist/cli/commands/roles/create.js +4 -4
- package/dist/cli/commands/schema/apply.js +3 -3
- package/dist/cli/commands/schema/snapshot.js +1 -1
- package/dist/cli/utils/create-db-connection.d.ts +1 -1
- package/dist/cli/utils/create-db-connection.js +1 -1
- package/dist/cli/utils/create-env/env-stub.liquid +3 -0
- package/dist/cli/utils/create-env/index.js +1 -1
- package/dist/constants.d.ts +7 -3
- package/dist/constants.js +7 -3
- package/dist/controllers/access.js +1 -1
- package/dist/controllers/assets.js +1 -1
- package/dist/controllers/deployment.js +481 -0
- package/dist/controllers/extensions.js +1 -1
- package/dist/controllers/fields.js +8 -6
- package/dist/controllers/files.js +1 -1
- package/dist/controllers/items.js +1 -1
- package/dist/controllers/not-found.js +1 -1
- package/dist/controllers/relations.js +1 -1
- package/dist/database/errors/dialects/mysql.d.ts +1 -1
- package/dist/database/errors/dialects/postgres.d.ts +1 -1
- package/dist/database/errors/dialects/sqlite.d.ts +1 -1
- package/dist/database/errors/translate.d.ts +1 -1
- package/dist/database/errors/translate.js +1 -1
- package/dist/database/get-ast-from-query/lib/parse-fields.js +2 -2
- package/dist/database/helpers/date/dialects/mssql.js +1 -1
- package/dist/database/helpers/date/dialects/mysql.js +1 -1
- package/dist/database/helpers/date/types.js +1 -1
- package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +1 -0
- package/dist/database/helpers/schema/dialects/cockroachdb.js +24 -1
- package/dist/database/helpers/schema/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/schema/dialects/mysql.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/mysql.js +16 -3
- package/dist/database/helpers/schema/dialects/postgres.d.ts +1 -1
- package/dist/database/helpers/schema/types.d.ts +13 -0
- package/dist/database/helpers/schema/types.js +24 -0
- package/dist/database/index.js +4 -4
- package/dist/database/migrations/20220429A-add-flows.js +1 -1
- package/dist/database/migrations/20230526A-migrate-translation-strings.js +1 -1
- package/dist/database/migrations/20231009A-update-csv-fields-to-text.js +1 -1
- package/dist/database/migrations/20240204A-marketplace.js +9 -7
- package/dist/database/migrations/20240311A-deprecate-webhooks.d.ts +15 -0
- package/dist/database/migrations/20240311A-deprecate-webhooks.js +1 -1
- package/dist/database/migrations/20240806A-permissions-policies.js +2 -2
- package/dist/database/migrations/20240924A-migrate-legacy-comments.js +1 -1
- package/dist/database/migrations/20251014A-add-project-owner.js +1 -1
- package/dist/database/migrations/20251224A-remove-webhooks.d.ts +3 -0
- package/dist/database/migrations/20251224A-remove-webhooks.js +19 -0
- package/dist/database/migrations/20260110A-add-ai-provider-settings.d.ts +3 -0
- package/dist/database/migrations/20260110A-add-ai-provider-settings.js +35 -0
- package/dist/database/migrations/20260113A-add-revisions-index.d.ts +3 -0
- package/dist/database/migrations/20260113A-add-revisions-index.js +41 -0
- package/dist/database/migrations/20260128A-add-collaborative-editing.d.ts +3 -0
- package/dist/database/migrations/20260128A-add-collaborative-editing.js +10 -0
- package/dist/database/migrations/20260204A-add-deployment.d.ts +3 -0
- package/dist/database/migrations/20260204A-add-deployment.js +32 -0
- package/dist/database/migrations/run.js +3 -3
- package/dist/database/run-ast/lib/apply-query/add-join.js +1 -1
- package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.d.ts +2 -2
- package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.js +1 -1
- package/dist/database/run-ast/lib/apply-query/filter/index.js +1 -1
- package/dist/database/run-ast/lib/apply-query/filter/operator.js +1 -1
- package/dist/database/run-ast/lib/apply-query/sort.js +1 -1
- package/dist/database/run-ast/utils/get-column-pre-processor.js +2 -2
- package/dist/database/run-ast/utils/get-column.js +1 -1
- package/dist/database/seeds/run.js +3 -3
- package/dist/deployment/deployment.d.ts +94 -0
- package/dist/deployment/deployment.js +29 -0
- package/dist/deployment/drivers/index.d.ts +1 -0
- package/dist/deployment/drivers/index.js +1 -0
- package/dist/deployment/drivers/vercel.d.ts +32 -0
- package/dist/deployment/drivers/vercel.js +208 -0
- package/dist/deployment/index.d.ts +2 -0
- package/dist/deployment/index.js +2 -0
- package/dist/deployment.d.ts +24 -0
- package/dist/deployment.js +39 -0
- package/dist/extensions/lib/get-extensions-path.js +1 -1
- package/dist/extensions/lib/get-extensions-settings.js +1 -1
- package/dist/extensions/lib/get-extensions.js +1 -1
- package/dist/extensions/lib/get-shared-deps-mapping.js +3 -3
- package/dist/extensions/lib/installation/manager.js +3 -3
- package/dist/extensions/lib/sandbox/register/route.d.ts +1 -1
- package/dist/extensions/lib/sync/status.js +1 -1
- package/dist/extensions/lib/sync/sync.js +7 -7
- package/dist/extensions/lib/sync/utils.js +2 -2
- package/dist/extensions/manager.d.ts +1 -1
- package/dist/extensions/manager.js +8 -8
- package/dist/flows.d.ts +1 -1
- package/dist/logger/index.js +1 -1
- package/dist/logger/logs-stream.d.ts +1 -1
- package/dist/logger/logs-stream.js +1 -1
- package/dist/mailer.js +1 -1
- package/dist/metrics/lib/create-metrics.js +2 -2
- package/dist/middleware/authenticate.js +3 -3
- package/dist/middleware/collection-exists.js +1 -1
- package/dist/middleware/extract-token.js +1 -1
- package/dist/middleware/graphql.js +2 -2
- package/dist/middleware/respond.js +27 -14
- package/dist/middleware/validate-batch.js +1 -1
- package/dist/operations/exec/index.js +2 -1
- package/dist/operations/mail/index.js +1 -1
- package/dist/operations/mail/rate-limiter.js +2 -2
- package/dist/permissions/cache.js +5 -0
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +1 -1
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +1 -1
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +2 -2
- package/dist/permissions/modules/process-ast/lib/inject-cases.js +1 -1
- package/dist/permissions/modules/process-ast/process-ast.js +1 -1
- package/dist/permissions/modules/process-ast/utils/find-related-collection.js +1 -1
- package/dist/permissions/modules/process-payload/process-payload.js +1 -1
- package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +14 -2
- package/dist/permissions/modules/validate-access/lib/validate-item-access.js +72 -13
- package/dist/permissions/modules/validate-access/validate-access.js +3 -2
- package/dist/rate-limiter.js +1 -1
- package/dist/request/is-denied-ip.js +1 -1
- package/dist/schedules/project.js +1 -1
- package/dist/schedules/telemetry.js +1 -1
- package/dist/schedules/tus.js +1 -1
- package/dist/server.js +6 -5
- package/dist/services/assets.d.ts +2 -1
- package/dist/services/assets.js +35 -8
- package/dist/services/authentication.js +2 -2
- package/dist/services/collections.js +1 -1
- package/dist/services/deployment-projects.d.ts +20 -0
- package/dist/services/deployment-projects.js +34 -0
- package/dist/services/deployment-runs.d.ts +13 -0
- package/dist/services/deployment-runs.js +6 -0
- package/dist/services/deployment.d.ts +40 -0
- package/dist/services/deployment.js +202 -0
- package/dist/services/extensions.d.ts +1 -1
- package/dist/services/files/utils/get-metadata.d.ts +1 -1
- package/dist/services/files/utils/get-metadata.js +1 -1
- package/dist/services/files.d.ts +1 -1
- package/dist/services/files.js +4 -4
- package/dist/services/graphql/index.d.ts +1 -1
- package/dist/services/graphql/index.js +1 -1
- package/dist/services/graphql/resolvers/mutation.js +1 -1
- package/dist/services/graphql/resolvers/system-admin.js +2 -3
- package/dist/services/graphql/schema/get-types.d.ts +1 -1
- package/dist/services/graphql/schema/read.js +1 -1
- package/dist/services/graphql/subscription.d.ts +1 -1
- package/dist/services/graphql/types/date.js +1 -1
- package/dist/services/graphql/types/hash.js +1 -1
- package/dist/services/graphql/utils/add-path-to-validation-error.js +1 -1
- package/dist/services/graphql/utils/filter-replace-m2a.js +3 -4
- package/dist/services/import-export.d.ts +1 -1
- package/dist/services/import-export.js +2 -2
- package/dist/services/index.d.ts +3 -1
- package/dist/services/index.js +3 -1
- package/dist/services/mail/index.js +2 -2
- package/dist/services/mail/rate-limiter.js +2 -2
- package/dist/services/payload.js +2 -2
- package/dist/services/schema.js +1 -1
- package/dist/services/server.js +13 -4
- package/dist/services/settings.js +2 -2
- package/dist/services/specifications.js +2 -2
- package/dist/services/tfa.js +1 -1
- package/dist/services/translations.js +1 -1
- package/dist/services/tus/data-store.d.ts +1 -3
- package/dist/services/tus/data-store.js +2 -5
- package/dist/services/tus/server.js +6 -6
- package/dist/services/users.js +4 -4
- package/dist/services/versions.js +1 -1
- package/dist/telemetry/lib/get-report.js +2 -0
- package/dist/telemetry/lib/send-report.d.ts +1 -1
- package/dist/telemetry/lib/send-report.js +1 -1
- package/dist/telemetry/lib/track.js +1 -1
- package/dist/telemetry/types/report.d.ts +8 -0
- package/dist/telemetry/utils/get-settings.d.ts +2 -0
- package/dist/telemetry/utils/get-settings.js +5 -0
- package/dist/test-utils/knex.js +1 -1
- package/dist/types/collection.d.ts +1 -1
- package/dist/utils/async-handler.d.ts +1 -1
- package/dist/utils/calculate-field-depth.js +1 -1
- package/dist/utils/compress.js +1 -1
- package/dist/utils/deep-map-response.d.ts +1 -1
- package/dist/utils/deep-map-response.js +2 -2
- package/dist/utils/get-cache-key.js +1 -1
- package/dist/utils/get-column-path.js +1 -1
- package/dist/utils/get-field-system-rows.js +1 -1
- package/dist/utils/get-ip-from-req.d.ts +1 -1
- package/dist/utils/get-ip-from-req.js +1 -1
- package/dist/utils/get-local-type.js +7 -3
- package/dist/utils/get-service.js +7 -3
- package/dist/utils/get-snapshot-diff.js +1 -1
- package/dist/utils/is-field-allowed.d.ts +4 -0
- package/dist/utils/is-field-allowed.js +9 -0
- package/dist/utils/is-url-allowed.js +1 -1
- package/dist/utils/jwt.js +1 -1
- package/dist/utils/sanitize-schema.d.ts +1 -1
- package/dist/utils/should-clear-cache.d.ts +1 -1
- package/dist/utils/should-skip-cache.js +2 -2
- package/dist/utils/validate-diff.js +1 -1
- package/dist/utils/validate-snapshot.js +3 -3
- package/dist/utils/validate-storage.js +2 -2
- package/dist/utils/verify-session-jwt.js +1 -1
- package/dist/utils/versioning/handle-version.js +1 -1
- package/dist/websocket/collab/calculate-cache-metadata.d.ts +9 -0
- package/dist/websocket/collab/calculate-cache-metadata.js +121 -0
- package/dist/websocket/collab/collab.d.ts +63 -0
- package/dist/websocket/collab/collab.js +481 -0
- package/dist/websocket/collab/constants.d.ts +1 -0
- package/dist/websocket/collab/constants.js +13 -0
- package/dist/websocket/collab/filter-to-fields.d.ts +2 -0
- package/dist/websocket/collab/filter-to-fields.js +11 -0
- package/dist/websocket/collab/messenger.d.ts +43 -0
- package/dist/websocket/collab/messenger.js +225 -0
- package/dist/websocket/collab/payload-permissions.d.ts +18 -0
- package/dist/websocket/collab/payload-permissions.js +158 -0
- package/dist/websocket/collab/permissions-cache.d.ts +52 -0
- package/dist/websocket/collab/permissions-cache.js +204 -0
- package/dist/websocket/collab/room.d.ts +125 -0
- package/dist/websocket/collab/room.js +593 -0
- package/dist/websocket/collab/store.d.ts +7 -0
- package/dist/websocket/collab/store.js +33 -0
- package/dist/websocket/collab/types.d.ts +21 -0
- package/dist/websocket/collab/types.js +1 -0
- package/dist/websocket/collab/verify-permissions.d.ts +11 -0
- package/dist/websocket/collab/verify-permissions.js +100 -0
- package/dist/websocket/controllers/base.d.ts +2 -2
- package/dist/websocket/controllers/base.js +3 -3
- package/dist/websocket/controllers/graphql.d.ts +1 -1
- package/dist/websocket/controllers/graphql.js +1 -1
- package/dist/websocket/controllers/logs.d.ts +1 -1
- package/dist/websocket/controllers/rest.d.ts +1 -1
- package/dist/websocket/controllers/rest.js +2 -2
- package/dist/websocket/handlers/heartbeat.js +1 -1
- package/dist/websocket/handlers/index.d.ts +2 -0
- package/dist/websocket/handlers/index.js +9 -0
- package/dist/websocket/handlers/items.js +2 -2
- package/dist/websocket/handlers/subscribe.js +1 -1
- package/dist/websocket/types.d.ts +1 -1
- package/dist/websocket/utils/items.d.ts +2 -2
- package/dist/websocket/utils/message.d.ts +1 -1
- package/dist/websocket/utils/message.js +2 -2
- package/dist/websocket/utils/wait-for-message.js +1 -1
- package/package.json +35 -33
- package/dist/controllers/webhooks.js +0 -74
- package/dist/services/webhooks.d.ts +0 -14
- package/dist/services/webhooks.js +0 -32
- package/dist/utils/get-relation-info.d.ts +0 -6
- package/dist/utils/get-relation-info.js +0 -43
- package/dist/utils/get-relation-type.d.ts +0 -6
- package/dist/utils/get-relation-type.js +0 -18
- package/dist/utils/is-login-redirect-allowed.d.ts +0 -4
- package/dist/utils/versioning/deep-map-with-schema.d.ts +0 -23
- package/dist/utils/versioning/deep-map-with-schema.js +0 -81
- /package/dist/controllers/{webhooks.d.ts → deployment.d.ts} +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { useLogger } from '../../logger/index.js';
|
|
2
|
+
import { fetchPermissions } from '../../permissions/lib/fetch-permissions.js';
|
|
3
|
+
import { fetchPolicies } from '../../permissions/lib/fetch-policies.js';
|
|
4
|
+
import { fetchAllowedFields } from '../../permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js';
|
|
5
|
+
import { validateItemAccess } from '../../permissions/modules/validate-access/lib/validate-item-access.js';
|
|
6
|
+
import { extractRequiredDynamicVariableContextForPermissions } from '../../permissions/utils/extract-required-dynamic-variable-context.js';
|
|
7
|
+
import { fetchDynamicVariableData } from '../../permissions/utils/fetch-dynamic-variable-data.js';
|
|
8
|
+
import { processPermissions } from '../../permissions/utils/process-permissions.js';
|
|
9
|
+
import { getService } from '../../utils/get-service.js';
|
|
10
|
+
import { calculateCacheMetadata } from './calculate-cache-metadata.js';
|
|
11
|
+
import { filterToFields } from './filter-to-fields.js';
|
|
12
|
+
import { permissionCache } from './permissions-cache.js';
|
|
13
|
+
/**
|
|
14
|
+
* Verify if a client has permissions to perform an action on the item.
|
|
15
|
+
* - `string[]`: List of fields the client has access to, empty if item exists but access is restricted.
|
|
16
|
+
* - `null`: Indicates the item doesn't exist.
|
|
17
|
+
*/
|
|
18
|
+
export async function verifyPermissions(accountability, collection, item, action = 'read', options) {
|
|
19
|
+
if (!accountability)
|
|
20
|
+
return [];
|
|
21
|
+
const { schema, knex } = options;
|
|
22
|
+
if (!schema.collections[collection])
|
|
23
|
+
return [];
|
|
24
|
+
if (accountability.admin)
|
|
25
|
+
return ['*'];
|
|
26
|
+
const cached = permissionCache.get(accountability, collection, String(item), action);
|
|
27
|
+
if (cached !== undefined)
|
|
28
|
+
return cached;
|
|
29
|
+
// Prevent caching stale permissions if invalidation occurs during async steps
|
|
30
|
+
const startInvalidationCount = permissionCache.getInvalidationCount();
|
|
31
|
+
let itemData = null;
|
|
32
|
+
try {
|
|
33
|
+
const adminService = getService(collection, { schema, knex });
|
|
34
|
+
const policies = await fetchPolicies(accountability, { knex, schema });
|
|
35
|
+
const rawPermissions = await fetchPermissions({ action, collections: [collection], policies, accountability, bypassDynamicVariableProcessing: true }, { knex, schema });
|
|
36
|
+
// Check for item-level rules to skip DB fetch
|
|
37
|
+
const hasItemRules = rawPermissions.some((p) => p.permissions && Object.keys(p.permissions).length > 0);
|
|
38
|
+
if (hasItemRules) {
|
|
39
|
+
// Resolve dynamic variables used in the permission filters
|
|
40
|
+
const dynamicVariableContext = extractRequiredDynamicVariableContextForPermissions(rawPermissions);
|
|
41
|
+
const permissionsContext = await fetchDynamicVariableData({ accountability, policies, dynamicVariableContext }, { knex, schema });
|
|
42
|
+
const processedPermissions = processPermissions({
|
|
43
|
+
permissions: rawPermissions,
|
|
44
|
+
accountability,
|
|
45
|
+
permissionsContext,
|
|
46
|
+
});
|
|
47
|
+
const fieldsToFetch = processedPermissions
|
|
48
|
+
.map((perm) => (perm.permissions ? filterToFields(perm.permissions, collection, schema) : []))
|
|
49
|
+
.flat();
|
|
50
|
+
// Fetch current item data to evaluate any conditional permission filters based on record state
|
|
51
|
+
if (item && action !== 'create') {
|
|
52
|
+
try {
|
|
53
|
+
itemData = await adminService.readOne(item, {
|
|
54
|
+
fields: fieldsToFetch,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Item doesn't exist
|
|
59
|
+
permissionCache.set(accountability, collection, String(item), action, null, []);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (schema.collections[collection]?.singleton && action !== 'create') {
|
|
64
|
+
const pkField = schema.collections[collection].primary;
|
|
65
|
+
if (pkField) {
|
|
66
|
+
if (Array.from(fieldsToFetch).some((field) => field === '*' || field === pkField) === false) {
|
|
67
|
+
fieldsToFetch.push(pkField);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
itemData = await adminService.readSingleton({ fields: fieldsToFetch });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
let allowedFields = [];
|
|
74
|
+
if ((item || schema.collections[collection]?.singleton) && hasItemRules) {
|
|
75
|
+
const primaryKeys = item ? [item] : [];
|
|
76
|
+
const validationContext = {
|
|
77
|
+
collection,
|
|
78
|
+
accountability,
|
|
79
|
+
action,
|
|
80
|
+
primaryKeys,
|
|
81
|
+
returnAllowedRootFields: true,
|
|
82
|
+
};
|
|
83
|
+
allowedFields = (await validateItemAccess(validationContext, { knex, schema })).allowedRootFields || [];
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
allowedFields = await fetchAllowedFields({ accountability, action, collection }, { knex, schema });
|
|
87
|
+
}
|
|
88
|
+
// Only cache if the state hasn't been invalidated by another operation in the meantime
|
|
89
|
+
if (permissionCache.getInvalidationCount() === startInvalidationCount) {
|
|
90
|
+
// Determine TTL and relational dependencies for cache invalidation
|
|
91
|
+
const { ttlMs, dependencies } = calculateCacheMetadata(collection, itemData, rawPermissions, schema, accountability);
|
|
92
|
+
permissionCache.set(accountability, collection, String(item), action, allowedFields, dependencies, ttlMs);
|
|
93
|
+
}
|
|
94
|
+
return allowedFields;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
useLogger().error(err, `[Collab] verifyPermissions failed for user "${accountability.user}", collection "${collection}", and item "${item}"`);
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { Server as httpServer, IncomingMessage } from 'http';
|
|
2
|
+
import type internal from 'stream';
|
|
1
3
|
import type { Accountability } from '@directus/types';
|
|
2
4
|
import { WebSocketMessage } from '@directus/types';
|
|
3
|
-
import type { IncomingMessage, Server as httpServer } from 'http';
|
|
4
5
|
import type { RateLimiterAbstract } from 'rate-limiter-flexible';
|
|
5
|
-
import type internal from 'stream';
|
|
6
6
|
import WebSocket, { type Server } from 'ws';
|
|
7
7
|
import { WebSocketAuthMessage } from '../messages.js';
|
|
8
8
|
import type { AuthenticationState, UpgradeContext, WebSocketAuthentication, WebSocketClient } from '../types.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { parse } from 'url';
|
|
1
3
|
import { useEnv } from '@directus/env';
|
|
2
4
|
import { InvalidProviderConfigError, TokenExpiredError } from '@directus/errors';
|
|
3
5
|
import { WebSocketMessage } from '@directus/types';
|
|
4
6
|
import { parseJSON, toBoolean } from '@directus/utils';
|
|
5
7
|
import cookie from 'cookie';
|
|
6
|
-
import { randomUUID } from 'node:crypto';
|
|
7
|
-
import { parse } from 'url';
|
|
8
8
|
import WebSocket, { WebSocketServer } from 'ws';
|
|
9
9
|
import { fromZodError } from 'zod-validation-error';
|
|
10
10
|
import emitter from '../../emitter.js';
|
|
@@ -13,7 +13,7 @@ import { createDefaultAccountability } from '../../permissions/utils/create-defa
|
|
|
13
13
|
import { createRateLimiter } from '../../rate-limiter.js';
|
|
14
14
|
import { getIPFromReq } from '../../utils/get-ip-from-req.js';
|
|
15
15
|
import { authenticateConnection, authenticationSuccess } from '../authenticate.js';
|
|
16
|
-
import {
|
|
16
|
+
import { handleWebSocketError, WebSocketError } from '../errors.js';
|
|
17
17
|
import { AuthMode, WebSocketAuthMessage } from '../messages.js';
|
|
18
18
|
import { getMessageType } from '../utils/message.js';
|
|
19
19
|
import { waitForAnyMessage, waitForMessageType } from '../utils/wait-for-message.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Server } from 'graphql-ws';
|
|
2
1
|
import type { Server as httpServer } from 'http';
|
|
2
|
+
import type { Server } from 'graphql-ws';
|
|
3
3
|
import type { GraphQLSocket, UpgradeContext, WebSocketClient } from '../types.js';
|
|
4
4
|
import SocketController from './base.js';
|
|
5
5
|
export declare class GraphQLSubscriptionController extends SocketController {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CloseCode,
|
|
1
|
+
import { CloseCode, makeServer, MessageType } from 'graphql-ws';
|
|
2
2
|
import { useLogger } from '../../logger/index.js';
|
|
3
3
|
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
4
4
|
import { bindPubSub } from '../../services/graphql/subscription.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Server as httpServer } from 'http';
|
|
2
|
+
import type { Accountability } from '@directus/types';
|
|
2
3
|
import { AuthMode } from '../messages.js';
|
|
3
4
|
import SocketController from './base.js';
|
|
4
|
-
import type { Accountability } from '@directus/types';
|
|
5
5
|
export declare class LogsController extends SocketController {
|
|
6
6
|
constructor(httpServer: httpServer);
|
|
7
7
|
getEnvironmentConfig(configPrefix: string): {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { WebSocketMessage } from '@directus/types';
|
|
2
1
|
import type { Server as httpServer } from 'http';
|
|
2
|
+
import { WebSocketMessage } from '@directus/types';
|
|
3
3
|
import SocketController from './base.js';
|
|
4
4
|
export declare class WebSocketController extends SocketController {
|
|
5
5
|
constructor(httpServer: httpServer);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { parseJSON } from '@directus/utils';
|
|
2
1
|
import { WebSocketMessage } from '@directus/types';
|
|
2
|
+
import { parseJSON } from '@directus/utils';
|
|
3
3
|
import emitter from '../../emitter.js';
|
|
4
4
|
import { useLogger } from '../../logger/index.js';
|
|
5
5
|
import { getAddress } from '../../utils/get-address.js';
|
|
6
|
-
import {
|
|
6
|
+
import { handleWebSocketError, WebSocketError } from '../errors.js';
|
|
7
7
|
import SocketController from './base.js';
|
|
8
8
|
import { registerWebSocketEvents } from './hooks.js';
|
|
9
9
|
const logger = useLogger();
|
|
@@ -3,7 +3,7 @@ import { ServiceUnavailableError } from '@directus/errors';
|
|
|
3
3
|
import { WebSocketMessage } from '@directus/types';
|
|
4
4
|
import { toBoolean } from '@directus/utils';
|
|
5
5
|
import emitter from '../../emitter.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getWebSocketController, WebSocketController } from '../controllers/index.js';
|
|
7
7
|
import { fmtMessage, getMessageType } from '../utils/message.js';
|
|
8
8
|
const env = useEnv();
|
|
9
9
|
const HEARTBEAT_FREQUENCY = Number(env['WEBSOCKETS_HEARTBEAT_PERIOD']) * 1000;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { CollabHandler } from '../collab/collab.js';
|
|
1
2
|
export declare function startWebSocketHandlers(): void;
|
|
3
|
+
export declare function getCollabHandler(): CollabHandler | undefined;
|
|
2
4
|
export * from './heartbeat.js';
|
|
3
5
|
export * from './items.js';
|
|
4
6
|
export * from './logs.js';
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { useEnv } from '@directus/env';
|
|
2
2
|
import { toBoolean } from '@directus/utils';
|
|
3
|
+
import { CollabHandler } from '../collab/collab.js';
|
|
3
4
|
import { HeartbeatHandler } from './heartbeat.js';
|
|
4
5
|
import { ItemsHandler } from './items.js';
|
|
5
6
|
import { LogsHandler } from './logs.js';
|
|
6
7
|
import { SubscribeHandler } from './subscribe.js';
|
|
8
|
+
let collabHandler;
|
|
7
9
|
export function startWebSocketHandlers() {
|
|
8
10
|
const env = useEnv();
|
|
9
11
|
const heartbeatEnabled = toBoolean(env['WEBSOCKETS_HEARTBEAT_ENABLED']);
|
|
10
12
|
const restEnabled = toBoolean(env['WEBSOCKETS_REST_ENABLED']);
|
|
11
13
|
const graphqlEnabled = toBoolean(env['WEBSOCKETS_GRAPHQL_ENABLED']);
|
|
12
14
|
const logsEnabled = toBoolean(env['WEBSOCKETS_LOGS_ENABLED']);
|
|
15
|
+
const collabEnabled = toBoolean(env['WEBSOCKETS_COLLAB_ENABLED']);
|
|
13
16
|
if (restEnabled && heartbeatEnabled) {
|
|
14
17
|
new HeartbeatHandler();
|
|
15
18
|
}
|
|
@@ -22,6 +25,12 @@ export function startWebSocketHandlers() {
|
|
|
22
25
|
if (logsEnabled) {
|
|
23
26
|
new LogsHandler();
|
|
24
27
|
}
|
|
28
|
+
if (collabEnabled) {
|
|
29
|
+
collabHandler = new CollabHandler();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function getCollabHandler() {
|
|
33
|
+
return collabHandler;
|
|
25
34
|
}
|
|
26
35
|
export * from './heartbeat.js';
|
|
27
36
|
export * from './items.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { isSystemCollection } from '@directus/system-data';
|
|
1
2
|
import emitter from '../../emitter.js';
|
|
2
3
|
import { ItemsService, MetaService } from '../../services/index.js';
|
|
3
4
|
import { getSchema } from '../../utils/get-schema.js';
|
|
4
|
-
import { isSystemCollection } from '@directus/system-data';
|
|
5
5
|
import { sanitizeQuery } from '../../utils/sanitize-query.js';
|
|
6
|
-
import {
|
|
6
|
+
import { handleWebSocketError, WebSocketError } from '../errors.js';
|
|
7
7
|
import { WebSocketItemsMessage } from '../messages.js';
|
|
8
8
|
import { fmtMessage, getMessageType } from '../utils/message.js';
|
|
9
9
|
export class ItemsHandler {
|
|
@@ -4,7 +4,7 @@ import { useBus } from '../../bus/index.js';
|
|
|
4
4
|
import emitter from '../../emitter.js';
|
|
5
5
|
import { getSchema } from '../../utils/get-schema.js';
|
|
6
6
|
import { sanitizeQuery } from '../../utils/sanitize-query.js';
|
|
7
|
-
import {
|
|
7
|
+
import { handleWebSocketError, WebSocketError } from '../errors.js';
|
|
8
8
|
import { WebSocketSubscribeMessage } from '../messages.js';
|
|
9
9
|
import { getPayload } from '../utils/items.js';
|
|
10
10
|
import { fmtMessage, getMessageType } from '../utils/message.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Accountability, Query } from '@directus/types';
|
|
2
1
|
import type { IncomingMessage } from 'http';
|
|
3
2
|
import type internal from 'stream';
|
|
3
|
+
import type { Accountability, Query } from '@directus/types';
|
|
4
4
|
import type { WebSocket } from 'ws';
|
|
5
5
|
import type { AuthMode } from './messages.js';
|
|
6
6
|
export type AuthenticationState = {
|
|
@@ -20,7 +20,7 @@ export declare function getPayload(subscription: PSubscription, accountability:
|
|
|
20
20
|
* @param event Event data
|
|
21
21
|
* @returns the fetched collection data
|
|
22
22
|
*/
|
|
23
|
-
export declare function getCollectionPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<string | number | import("../../types/collection.js").Collection |
|
|
23
|
+
export declare function getCollectionPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<string | number | (string | number)[] | import("../../types/collection.js").Collection | import("../../types/collection.js").Collection[]>;
|
|
24
24
|
/**
|
|
25
25
|
* Get fields items
|
|
26
26
|
*
|
|
@@ -29,7 +29,7 @@ export declare function getCollectionPayload(subscription: PSubscription, accoun
|
|
|
29
29
|
* @param event Event data
|
|
30
30
|
* @returns the fetched field data
|
|
31
31
|
*/
|
|
32
|
-
export declare function getFieldsPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<string | number | Record<string, any> | import("@directus/types").Field[]
|
|
32
|
+
export declare function getFieldsPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<string | number | Record<string, any> | (string | number)[] | import("@directus/types").Field[]>;
|
|
33
33
|
/**
|
|
34
34
|
* Get items from a collection using the appropriate service
|
|
35
35
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { WebSocketClient } from '../types.js';
|
|
2
2
|
export declare const fmtMessage: (type: string, data?: Record<string, any>, uid?: string | number) => string;
|
|
3
3
|
export declare const safeSend: (client: WebSocketClient, data: string, delay?: number) => Promise<unknown>;
|
|
4
|
-
export declare
|
|
4
|
+
export declare function getMessageType(message: unknown): string;
|
|
@@ -22,6 +22,6 @@ export const safeSend = async (client, data, delay = 100) => {
|
|
|
22
22
|
return true;
|
|
23
23
|
};
|
|
24
24
|
// an often used message type extractor function
|
|
25
|
-
export
|
|
25
|
+
export function getMessageType(message) {
|
|
26
26
|
return typeof message !== 'object' || Array.isArray(message) || message === null ? '' : String(message.type);
|
|
27
|
-
}
|
|
27
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseJSON } from '@directus/utils';
|
|
2
1
|
import { WebSocketMessage } from '@directus/types';
|
|
2
|
+
import { parseJSON } from '@directus/utils';
|
|
3
3
|
import { getMessageType } from './message.js';
|
|
4
4
|
export const waitForAnyMessage = (client, timeout) => {
|
|
5
5
|
return new Promise((resolve, reject) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "33.1.0",
|
|
4
4
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"directus",
|
|
@@ -58,19 +58,21 @@
|
|
|
58
58
|
"dist"
|
|
59
59
|
],
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@ai-sdk/anthropic": "3.0.
|
|
62
|
-
"@ai-sdk/
|
|
61
|
+
"@ai-sdk/anthropic": "3.0.9",
|
|
62
|
+
"@ai-sdk/google": "3.0.6",
|
|
63
|
+
"@ai-sdk/openai": "3.0.7",
|
|
64
|
+
"@ai-sdk/openai-compatible": "2.0.4",
|
|
63
65
|
"@authenio/samlify-node-xmllint": "2.0.0",
|
|
64
66
|
"@aws-sdk/client-sesv2": "3.928.0",
|
|
65
67
|
"@godaddy/terminus": "4.12.1",
|
|
66
|
-
"@modelcontextprotocol/sdk": "1.
|
|
68
|
+
"@modelcontextprotocol/sdk": "1.26.0",
|
|
67
69
|
"@rollup/plugin-alias": "5.1.1",
|
|
68
70
|
"@rollup/plugin-node-resolve": "16.0.3",
|
|
69
71
|
"@rollup/plugin-virtual": "3.0.2",
|
|
70
72
|
"@tus/server": "2.3.0",
|
|
71
73
|
"@tus/utils": "0.6.0",
|
|
74
|
+
"ai": "6.0.25",
|
|
72
75
|
"archiver": "7.0.1",
|
|
73
|
-
"ai": "6.0.0-beta.98",
|
|
74
76
|
"argon2": "0.44.0",
|
|
75
77
|
"async": "3.2.6",
|
|
76
78
|
"async-mutex": "0.5.0",
|
|
@@ -114,7 +116,7 @@
|
|
|
114
116
|
"jsonwebtoken": "9.0.3",
|
|
115
117
|
"keyv": "5.5.3",
|
|
116
118
|
"knex": "3.1.0",
|
|
117
|
-
"
|
|
119
|
+
"ldapts": "8.1.3",
|
|
118
120
|
"liquidjs": "10.24.0",
|
|
119
121
|
"lodash-es": "4.17.21",
|
|
120
122
|
"marked": "16.4.1",
|
|
@@ -125,7 +127,7 @@
|
|
|
125
127
|
"ms": "2.1.3",
|
|
126
128
|
"nanoid": "5.1.6",
|
|
127
129
|
"node-machine-id": "1.1.12",
|
|
128
|
-
"nodemailer": "7.0.
|
|
130
|
+
"nodemailer": "7.0.11",
|
|
129
131
|
"object-hash": "3.0.0",
|
|
130
132
|
"openapi3-ts": "4.5.0",
|
|
131
133
|
"openid-client": "5.7.1",
|
|
@@ -138,10 +140,10 @@
|
|
|
138
140
|
"pino-http": "10.5.0",
|
|
139
141
|
"pino-http-print": "3.1.0",
|
|
140
142
|
"pino-pretty": "13.1.2",
|
|
141
|
-
"pm2": "6.0.
|
|
143
|
+
"pm2": "6.0.14",
|
|
142
144
|
"prom-client": "15.1.3",
|
|
143
145
|
"proxy-addr": "2.0.7",
|
|
144
|
-
"qs": "6.14.
|
|
146
|
+
"qs": "6.14.1",
|
|
145
147
|
"rate-limiter-flexible": "7.2.0",
|
|
146
148
|
"rolldown": "1.0.0-beta.31",
|
|
147
149
|
"rollup": "4.52.5",
|
|
@@ -151,37 +153,38 @@
|
|
|
151
153
|
"sharp": "0.34.5",
|
|
152
154
|
"snappy": "7.3.3",
|
|
153
155
|
"stream-json": "1.9.1",
|
|
154
|
-
"tar": "7.5.
|
|
156
|
+
"tar": "7.5.4",
|
|
155
157
|
"tsx": "4.20.6",
|
|
156
158
|
"uuid": "11.1.0",
|
|
157
159
|
"wellknown": "0.5.0",
|
|
158
160
|
"ws": "8.18.3",
|
|
159
161
|
"zod": "4.1.12",
|
|
160
162
|
"zod-validation-error": "4.0.2",
|
|
161
|
-
"@directus/
|
|
162
|
-
"@directus/
|
|
163
|
-
"@directus/
|
|
164
|
-
"@directus/extensions
|
|
163
|
+
"@directus/ai": "1.1.0",
|
|
164
|
+
"@directus/app": "15.1.0",
|
|
165
|
+
"@directus/env": "5.5.0",
|
|
166
|
+
"@directus/extensions": "3.0.17",
|
|
165
167
|
"@directus/constants": "14.0.0",
|
|
166
|
-
"@directus/
|
|
167
|
-
"@directus/
|
|
168
|
+
"@directus/errors": "2.2.0",
|
|
169
|
+
"@directus/extensions-registry": "3.0.17",
|
|
170
|
+
"@directus/memory": "3.1.0",
|
|
168
171
|
"@directus/format-title": "12.1.1",
|
|
169
|
-
"@directus/
|
|
170
|
-
"@directus/
|
|
171
|
-
"@directus/
|
|
172
|
+
"@directus/pressure": "3.0.15",
|
|
173
|
+
"@directus/schema": "13.0.5",
|
|
174
|
+
"@directus/extensions-sdk": "17.0.6",
|
|
175
|
+
"@directus/schema-builder": "0.0.12",
|
|
176
|
+
"@directus/specs": "12.0.0",
|
|
172
177
|
"@directus/storage": "12.0.3",
|
|
173
|
-
"@directus/
|
|
174
|
-
"@directus/
|
|
175
|
-
"@directus/storage-driver-
|
|
176
|
-
"@directus/storage-driver-cloudinary": "12.0.13",
|
|
177
|
-
"@directus/storage-driver-gcs": "12.0.13",
|
|
178
|
+
"@directus/storage-driver-azure": "12.0.15",
|
|
179
|
+
"@directus/storage-driver-s3": "12.1.1",
|
|
180
|
+
"@directus/storage-driver-gcs": "12.0.15",
|
|
178
181
|
"@directus/storage-driver-local": "12.0.3",
|
|
179
|
-
"@directus/
|
|
180
|
-
"@directus/
|
|
181
|
-
"@directus/utils": "13.
|
|
182
|
-
"
|
|
183
|
-
"@directus/
|
|
184
|
-
"directus": "
|
|
182
|
+
"@directus/storage-driver-supabase": "3.0.15",
|
|
183
|
+
"@directus/system-data": "4.1.0",
|
|
184
|
+
"@directus/utils": "13.2.0",
|
|
185
|
+
"directus": "11.15.0",
|
|
186
|
+
"@directus/validation": "2.0.15",
|
|
187
|
+
"@directus/storage-driver-cloudinary": "12.0.15"
|
|
185
188
|
},
|
|
186
189
|
"devDependencies": {
|
|
187
190
|
"@directus/tsconfig": "3.0.0",
|
|
@@ -204,7 +207,6 @@
|
|
|
204
207
|
"@types/js-yaml": "4.0.9",
|
|
205
208
|
"@types/json2csv": "5.0.7",
|
|
206
209
|
"@types/jsonwebtoken": "9.0.10",
|
|
207
|
-
"@types/ldapjs": "2.2.5",
|
|
208
210
|
"@types/lodash-es": "4.17.12",
|
|
209
211
|
"@types/mime-types": "3.0.1",
|
|
210
212
|
"@types/ms": "2.1.0",
|
|
@@ -225,8 +227,8 @@
|
|
|
225
227
|
"knex-mock-client": "3.0.2",
|
|
226
228
|
"typescript": "5.9.3",
|
|
227
229
|
"vitest": "3.2.4",
|
|
228
|
-
"@directus/schema-builder": "0.0.
|
|
229
|
-
"@directus/types": "
|
|
230
|
+
"@directus/schema-builder": "0.0.12",
|
|
231
|
+
"@directus/types": "14.1.0"
|
|
230
232
|
},
|
|
231
233
|
"optionalDependencies": {
|
|
232
234
|
"@keyv/redis": "3.0.1",
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { ErrorCode, createError } from '@directus/errors';
|
|
2
|
-
import express from 'express';
|
|
3
|
-
import { respond } from '../middleware/respond.js';
|
|
4
|
-
import useCollection from '../middleware/use-collection.js';
|
|
5
|
-
import { validateBatch } from '../middleware/validate-batch.js';
|
|
6
|
-
import { MetaService } from '../services/meta.js';
|
|
7
|
-
import { WebhooksService } from '../services/webhooks.js';
|
|
8
|
-
import asyncHandler from '../utils/async-handler.js';
|
|
9
|
-
import { sanitizeQuery } from '../utils/sanitize-query.js';
|
|
10
|
-
const router = express.Router();
|
|
11
|
-
router.use(useCollection('directus_webhooks'));
|
|
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))();
|
|
15
|
-
}), respond);
|
|
16
|
-
const readHandler = asyncHandler(async (req, res, next) => {
|
|
17
|
-
const service = new WebhooksService({
|
|
18
|
-
accountability: req.accountability,
|
|
19
|
-
schema: req.schema,
|
|
20
|
-
});
|
|
21
|
-
const metaService = new MetaService({
|
|
22
|
-
accountability: req.accountability,
|
|
23
|
-
schema: req.schema,
|
|
24
|
-
});
|
|
25
|
-
const records = await service.readByQuery(req.sanitizedQuery);
|
|
26
|
-
const meta = await metaService.getMetaForQuery(req.collection, req.sanitizedQuery);
|
|
27
|
-
res.locals['payload'] = { data: records || null, meta };
|
|
28
|
-
return next();
|
|
29
|
-
});
|
|
30
|
-
router.get('/', validateBatch('read'), readHandler, respond);
|
|
31
|
-
router.search('/', validateBatch('read'), readHandler, respond);
|
|
32
|
-
router.get('/:pk', asyncHandler(async (req, res, next) => {
|
|
33
|
-
const service = new WebhooksService({
|
|
34
|
-
accountability: req.accountability,
|
|
35
|
-
schema: req.schema,
|
|
36
|
-
});
|
|
37
|
-
const record = await service.readOne(req.params['pk'], req.sanitizedQuery);
|
|
38
|
-
res.locals['payload'] = { data: record || null };
|
|
39
|
-
return next();
|
|
40
|
-
}), respond);
|
|
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))();
|
|
44
|
-
}), respond);
|
|
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))();
|
|
48
|
-
}), respond);
|
|
49
|
-
router.delete('/', asyncHandler(async (req, _res, next) => {
|
|
50
|
-
const service = new WebhooksService({
|
|
51
|
-
accountability: req.accountability,
|
|
52
|
-
schema: req.schema,
|
|
53
|
-
});
|
|
54
|
-
if (Array.isArray(req.body)) {
|
|
55
|
-
await service.deleteMany(req.body);
|
|
56
|
-
}
|
|
57
|
-
else if (req.body.keys) {
|
|
58
|
-
await service.deleteMany(req.body.keys);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
const sanitizedQuery = await sanitizeQuery(req.body.query, req.schema, req.accountability);
|
|
62
|
-
await service.deleteByQuery(sanitizedQuery);
|
|
63
|
-
}
|
|
64
|
-
return next();
|
|
65
|
-
}), respond);
|
|
66
|
-
router.delete('/:pk', asyncHandler(async (req, _res, next) => {
|
|
67
|
-
const service = new WebhooksService({
|
|
68
|
-
accountability: req.accountability,
|
|
69
|
-
schema: req.schema,
|
|
70
|
-
});
|
|
71
|
-
await service.deleteOne(req.params['pk']);
|
|
72
|
-
return next();
|
|
73
|
-
}), respond);
|
|
74
|
-
export default router;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { type DirectusError } from '@directus/errors';
|
|
2
|
-
import type { Bus } from '@directus/memory';
|
|
3
|
-
import type { AbstractServiceOptions, MutationOptions, PrimaryKey, Webhook } from '@directus/types';
|
|
4
|
-
import { ItemsService } from './items.js';
|
|
5
|
-
export declare class WebhooksService extends ItemsService<Webhook> {
|
|
6
|
-
messenger: Bus;
|
|
7
|
-
errorDeprecation: DirectusError;
|
|
8
|
-
constructor(options: AbstractServiceOptions);
|
|
9
|
-
createOne(): Promise<PrimaryKey>;
|
|
10
|
-
createMany(): Promise<PrimaryKey[]>;
|
|
11
|
-
updateBatch(): Promise<PrimaryKey[]>;
|
|
12
|
-
updateMany(): Promise<PrimaryKey[]>;
|
|
13
|
-
deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
14
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { ErrorCode, createError } from '@directus/errors';
|
|
2
|
-
import { useBus } from '../bus/index.js';
|
|
3
|
-
import { useLogger } from '../logger/index.js';
|
|
4
|
-
import { ItemsService } from './items.js';
|
|
5
|
-
const logger = useLogger();
|
|
6
|
-
export class WebhooksService extends ItemsService {
|
|
7
|
-
messenger;
|
|
8
|
-
errorDeprecation;
|
|
9
|
-
constructor(options) {
|
|
10
|
-
super('directus_webhooks', options);
|
|
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');
|
|
14
|
-
}
|
|
15
|
-
async createOne() {
|
|
16
|
-
throw this.errorDeprecation;
|
|
17
|
-
}
|
|
18
|
-
async createMany() {
|
|
19
|
-
throw this.errorDeprecation;
|
|
20
|
-
}
|
|
21
|
-
async updateBatch() {
|
|
22
|
-
throw this.errorDeprecation;
|
|
23
|
-
}
|
|
24
|
-
async updateMany() {
|
|
25
|
-
throw this.errorDeprecation;
|
|
26
|
-
}
|
|
27
|
-
async deleteMany(keys, opts) {
|
|
28
|
-
const result = await super.deleteMany(keys, opts);
|
|
29
|
-
this.messenger.publish('webhooks', { type: 'reload' });
|
|
30
|
-
return result;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { Relation } from '@directus/types';
|
|
2
|
-
export type RelationInfo = {
|
|
3
|
-
relation: Relation | null;
|
|
4
|
-
relationType: 'o2m' | 'm2o' | 'a2o' | 'o2a' | null;
|
|
5
|
-
};
|
|
6
|
-
export declare function getRelationInfo(relations: Relation[], collection: string, field: string): RelationInfo;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { getRelation } from '@directus/utils';
|
|
2
|
-
import { getRelationType } from './get-relation-type.js';
|
|
3
|
-
function checkImplicitRelation(field) {
|
|
4
|
-
if (field.startsWith('$FOLLOW(') && field.endsWith(')')) {
|
|
5
|
-
return field.slice(8, -1).split(',');
|
|
6
|
-
}
|
|
7
|
-
return null;
|
|
8
|
-
}
|
|
9
|
-
export function getRelationInfo(relations, collection, field) {
|
|
10
|
-
if (field.startsWith('$FOLLOW') && field.length > 500) {
|
|
11
|
-
throw new Error(`Implicit $FOLLOW statement is too big to parse. Got: "${field.substring(500)}..."`);
|
|
12
|
-
}
|
|
13
|
-
const implicitRelation = checkImplicitRelation(field);
|
|
14
|
-
if (implicitRelation) {
|
|
15
|
-
if (implicitRelation[2] === undefined) {
|
|
16
|
-
const [m2oCollection, m2oField] = implicitRelation;
|
|
17
|
-
const relation = {
|
|
18
|
-
collection: m2oCollection.trim(),
|
|
19
|
-
field: m2oField.trim(),
|
|
20
|
-
related_collection: collection,
|
|
21
|
-
schema: null,
|
|
22
|
-
meta: null,
|
|
23
|
-
};
|
|
24
|
-
return { relation, relationType: 'o2m' };
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
const [a2oCollection, a2oItemField, a2oCollectionField] = implicitRelation;
|
|
28
|
-
const relation = {
|
|
29
|
-
collection: a2oCollection.trim(),
|
|
30
|
-
field: a2oItemField.trim(),
|
|
31
|
-
related_collection: collection,
|
|
32
|
-
schema: null,
|
|
33
|
-
meta: {
|
|
34
|
-
one_collection_field: a2oCollectionField.trim(),
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
return { relation, relationType: 'o2a' };
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const relation = getRelation(relations, collection, field) ?? null;
|
|
41
|
-
const relationType = relation ? getRelationType({ relation, collection, field }) : null;
|
|
42
|
-
return { relation, relationType };
|
|
43
|
-
}
|