@directus/api 32.1.0 → 32.2.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/constants/system-prompt.d.ts +1 -0
- package/dist/ai/chat/constants/system-prompt.js +51 -0
- package/dist/ai/chat/controllers/chat.post.d.ts +2 -0
- package/dist/ai/chat/controllers/chat.post.js +47 -0
- package/dist/ai/chat/lib/create-ui-stream.d.ts +15 -0
- package/dist/ai/chat/lib/create-ui-stream.js +42 -0
- package/dist/ai/chat/middleware/load-settings.d.ts +2 -0
- package/dist/ai/chat/middleware/load-settings.js +18 -0
- package/dist/ai/chat/models/chat-request.d.ts +34 -0
- package/dist/ai/chat/models/chat-request.js +26 -0
- package/dist/ai/chat/models/providers.d.ts +9 -0
- package/dist/ai/chat/models/providers.js +9 -0
- package/dist/ai/chat/router.d.ts +1 -0
- package/dist/ai/chat/router.js +5 -0
- package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.d.ts +9 -0
- package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.js +38 -0
- package/dist/ai/chat/utils/fix-error-tool-calls.d.ts +12 -0
- package/dist/ai/chat/utils/fix-error-tool-calls.js +30 -0
- package/dist/ai/chat/utils/parse-json-schema-7.d.ts +13 -0
- package/dist/ai/chat/utils/parse-json-schema-7.js +75 -0
- package/dist/{mcp → ai/mcp}/server.d.ts +13 -16
- package/dist/{mcp → ai/mcp}/server.js +4 -13
- package/dist/ai/mcp/types.d.ts +15 -0
- package/dist/{mcp/tools/assets.js → ai/tools/assets/index.js} +8 -5
- package/dist/{mcp/tools/collections.js → ai/tools/collections/index.js} +7 -4
- package/dist/{mcp/tools/fields.js → ai/tools/fields/index.js} +12 -9
- package/dist/{mcp/tools/files.js → ai/tools/files/index.js} +11 -5
- package/dist/{mcp/tools/flows.js → ai/tools/flows/index.js} +11 -5
- package/dist/{mcp/tools/folders.js → ai/tools/folders/index.js} +12 -5
- package/dist/ai/tools/index.d.ts +15 -0
- package/dist/ai/tools/index.js +29 -0
- package/dist/{mcp/tools/items.js → ai/tools/items/index.js} +13 -6
- package/dist/{mcp/tools/prompts/items.md → ai/tools/items/prompt.md} +19 -15
- package/dist/{mcp/tools/operations.d.ts → ai/tools/operations/index.d.ts} +46 -0
- package/dist/{mcp/tools/operations.js → ai/tools/operations/index.js} +12 -5
- package/dist/{mcp/tools/relations.js → ai/tools/relations/index.js} +7 -4
- package/dist/{mcp/tools/schema.d.ts → ai/tools/schema/index.d.ts} +1 -1
- package/dist/{mcp/tools/schema.js → ai/tools/schema/index.js} +9 -6
- package/dist/{mcp/tools/system.js → ai/tools/system/index.js} +7 -4
- package/dist/{mcp/tools/trigger-flow.js → ai/tools/trigger-flow/index.js} +8 -5
- package/dist/{mcp → ai/tools}/types.d.ts +1 -17
- package/dist/ai/tools/utils.d.ts +9 -0
- package/dist/ai/tools/utils.js +17 -0
- package/dist/app.js +5 -0
- package/dist/auth/drivers/oauth2.d.ts +2 -1
- package/dist/auth/drivers/oauth2.js +17 -22
- package/dist/auth/drivers/openid.d.ts +2 -1
- package/dist/auth/drivers/openid.js +13 -18
- package/dist/auth/drivers/saml.js +6 -3
- package/dist/controllers/assets.js +39 -2
- package/dist/controllers/mcp.js +1 -1
- package/dist/database/migrations/20240806A-permissions-policies.js +2 -2
- package/dist/database/migrations/20251103A-add-ai-settings.d.ts +3 -0
- package/dist/database/migrations/20251103A-add-ai-settings.js +14 -0
- package/dist/database/run-ast/run-ast.js +1 -1
- package/dist/extensions/lib/installation/manager.js +5 -9
- package/dist/extensions/lib/sync/status.d.ts +11 -0
- package/dist/extensions/lib/sync/status.js +34 -0
- package/dist/extensions/lib/sync/sync.d.ts +6 -0
- package/dist/extensions/lib/sync/sync.js +90 -0
- package/dist/extensions/lib/sync/tracker.d.ts +18 -0
- package/dist/extensions/lib/sync/tracker.js +71 -0
- package/dist/extensions/lib/sync/utils.d.ts +24 -0
- package/dist/extensions/lib/sync/utils.js +62 -0
- package/dist/extensions/manager.d.ts +8 -4
- package/dist/extensions/manager.js +30 -13
- package/dist/middleware/respond.js +2 -2
- package/dist/permissions/lib/fetch-policies.d.ts +1 -1
- package/dist/permissions/lib/fetch-roles-tree.d.ts +6 -3
- package/dist/permissions/lib/fetch-roles-tree.js +5 -27
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +9 -7
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +17 -9
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +1 -1
- package/dist/permissions/utils/fetch-raw-permissions.d.ts +1 -1
- package/dist/permissions/utils/fetch-share-info.d.ts +1 -1
- package/dist/permissions/utils/fetch-share-info.js +1 -1
- package/dist/permissions/utils/filter-policies-by-ip.js +1 -1
- package/dist/permissions/utils/get-permissions-for-share.js +8 -8
- package/dist/permissions/utils/with-cache.d.ts +8 -6
- package/dist/permissions/utils/with-cache.js +12 -10
- package/dist/request/is-denied-ip.js +2 -2
- package/dist/services/assets/name-deduper.d.ts +7 -0
- package/dist/services/assets/name-deduper.js +23 -0
- package/dist/services/assets.d.ts +15 -2
- package/dist/services/assets.js +98 -5
- package/dist/services/authentication.js +4 -4
- package/dist/services/comments.js +2 -2
- package/dist/services/extensions.js +4 -0
- package/dist/services/folders.d.ts +27 -2
- package/dist/services/folders.js +75 -0
- package/dist/services/graphql/resolvers/query.js +1 -1
- package/dist/services/import-export.d.ts +1 -1
- package/dist/services/import-export.js +4 -5
- package/dist/services/notifications.js +2 -2
- package/dist/services/payload.js +20 -0
- package/dist/services/roles.js +2 -2
- package/dist/services/tus/server.js +3 -3
- package/dist/telemetry/utils/get-settings.d.ts +15 -0
- package/dist/telemetry/utils/get-settings.js +25 -9
- package/dist/test-utils/README.md +95 -24
- package/dist/test-utils/cache.d.ts +2 -2
- package/dist/test-utils/cache.js +2 -2
- package/dist/test-utils/{fields-service.d.ts → services/fields-service.d.ts} +1 -1
- package/dist/test-utils/{fields-service.js → services/fields-service.js} +3 -2
- package/dist/test-utils/services/files-service.d.ts +28 -0
- package/dist/test-utils/services/files-service.js +34 -0
- package/dist/test-utils/services/folders-service.d.ts +28 -0
- package/dist/test-utils/services/folders-service.js +33 -0
- package/dist/utils/encrypt.d.ts +2 -0
- package/dist/utils/encrypt.js +64 -0
- package/dist/utils/get-accountability-for-role.js +2 -2
- package/dist/utils/get-accountability-for-token.js +4 -4
- package/dist/utils/get-cache-key.js +2 -2
- package/dist/utils/is-login-redirect-allowed.d.ts +4 -0
- package/dist/{auth/utils → utils}/is-login-redirect-allowed.js +8 -16
- package/dist/utils/require-text.d.ts +1 -0
- package/dist/utils/require-text.js +4 -0
- package/dist/utils/require-yaml.js +2 -2
- package/package.json +31 -25
- package/dist/auth/utils/generate-callback-url.d.ts +0 -8
- package/dist/auth/utils/generate-callback-url.js +0 -11
- package/dist/auth/utils/is-login-redirect-allowed.d.ts +0 -8
- package/dist/extensions/lib/sync-extensions.d.ts +0 -3
- package/dist/extensions/lib/sync-extensions.js +0 -70
- package/dist/extensions/lib/sync-status.d.ts +0 -10
- package/dist/extensions/lib/sync-status.js +0 -27
- package/dist/mcp/tools/index.d.ts +0 -15
- package/dist/mcp/tools/index.js +0 -29
- package/dist/mcp/tools/prompts/index.d.ts +0 -16
- package/dist/mcp/tools/prompts/index.js +0 -19
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
- package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
- package/dist/utils/get-date-formatted.d.ts +0 -1
- package/dist/utils/get-date-formatted.js +0 -10
- package/dist/utils/ip-in-networks.d.ts +0 -6
- package/dist/utils/ip-in-networks.js +0 -13
- /package/dist/{mcp → ai/mcp}/index.d.ts +0 -0
- /package/dist/{mcp → ai/mcp}/index.js +0 -0
- /package/dist/{mcp → ai/mcp}/transport.d.ts +0 -0
- /package/dist/{mcp → ai/mcp}/transport.js +0 -0
- /package/dist/{mcp → ai/mcp}/types.js +0 -0
- /package/dist/{mcp/tools/assets.d.ts → ai/tools/assets/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/assets.md → ai/tools/assets/prompt.md} +0 -0
- /package/dist/{mcp/tools/collections.d.ts → ai/tools/collections/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/collections.md → ai/tools/collections/prompt.md} +0 -0
- /package/dist/{mcp/define.d.ts → ai/tools/define-tool.d.ts} +0 -0
- /package/dist/{mcp/define.js → ai/tools/define-tool.js} +0 -0
- /package/dist/{mcp/tools/fields.d.ts → ai/tools/fields/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/fields.md → ai/tools/fields/prompt.md} +0 -0
- /package/dist/{mcp/tools/files.d.ts → ai/tools/files/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/files.md → ai/tools/files/prompt.md} +0 -0
- /package/dist/{mcp/tools/flows.d.ts → ai/tools/flows/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/flows.md → ai/tools/flows/prompt.md} +0 -0
- /package/dist/{mcp/tools/folders.d.ts → ai/tools/folders/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/folders.md → ai/tools/folders/prompt.md} +0 -0
- /package/dist/{mcp/tools/items.d.ts → ai/tools/items/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/operations.md → ai/tools/operations/prompt.md} +0 -0
- /package/dist/{mcp/tools/relations.d.ts → ai/tools/relations/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/relations.md → ai/tools/relations/prompt.md} +0 -0
- /package/dist/{mcp/tools/prompts/schema.md → ai/tools/schema/prompt.md} +0 -0
- /package/dist/{mcp → ai/tools}/schema.d.ts +0 -0
- /package/dist/{mcp → ai/tools}/schema.js +0 -0
- /package/dist/{mcp/tools/system.d.ts → ai/tools/system/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/system-prompt-description.md → ai/tools/system/prompt-description.md} +0 -0
- /package/dist/{mcp/tools/prompts/system-prompt.md → ai/tools/system/prompt.md} +0 -0
- /package/dist/{mcp/tools/trigger-flow.d.ts → ai/tools/trigger-flow/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/trigger-flow.md → ai/tools/trigger-flow/prompt.md} +0 -0
- /package/dist/{permissions/modules/fetch-global-access → ai/tools}/types.js +0 -0
- /package/dist/test-utils/{items-service.d.ts → services/items-service.d.ts} +0 -0
- /package/dist/test-utils/{items-service.js → services/items-service.js} +0 -0
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
import { useEnv } from '@directus/env';
|
|
2
2
|
import { toArray } from '@directus/utils';
|
|
3
|
-
import { useLogger } from '
|
|
4
|
-
import isUrlAllowed from '
|
|
3
|
+
import { useLogger } from '../logger/index.js';
|
|
4
|
+
import isUrlAllowed from './is-url-allowed.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @param originUrl Origin URL
|
|
8
|
-
* @param provider OAuth provider name
|
|
9
|
-
* @param redirect URL to redirect to
|
|
10
|
-
* @returns True if the redirect is allowed, false otherwise
|
|
6
|
+
* Checks if the defined redirect after successful SSO login is in the allow list
|
|
11
7
|
*/
|
|
12
|
-
export function isLoginRedirectAllowed(
|
|
8
|
+
export function isLoginRedirectAllowed(redirect, provider) {
|
|
13
9
|
if (!redirect)
|
|
14
10
|
return true; // empty redirect
|
|
15
11
|
if (typeof redirect !== 'string')
|
|
16
12
|
return false; // invalid type
|
|
17
13
|
const env = useEnv();
|
|
18
14
|
const publicUrl = env['PUBLIC_URL'];
|
|
19
|
-
if (
|
|
20
|
-
if (
|
|
15
|
+
if (URL.canParse(redirect) === false) {
|
|
16
|
+
if (redirect.startsWith('//') === false) {
|
|
21
17
|
// should be a relative path like `/admin/test`
|
|
22
18
|
return true;
|
|
23
19
|
}
|
|
@@ -25,10 +21,6 @@ export function isLoginRedirectAllowed(provider, originUrl, redirect) {
|
|
|
25
21
|
return false;
|
|
26
22
|
}
|
|
27
23
|
const { protocol: redirectProtocol, hostname: redirectDomain } = new URL(redirect);
|
|
28
|
-
const redirectUrl = `${redirectProtocol}//${redirectDomain}`;
|
|
29
|
-
// Security check: redirect URL must match the request origin
|
|
30
|
-
if (redirectUrl !== originUrl)
|
|
31
|
-
return false;
|
|
32
24
|
const envKey = `AUTH_${provider.toUpperCase()}_REDIRECT_ALLOW_LIST`;
|
|
33
25
|
if (envKey in env) {
|
|
34
26
|
if (isUrlAllowed(redirect, [...toArray(env[envKey]), publicUrl]))
|
|
@@ -38,7 +30,7 @@ export function isLoginRedirectAllowed(provider, originUrl, redirect) {
|
|
|
38
30
|
useLogger().error('Invalid PUBLIC_URL for login redirect');
|
|
39
31
|
return false;
|
|
40
32
|
}
|
|
41
|
-
const { protocol: publicProtocol, hostname: publicDomain } = new URL(publicUrl);
|
|
42
33
|
// allow redirects to the defined PUBLIC_URL
|
|
43
|
-
|
|
34
|
+
const { protocol: publicProtocol, hostname: publicDomain } = new URL(publicUrl);
|
|
35
|
+
return `${redirectProtocol}//${redirectDomain}` === `${publicProtocol}//${publicDomain}`;
|
|
44
36
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function requireText(filepath: string): string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import fse from 'fs-extra';
|
|
2
1
|
import yaml from 'js-yaml';
|
|
2
|
+
import { requireText } from './require-text.js';
|
|
3
3
|
export function requireYAML(filepath) {
|
|
4
|
-
const yamlRaw =
|
|
4
|
+
const yamlRaw = requireText(filepath);
|
|
5
5
|
return yaml.load(yamlRaw);
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/api",
|
|
3
|
-
"version": "32.
|
|
3
|
+
"version": "32.2.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,15 +58,19 @@
|
|
|
58
58
|
"dist"
|
|
59
59
|
],
|
|
60
60
|
"dependencies": {
|
|
61
|
+
"@ai-sdk/anthropic": "3.0.0-beta.53",
|
|
62
|
+
"@ai-sdk/openai": "3.0.0-beta.57",
|
|
61
63
|
"@authenio/samlify-node-xmllint": "2.0.0",
|
|
62
64
|
"@aws-sdk/client-sesv2": "3.928.0",
|
|
63
65
|
"@godaddy/terminus": "4.12.1",
|
|
64
|
-
"@modelcontextprotocol/sdk": "1.
|
|
66
|
+
"@modelcontextprotocol/sdk": "1.24.0",
|
|
65
67
|
"@rollup/plugin-alias": "5.1.1",
|
|
66
68
|
"@rollup/plugin-node-resolve": "16.0.3",
|
|
67
69
|
"@rollup/plugin-virtual": "3.0.2",
|
|
68
70
|
"@tus/server": "2.3.0",
|
|
69
71
|
"@tus/utils": "0.6.0",
|
|
72
|
+
"archiver": "7.0.1",
|
|
73
|
+
"ai": "6.0.0-beta.98",
|
|
70
74
|
"argon2": "0.44.0",
|
|
71
75
|
"async": "3.2.6",
|
|
72
76
|
"async-mutex": "0.5.0",
|
|
@@ -81,6 +85,7 @@
|
|
|
81
85
|
"cookie": "1.0.2",
|
|
82
86
|
"cookie-parser": "1.4.7",
|
|
83
87
|
"cors": "2.8.5",
|
|
88
|
+
"cron": "4.3.4",
|
|
84
89
|
"date-fns": "4.1.0",
|
|
85
90
|
"deep-diff": "1.0.2",
|
|
86
91
|
"destroy": "1.2.0",
|
|
@@ -106,7 +111,7 @@
|
|
|
106
111
|
"js-yaml": "4.1.1",
|
|
107
112
|
"js2xmlparser": "5.0.0",
|
|
108
113
|
"json2csv": "5.0.7",
|
|
109
|
-
"jsonwebtoken": "9.0.
|
|
114
|
+
"jsonwebtoken": "9.0.3",
|
|
110
115
|
"keyv": "5.5.3",
|
|
111
116
|
"knex": "3.1.0",
|
|
112
117
|
"ldapjs": "2.3.3",
|
|
@@ -120,7 +125,6 @@
|
|
|
120
125
|
"ms": "2.1.3",
|
|
121
126
|
"nanoid": "5.1.6",
|
|
122
127
|
"node-machine-id": "1.1.12",
|
|
123
|
-
"cron": "4.3.4",
|
|
124
128
|
"nodemailer": "7.0.10",
|
|
125
129
|
"object-hash": "3.0.0",
|
|
126
130
|
"openapi3-ts": "4.5.0",
|
|
@@ -141,7 +145,8 @@
|
|
|
141
145
|
"rate-limiter-flexible": "7.2.0",
|
|
142
146
|
"rolldown": "1.0.0-beta.31",
|
|
143
147
|
"rollup": "4.52.5",
|
|
144
|
-
"samlify": "2.10.
|
|
148
|
+
"samlify": "2.10.2",
|
|
149
|
+
"sanitize-filename": "1.6.3",
|
|
145
150
|
"sanitize-html": "2.17.0",
|
|
146
151
|
"sharp": "0.34.5",
|
|
147
152
|
"snappy": "7.3.3",
|
|
@@ -153,34 +158,35 @@
|
|
|
153
158
|
"ws": "8.18.3",
|
|
154
159
|
"zod": "4.1.12",
|
|
155
160
|
"zod-validation-error": "4.0.2",
|
|
156
|
-
"@directus/app": "14.
|
|
157
|
-
"@directus/
|
|
161
|
+
"@directus/app": "14.4.0",
|
|
162
|
+
"@directus/extensions": "3.0.15",
|
|
163
|
+
"@directus/errors": "2.1.0",
|
|
164
|
+
"@directus/extensions-sdk": "17.0.4",
|
|
158
165
|
"@directus/constants": "14.0.0",
|
|
159
|
-
"@directus/
|
|
160
|
-
"@directus/
|
|
161
|
-
"@directus/extensions-sdk": "17.0.3",
|
|
166
|
+
"@directus/extensions-registry": "3.0.15",
|
|
167
|
+
"@directus/env": "5.3.3",
|
|
162
168
|
"@directus/format-title": "12.1.1",
|
|
163
|
-
"@directus/
|
|
164
|
-
"@directus/pressure": "3.0.
|
|
169
|
+
"@directus/memory": "3.0.13",
|
|
170
|
+
"@directus/pressure": "3.0.13",
|
|
165
171
|
"@directus/schema": "13.0.4",
|
|
166
|
-
"@directus/memory": "3.0.12",
|
|
167
|
-
"@directus/schema-builder": "0.0.9",
|
|
168
172
|
"@directus/storage": "12.0.3",
|
|
169
173
|
"@directus/specs": "11.2.0",
|
|
170
|
-
"@directus/
|
|
171
|
-
"@directus/storage-driver-
|
|
172
|
-
"@directus/storage-driver-
|
|
173
|
-
"@directus/storage-driver-
|
|
174
|
+
"@directus/schema-builder": "0.0.10",
|
|
175
|
+
"@directus/storage-driver-azure": "12.0.13",
|
|
176
|
+
"@directus/storage-driver-cloudinary": "12.0.13",
|
|
177
|
+
"@directus/storage-driver-gcs": "12.0.13",
|
|
174
178
|
"@directus/storage-driver-local": "12.0.3",
|
|
175
|
-
"@directus/
|
|
176
|
-
"@directus/
|
|
177
|
-
"@directus/
|
|
178
|
-
"@directus/
|
|
179
|
-
"directus": "
|
|
179
|
+
"@directus/system-data": "3.5.0",
|
|
180
|
+
"@directus/storage-driver-supabase": "3.0.13",
|
|
181
|
+
"@directus/utils": "13.1.0",
|
|
182
|
+
"@directus/validation": "2.0.13",
|
|
183
|
+
"@directus/storage-driver-s3": "12.0.13",
|
|
184
|
+
"directus": "11.14.0"
|
|
180
185
|
},
|
|
181
186
|
"devDependencies": {
|
|
182
187
|
"@directus/tsconfig": "3.0.0",
|
|
183
188
|
"@ngneat/falso": "8.0.2",
|
|
189
|
+
"@types/archiver": "7.0.0",
|
|
184
190
|
"@types/async": "3.2.25",
|
|
185
191
|
"@types/busboy": "1.5.4",
|
|
186
192
|
"@types/bytes": "3.1.5",
|
|
@@ -219,8 +225,8 @@
|
|
|
219
225
|
"knex-mock-client": "3.0.2",
|
|
220
226
|
"typescript": "5.9.3",
|
|
221
227
|
"vitest": "3.2.4",
|
|
222
|
-
"@directus/
|
|
223
|
-
"@directus/
|
|
228
|
+
"@directus/schema-builder": "0.0.10",
|
|
229
|
+
"@directus/types": "13.5.0"
|
|
224
230
|
},
|
|
225
231
|
"optionalDependencies": {
|
|
226
232
|
"@keyv/redis": "3.0.1",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Url } from '../../utils/url.js';
|
|
2
|
-
/**
|
|
3
|
-
* Generate callback URL from origin
|
|
4
|
-
*
|
|
5
|
-
* @param string Origin URL
|
|
6
|
-
* @param providerName OAuth provider name
|
|
7
|
-
* @returns url
|
|
8
|
-
*/
|
|
9
|
-
export function generateCallbackUrl(providerName, originUrl) {
|
|
10
|
-
return new Url(originUrl).addPath('auth', 'login', providerName, 'callback').toString();
|
|
11
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Check if the redirect URL is allowed
|
|
3
|
-
* @param originUrl Origin URL
|
|
4
|
-
* @param provider OAuth provider name
|
|
5
|
-
* @param redirect URL to redirect to
|
|
6
|
-
* @returns True if the redirect is allowed, false otherwise
|
|
7
|
-
*/
|
|
8
|
-
export declare function isLoginRedirectAllowed(provider: string, originUrl: string, redirect: unknown): boolean;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { useEnv } from '@directus/env';
|
|
2
|
-
import { exists } from 'fs-extra';
|
|
3
|
-
import mid from 'node-machine-id';
|
|
4
|
-
import { createWriteStream } from 'node:fs';
|
|
5
|
-
import { mkdir, rm } from 'node:fs/promises';
|
|
6
|
-
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
7
|
-
import { pipeline } from 'node:stream/promises';
|
|
8
|
-
import Queue from 'p-queue';
|
|
9
|
-
import { useBus } from '../../bus/index.js';
|
|
10
|
-
import { useLock } from '../../lock/index.js';
|
|
11
|
-
import { useLogger } from '../../logger/index.js';
|
|
12
|
-
import { getStorage } from '../../storage/index.js';
|
|
13
|
-
import { getExtensionsPath } from './get-extensions-path.js';
|
|
14
|
-
import { SyncStatus, getSyncStatus, setSyncStatus } from './sync-status.js';
|
|
15
|
-
export const syncExtensions = async (options) => {
|
|
16
|
-
const lock = useLock();
|
|
17
|
-
const messenger = useBus();
|
|
18
|
-
const env = useEnv();
|
|
19
|
-
const logger = useLogger();
|
|
20
|
-
if (!options?.force) {
|
|
21
|
-
const isDone = (await getSyncStatus()) === SyncStatus.DONE;
|
|
22
|
-
if (isDone)
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const machineId = await mid.machineId();
|
|
26
|
-
const machineKey = `extensions-sync/${machineId}`;
|
|
27
|
-
const processId = await lock.increment(machineKey);
|
|
28
|
-
const currentProcessShouldHandleSync = processId === 1;
|
|
29
|
-
if (currentProcessShouldHandleSync === false) {
|
|
30
|
-
logger.trace('Extensions already being synced to this machine from another process.');
|
|
31
|
-
// Wait until the process that called the lock publishes a message that the syncing is complete
|
|
32
|
-
return new Promise((resolve) => {
|
|
33
|
-
messenger.subscribe(machineKey, () => resolve());
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
try {
|
|
37
|
-
const extensionsPath = getExtensionsPath();
|
|
38
|
-
const storageExtensionsPath = env['EXTENSIONS_PATH'];
|
|
39
|
-
if (await exists(extensionsPath)) {
|
|
40
|
-
// In case the FS still contains the cached extensions from a previous invocation. We have to
|
|
41
|
-
// clear them out to ensure the remote extensions folder remains the source of truth for all
|
|
42
|
-
// extensions that are loaded.
|
|
43
|
-
await rm(extensionsPath, { recursive: true, force: true });
|
|
44
|
-
}
|
|
45
|
-
// Ensure that the local extensions cache path exists
|
|
46
|
-
await mkdir(extensionsPath, { recursive: true });
|
|
47
|
-
await setSyncStatus(SyncStatus.SYNCING);
|
|
48
|
-
logger.trace('Syncing extensions from configured storage location...');
|
|
49
|
-
const storage = await getStorage();
|
|
50
|
-
const disk = storage.location(env['EXTENSIONS_LOCATION']);
|
|
51
|
-
// Make sure we don't overload the file handles
|
|
52
|
-
const queue = new Queue({ concurrency: 1000 });
|
|
53
|
-
for await (const filepath of disk.list(storageExtensionsPath)) {
|
|
54
|
-
const readStream = await disk.read(filepath);
|
|
55
|
-
// We want files to be stored in the root of `$TEMP_PATH/extensions`, so gotta remove the
|
|
56
|
-
// extensions path on disk from the start of the file path
|
|
57
|
-
const destPath = join(extensionsPath, relative(resolve(sep, storageExtensionsPath), resolve(sep, filepath)));
|
|
58
|
-
// Ensure that the directory path exists
|
|
59
|
-
await mkdir(dirname(destPath), { recursive: true });
|
|
60
|
-
const writeStream = createWriteStream(destPath);
|
|
61
|
-
queue.add(() => pipeline(readStream, writeStream));
|
|
62
|
-
}
|
|
63
|
-
await queue.onIdle();
|
|
64
|
-
await setSyncStatus(SyncStatus.DONE);
|
|
65
|
-
messenger.publish(machineKey, { ready: true });
|
|
66
|
-
}
|
|
67
|
-
finally {
|
|
68
|
-
await lock.delete(machineKey);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare enum SyncStatus {
|
|
2
|
-
UNKNOWN = "UNKNOWN",
|
|
3
|
-
SYNCING = "SYNCING",
|
|
4
|
-
DONE = "DONE"
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Retrieves the sync status from the `.status` file in the local extensions folder
|
|
8
|
-
*/
|
|
9
|
-
export declare const getSyncStatus: () => Promise<string>;
|
|
10
|
-
export declare const setSyncStatus: (status: SyncStatus) => Promise<void>;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { exists } from 'fs-extra';
|
|
2
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { getExtensionsPath } from './get-extensions-path.js';
|
|
5
|
-
export var SyncStatus;
|
|
6
|
-
(function (SyncStatus) {
|
|
7
|
-
SyncStatus["UNKNOWN"] = "UNKNOWN";
|
|
8
|
-
SyncStatus["SYNCING"] = "SYNCING";
|
|
9
|
-
SyncStatus["DONE"] = "DONE";
|
|
10
|
-
})(SyncStatus || (SyncStatus = {}));
|
|
11
|
-
/**
|
|
12
|
-
* Retrieves the sync status from the `.status` file in the local extensions folder
|
|
13
|
-
*/
|
|
14
|
-
export const getSyncStatus = async () => {
|
|
15
|
-
const statusFilePath = join(getExtensionsPath(), '.status');
|
|
16
|
-
if (await exists(statusFilePath)) {
|
|
17
|
-
const status = await readFile(statusFilePath, 'utf8');
|
|
18
|
-
return status;
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
return SyncStatus.UNKNOWN;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
export const setSyncStatus = async (status) => {
|
|
25
|
-
const statusFilePath = join(getExtensionsPath(), '.status');
|
|
26
|
-
await writeFile(statusFilePath, status);
|
|
27
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { ToolConfig } from '../types.js';
|
|
2
|
-
import { collections } from './collections.js';
|
|
3
|
-
import { fields } from './fields.js';
|
|
4
|
-
import { files } from './files.js';
|
|
5
|
-
import { flows } from './flows.js';
|
|
6
|
-
import { items } from './items.js';
|
|
7
|
-
import { operations } from './operations.js';
|
|
8
|
-
import { relations } from './relations.js';
|
|
9
|
-
import { schema } from './schema.js';
|
|
10
|
-
import { system } from './system.js';
|
|
11
|
-
import { triggerFlow } from './trigger-flow.js';
|
|
12
|
-
export declare const ALL_TOOLS: ToolConfig<any>[];
|
|
13
|
-
export declare const getAllMcpTools: () => ToolConfig<any>[];
|
|
14
|
-
export declare const findMcpTool: (name: string) => ToolConfig<any> | undefined;
|
|
15
|
-
export { collections, fields, files, flows, items, operations, relations, schema, system, triggerFlow };
|
package/dist/mcp/tools/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { assets } from './assets.js';
|
|
2
|
-
import { collections } from './collections.js';
|
|
3
|
-
import { fields } from './fields.js';
|
|
4
|
-
import { files } from './files.js';
|
|
5
|
-
import { flows } from './flows.js';
|
|
6
|
-
import { folders } from './folders.js';
|
|
7
|
-
import { items } from './items.js';
|
|
8
|
-
import { operations } from './operations.js';
|
|
9
|
-
import { relations } from './relations.js';
|
|
10
|
-
import { schema } from './schema.js';
|
|
11
|
-
import { system } from './system.js';
|
|
12
|
-
import { triggerFlow } from './trigger-flow.js';
|
|
13
|
-
export const ALL_TOOLS = [
|
|
14
|
-
system,
|
|
15
|
-
items,
|
|
16
|
-
files,
|
|
17
|
-
folders,
|
|
18
|
-
assets,
|
|
19
|
-
flows,
|
|
20
|
-
triggerFlow,
|
|
21
|
-
operations,
|
|
22
|
-
schema,
|
|
23
|
-
collections,
|
|
24
|
-
fields,
|
|
25
|
-
relations,
|
|
26
|
-
];
|
|
27
|
-
export const getAllMcpTools = () => ALL_TOOLS;
|
|
28
|
-
export const findMcpTool = (name) => ALL_TOOLS.find((tool) => tool.name === name);
|
|
29
|
-
export { collections, fields, files, flows, items, operations, relations, schema, system, triggerFlow };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
declare const _default: {
|
|
2
|
-
assets: string;
|
|
3
|
-
collections: string;
|
|
4
|
-
fields: string;
|
|
5
|
-
files: string;
|
|
6
|
-
folders: string;
|
|
7
|
-
flows: string;
|
|
8
|
-
items: string;
|
|
9
|
-
operations: string;
|
|
10
|
-
relations: string;
|
|
11
|
-
schema: string;
|
|
12
|
-
systemPrompt: string;
|
|
13
|
-
systemPromptDescription: string;
|
|
14
|
-
triggerFlow: string;
|
|
15
|
-
};
|
|
16
|
-
export default _default;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import fse from 'fs-extra';
|
|
2
|
-
import { dirname, join } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
-
export default {
|
|
6
|
-
assets: fse.readFileSync(join(__dirname, 'assets.md'), 'utf8'),
|
|
7
|
-
collections: fse.readFileSync(join(__dirname, 'collections.md'), 'utf8'),
|
|
8
|
-
fields: fse.readFileSync(join(__dirname, 'fields.md'), 'utf8'),
|
|
9
|
-
files: fse.readFileSync(join(__dirname, 'files.md'), 'utf8'),
|
|
10
|
-
folders: fse.readFileSync(join(__dirname, 'folders.md'), 'utf8'),
|
|
11
|
-
flows: fse.readFileSync(join(__dirname, 'flows.md'), 'utf8'),
|
|
12
|
-
items: fse.readFileSync(join(__dirname, 'items.md'), 'utf8'),
|
|
13
|
-
operations: fse.readFileSync(join(__dirname, 'operations.md'), 'utf8'),
|
|
14
|
-
relations: fse.readFileSync(join(__dirname, 'relations.md'), 'utf8'),
|
|
15
|
-
schema: fse.readFileSync(join(__dirname, 'schema.md'), 'utf8'),
|
|
16
|
-
systemPrompt: fse.readFileSync(join(__dirname, 'system-prompt.md'), 'utf8'),
|
|
17
|
-
systemPromptDescription: fse.readFileSync(join(__dirname, 'system-prompt-description.md'), 'utf8'),
|
|
18
|
-
triggerFlow: fse.readFileSync(join(__dirname, 'trigger-flow.md'), 'utf8'),
|
|
19
|
-
};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Accountability } from '@directus/types';
|
|
2
|
-
import type { Knex } from 'knex';
|
|
3
|
-
import type { GlobalAccess } from '../types.js';
|
|
4
|
-
export declare const fetchGlobalAccessForRoles: typeof _fetchGlobalAccessForRoles;
|
|
5
|
-
export declare function _fetchGlobalAccessForRoles(accountability: Pick<Accountability, 'roles' | 'ip'>, knex: Knex): Promise<GlobalAccess>;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { withCache } from '../../../utils/with-cache.js';
|
|
2
|
-
import { fetchGlobalAccessForQuery } from '../utils/fetch-global-access-for-query.js';
|
|
3
|
-
export const fetchGlobalAccessForRoles = withCache('global-access-role', _fetchGlobalAccessForRoles, ({ roles, ip }) => ({ roles, ip }));
|
|
4
|
-
export async function _fetchGlobalAccessForRoles(accountability, knex) {
|
|
5
|
-
const query = knex.where('role', 'in', accountability.roles);
|
|
6
|
-
return await fetchGlobalAccessForQuery(query, accountability);
|
|
7
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Accountability } from '@directus/types';
|
|
2
|
-
import type { Knex } from 'knex';
|
|
3
|
-
import type { GlobalAccess } from '../types.js';
|
|
4
|
-
export declare const fetchGlobalAccessForUser: typeof _fetchGlobalAccessForUser;
|
|
5
|
-
export declare function _fetchGlobalAccessForUser(accountability: Pick<Accountability, 'user' | 'ip'>, knex: Knex): Promise<GlobalAccess>;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { withCache } from '../../../utils/with-cache.js';
|
|
2
|
-
import { fetchGlobalAccessForQuery } from '../utils/fetch-global-access-for-query.js';
|
|
3
|
-
export const fetchGlobalAccessForUser = withCache('global-access-user', _fetchGlobalAccessForUser, ({ user, ip }) => ({
|
|
4
|
-
user,
|
|
5
|
-
ip,
|
|
6
|
-
}));
|
|
7
|
-
export async function _fetchGlobalAccessForUser(accountability, knex) {
|
|
8
|
-
const query = knex.where('user', '=', accountability.user);
|
|
9
|
-
return await fetchGlobalAccessForQuery(query, accountability);
|
|
10
|
-
}
|
package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { Accountability } from '@directus/types';
|
|
2
|
-
import type { Knex } from 'knex';
|
|
3
|
-
import type { GlobalAccess } from '../types.js';
|
|
4
|
-
export declare function fetchGlobalAccessForQuery(query: Knex.QueryBuilder<any, any[]>, accountability: Pick<Accountability, 'ip'>): Promise<GlobalAccess>;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { toBoolean, toArray } from '@directus/utils';
|
|
2
|
-
import { ipInNetworks } from '../../../../utils/ip-in-networks.js';
|
|
3
|
-
export async function fetchGlobalAccessForQuery(query, accountability) {
|
|
4
|
-
const globalAccess = {
|
|
5
|
-
app: false,
|
|
6
|
-
admin: false,
|
|
7
|
-
};
|
|
8
|
-
const accessRows = await query
|
|
9
|
-
.select('directus_policies.admin_access', 'directus_policies.app_access', 'directus_policies.ip_access')
|
|
10
|
-
.from('directus_access')
|
|
11
|
-
// @NOTE: `where` clause comes from the caller
|
|
12
|
-
.leftJoin('directus_policies', 'directus_policies.id', 'directus_access.policy');
|
|
13
|
-
// Additively merge access permissions
|
|
14
|
-
for (const { admin_access, app_access, ip_access } of accessRows) {
|
|
15
|
-
if (accountability.ip && ip_access) {
|
|
16
|
-
// Skip row if IP is not in the allowed networks
|
|
17
|
-
const networks = toArray(ip_access);
|
|
18
|
-
if (!ipInNetworks(accountability.ip, networks))
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
globalAccess.admin ||= toBoolean(admin_access);
|
|
22
|
-
globalAccess.app ||= globalAccess.admin || toBoolean(app_access);
|
|
23
|
-
if (globalAccess.admin)
|
|
24
|
-
break;
|
|
25
|
-
}
|
|
26
|
-
return globalAccess;
|
|
27
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function getDateFormatted(): string;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export function getDateFormatted() {
|
|
2
|
-
const date = new Date();
|
|
3
|
-
let month = String(date.getMonth() + 1);
|
|
4
|
-
if (month.length === 1)
|
|
5
|
-
month = '0' + month;
|
|
6
|
-
let day = String(date.getDate());
|
|
7
|
-
if (day.length === 1)
|
|
8
|
-
day = '0' + day;
|
|
9
|
-
return `${date.getFullYear()}${month}${day}-${date.getHours()}${date.getMinutes()}${date.getSeconds()}`;
|
|
10
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checks if an IP address is contained in a list of networks
|
|
3
|
-
* @param networks List of IP addresses (192.168.0.1), CIDR notations (192.168.0.0/24) or IP ranges (192-168.0.0-192.168.2.0)
|
|
4
|
-
* @throws Will throw if list contains invalid network definitions
|
|
5
|
-
*/
|
|
6
|
-
export declare function ipInNetworks(ip: string, networks: string[]): boolean;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { matches } from 'ip-matching';
|
|
2
|
-
/**
|
|
3
|
-
* Checks if an IP address is contained in a list of networks
|
|
4
|
-
* @param networks List of IP addresses (192.168.0.1), CIDR notations (192.168.0.0/24) or IP ranges (192-168.0.0-192.168.2.0)
|
|
5
|
-
* @throws Will throw if list contains invalid network definitions
|
|
6
|
-
*/
|
|
7
|
-
export function ipInNetworks(ip, networks) {
|
|
8
|
-
for (const allowedIp of networks) {
|
|
9
|
-
if (matches(ip, allowedIp))
|
|
10
|
-
return true;
|
|
11
|
-
}
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|