@directus/api 14.1.2 → 16.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 +8 -6
- package/dist/auth/drivers/ldap.js +7 -4
- package/dist/auth/drivers/local.js +3 -2
- package/dist/auth/drivers/oauth2.js +11 -5
- package/dist/auth/drivers/openid.js +11 -5
- package/dist/auth/drivers/saml.js +6 -4
- package/dist/auth.js +7 -4
- package/dist/bus/index.d.ts +1 -0
- package/dist/bus/index.js +1 -0
- package/dist/bus/lib/use-bus.d.ts +9 -0
- package/dist/bus/lib/use-bus.js +21 -0
- package/dist/cache.js +9 -9
- package/dist/cli/commands/bootstrap/index.js +6 -2
- package/dist/cli/commands/count/index.js +2 -1
- package/dist/cli/commands/database/install.js +2 -1
- package/dist/cli/commands/database/migrate.js +2 -1
- package/dist/cli/commands/roles/create.js +2 -1
- package/dist/cli/commands/schema/apply.js +46 -34
- package/dist/cli/commands/schema/snapshot.js +6 -5
- package/dist/cli/commands/users/create.js +4 -3
- package/dist/cli/commands/users/passwd.js +5 -4
- package/dist/cli/index.js +2 -2
- package/dist/cli/load-extensions.js +4 -2
- package/dist/cli/utils/create-env/env-stub.liquid +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +4 -1
- package/dist/controllers/assets.js +5 -3
- package/dist/controllers/auth.js +5 -4
- package/dist/controllers/extensions.js +18 -6
- package/dist/controllers/files.js +3 -3
- package/dist/controllers/schema.js +3 -2
- package/dist/controllers/shares.js +3 -3
- package/dist/database/helpers/index.d.ts +1 -1
- package/dist/database/index.d.ts +2 -1
- package/dist/database/index.js +11 -3
- package/dist/database/migrations/20210518A-add-foreign-key-constraints.js +3 -1
- package/dist/database/migrations/20210519A-add-system-fk-triggers.js +3 -1
- package/dist/database/migrations/20210802A-replace-groups.js +2 -1
- package/dist/database/migrations/20230721A-require-shares-fields.js +2 -1
- package/dist/database/migrations/20231215A-add-focalpoints.d.ts +3 -0
- package/dist/database/migrations/20231215A-add-focalpoints.js +12 -0
- package/dist/database/migrations/run.js +2 -1
- package/dist/database/run-ast.js +5 -2
- package/dist/database/system-data/app-access-permissions/app-access-permissions.yaml +0 -7
- package/dist/database/system-data/fields/files.yaml +16 -0
- package/dist/database/system-data/relations/relations.yaml +4 -0
- package/dist/emitter.d.ts +1 -0
- package/dist/emitter.js +4 -1
- package/dist/extensions/lib/get-extensions-path.d.ts +1 -1
- package/dist/extensions/lib/get-extensions-path.js +2 -1
- package/dist/extensions/lib/get-extensions.d.ts +1 -1
- package/dist/extensions/lib/get-extensions.js +32 -8
- package/dist/extensions/lib/get-shared-deps-mapping.js +7 -5
- package/dist/extensions/lib/sandbox/register/call-reference.js +4 -2
- package/dist/extensions/lib/sandbox/register/route.d.ts +1 -0
- package/dist/extensions/lib/sandbox/sdk/generators/log.js +2 -1
- package/dist/extensions/lib/sync-extensions.js +6 -4
- package/dist/extensions/manager.d.ts +5 -0
- package/dist/extensions/manager.js +84 -34
- package/dist/flows.js +13 -7
- package/dist/logger.d.ts +7 -6
- package/dist/logger.js +116 -91
- package/dist/mailer.js +4 -2
- package/dist/middleware/cache.js +4 -2
- package/dist/middleware/check-ip.js +25 -6
- package/dist/middleware/cors.js +2 -1
- package/dist/middleware/error-handler.js +5 -5
- package/dist/middleware/rate-limiter-global.js +4 -2
- package/dist/middleware/rate-limiter-ip.js +16 -12
- package/dist/middleware/respond.js +4 -2
- package/dist/operations/log/index.js +2 -1
- package/dist/rate-limiter.d.ts +2 -1
- package/dist/rate-limiter.js +5 -2
- package/dist/redis/index.d.ts +3 -0
- package/dist/redis/index.js +3 -0
- package/dist/redis/lib/create-redis.d.ts +7 -0
- package/dist/redis/lib/create-redis.js +12 -0
- package/dist/redis/lib/use-redis.d.ts +16 -0
- package/dist/redis/lib/use-redis.js +22 -0
- package/dist/redis/utils/redis-config-available.d.ts +4 -0
- package/dist/redis/utils/redis-config-available.js +8 -0
- package/dist/request/request-interceptor.js +7 -5
- package/dist/request/response-interceptor.js +2 -2
- package/dist/request/validate-ip.d.ts +1 -1
- package/dist/request/validate-ip.js +23 -7
- package/dist/server.d.ts +2 -0
- package/dist/server.js +11 -7
- package/dist/services/activity.js +5 -4
- package/dist/services/assets.d.ts +2 -0
- package/dist/services/assets.js +9 -4
- package/dist/services/authentication.js +17 -9
- package/dist/services/collections.js +5 -4
- package/dist/services/extensions.d.ts +15 -9
- package/dist/services/extensions.js +75 -40
- package/dist/services/fields.js +9 -4
- package/dist/services/files.d.ts +2 -2
- package/dist/services/files.js +22 -14
- package/dist/services/graphql/index.js +96 -18
- package/dist/services/graphql/subscription.js +2 -2
- package/dist/services/graphql/types/bigint.js +16 -5
- package/dist/services/graphql/utils/process-error.d.ts +4 -1
- package/dist/services/graphql/utils/process-error.js +10 -8
- package/dist/services/import-export/index.js +5 -3
- package/dist/services/items.js +12 -8
- package/dist/services/mail/index.js +4 -2
- package/dist/services/notifications.js +7 -3
- package/dist/services/payload.js +3 -3
- package/dist/services/relations.js +19 -10
- package/dist/services/server.js +7 -7
- package/dist/services/shares.js +3 -2
- package/dist/services/specifications.js +5 -4
- package/dist/services/users.js +24 -13
- package/dist/services/versions.js +6 -5
- package/dist/services/webhooks.d.ts +2 -2
- package/dist/services/webhooks.js +2 -2
- package/dist/services/websocket.d.ts +1 -1
- package/dist/services/websocket.js +4 -3
- package/dist/storage/register-drivers.js +2 -1
- package/dist/storage/register-locations.js +2 -1
- package/dist/synchronization.js +3 -1
- package/dist/telemetry/index.d.ts +4 -0
- package/dist/telemetry/index.js +4 -0
- package/dist/telemetry/lib/get-report.d.ts +5 -0
- package/dist/telemetry/lib/get-report.js +42 -0
- package/dist/telemetry/lib/init-telemetry.d.ts +11 -0
- package/dist/telemetry/lib/init-telemetry.js +30 -0
- package/dist/telemetry/lib/send-report.d.ts +5 -0
- package/dist/telemetry/lib/send-report.js +23 -0
- package/dist/telemetry/lib/track.d.ts +10 -0
- package/dist/telemetry/lib/track.js +30 -0
- package/dist/telemetry/types/report.d.ts +58 -0
- package/dist/telemetry/types/report.js +1 -0
- package/dist/telemetry/utils/get-item-count.d.ts +26 -0
- package/dist/telemetry/utils/get-item-count.js +36 -0
- package/dist/telemetry/utils/get-random-wait-time.d.ts +5 -0
- package/dist/telemetry/utils/get-random-wait-time.js +5 -0
- package/dist/telemetry/utils/get-user-count.d.ts +7 -0
- package/dist/telemetry/utils/get-user-count.js +30 -0
- package/dist/telemetry/utils/get-user-item-count.d.ts +13 -0
- package/dist/telemetry/utils/get-user-item-count.js +18 -0
- package/dist/types/assets.d.ts +2 -0
- package/dist/utils/apply-diff.js +2 -1
- package/dist/utils/apply-query.js +2 -2
- package/dist/utils/delete-from-require-cache.js +2 -1
- package/dist/utils/get-accountability-for-token.js +3 -2
- package/dist/utils/get-auth-providers.js +2 -1
- package/dist/utils/get-cache-headers.js +5 -2
- package/dist/utils/get-cache-key.js +1 -1
- package/dist/utils/get-config-from-env.js +2 -1
- package/dist/utils/get-default-value.js +4 -3
- package/dist/utils/get-ip-from-req.d.ts +1 -1
- package/dist/utils/get-ip-from-req.js +5 -3
- package/dist/utils/get-permissions.js +5 -3
- package/dist/utils/get-schema.js +5 -2
- package/dist/utils/get-snapshot-diff.js +7 -9
- package/dist/utils/get-snapshot.js +5 -5
- package/dist/utils/get-versioned-hash.js +1 -1
- package/dist/utils/ip-in-networks.d.ts +6 -0
- package/dist/utils/ip-in-networks.js +13 -0
- package/dist/utils/is-url-allowed.js +2 -1
- package/dist/utils/job-queue.d.ts +1 -0
- package/dist/utils/job-queue.js +3 -0
- package/dist/utils/md.d.ts +1 -1
- package/dist/utils/md.js +3 -2
- package/dist/utils/sanitize-query.js +7 -2
- package/dist/utils/sanitize-schema.d.ts +1 -1
- package/dist/utils/should-clear-cache.js +2 -1
- package/dist/utils/should-skip-cache.js +2 -1
- package/dist/utils/transformations.js +95 -12
- package/dist/utils/validate-env.js +4 -2
- package/dist/utils/validate-query.js +8 -3
- package/dist/utils/validate-snapshot.js +3 -3
- package/dist/utils/validate-storage.js +4 -2
- package/dist/webhooks.js +4 -3
- package/dist/websocket/controllers/base.d.ts +2 -0
- package/dist/websocket/controllers/base.js +12 -6
- package/dist/websocket/controllers/graphql.d.ts +2 -0
- package/dist/websocket/controllers/graphql.js +5 -3
- package/dist/websocket/controllers/hooks.js +3 -2
- package/dist/websocket/controllers/index.d.ts +2 -0
- package/dist/websocket/controllers/index.js +4 -2
- package/dist/websocket/controllers/rest.d.ts +2 -0
- package/dist/websocket/controllers/rest.js +4 -2
- package/dist/websocket/errors.js +2 -1
- package/dist/websocket/handlers/heartbeat.js +4 -3
- package/dist/websocket/handlers/subscribe.d.ts +2 -2
- package/dist/websocket/handlers/subscribe.js +5 -4
- package/dist/websocket/types.d.ts +3 -1
- package/package.json +114 -115
- package/dist/__utils__/items-utils.d.ts +0 -2
- package/dist/__utils__/items-utils.js +0 -31
- package/dist/__utils__/mock-env.d.ts +0 -18
- package/dist/__utils__/mock-env.js +0 -41
- package/dist/__utils__/schemas.d.ts +0 -13
- package/dist/__utils__/schemas.js +0 -301
- package/dist/__utils__/snapshots.d.ts +0 -5
- package/dist/__utils__/snapshots.js +0 -903
- package/dist/env.d.ts +0 -13
- package/dist/env.js +0 -505
- package/dist/messenger.d.ts +0 -24
- package/dist/messenger.js +0 -64
- package/dist/utils/package.d.ts +0 -2
- package/dist/utils/package.js +0 -6
- package/dist/utils/telemetry.d.ts +0 -1
- package/dist/utils/telemetry.js +0 -23
- package/dist/utils/to-boolean.d.ts +0 -4
- package/dist/utils/to-boolean.js +0 -6
package/dist/app.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
2
|
+
import { InvalidPayloadError, ServiceUnavailableError } from '@directus/errors';
|
|
1
3
|
import { handlePressure } from '@directus/pressure';
|
|
2
4
|
import cookieParser from 'cookie-parser';
|
|
3
5
|
import express from 'express';
|
|
@@ -39,11 +41,9 @@ import versionsRouter from './controllers/versions.js';
|
|
|
39
41
|
import webhooksRouter from './controllers/webhooks.js';
|
|
40
42
|
import { isInstalled, validateDatabaseConnection, validateDatabaseExtensions, validateMigrations, } from './database/index.js';
|
|
41
43
|
import emitter from './emitter.js';
|
|
42
|
-
import env from './env.js';
|
|
43
|
-
import { InvalidPayloadError, ServiceUnavailableError } from '@directus/errors';
|
|
44
44
|
import { getExtensionManager } from './extensions/index.js';
|
|
45
45
|
import { getFlowManager } from './flows.js';
|
|
46
|
-
import
|
|
46
|
+
import { createExpressLogger, useLogger } from './logger.js';
|
|
47
47
|
import authenticate from './middleware/authenticate.js';
|
|
48
48
|
import cache from './middleware/cache.js';
|
|
49
49
|
import { checkIP } from './middleware/check-ip.js';
|
|
@@ -55,14 +55,16 @@ import rateLimiterGlobal from './middleware/rate-limiter-global.js';
|
|
|
55
55
|
import rateLimiter from './middleware/rate-limiter-ip.js';
|
|
56
56
|
import sanitizeQuery from './middleware/sanitize-query.js';
|
|
57
57
|
import schema from './middleware/schema.js';
|
|
58
|
+
import { initTelemetry } from './telemetry/index.js';
|
|
58
59
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
59
|
-
import { collectTelemetry } from './utils/telemetry.js';
|
|
60
60
|
import { Url } from './utils/url.js';
|
|
61
61
|
import { validateEnv } from './utils/validate-env.js';
|
|
62
62
|
import { validateStorage } from './utils/validate-storage.js';
|
|
63
63
|
import { init as initWebhooks } from './webhooks.js';
|
|
64
64
|
const require = createRequire(import.meta.url);
|
|
65
65
|
export default async function createApp() {
|
|
66
|
+
const env = useEnv();
|
|
67
|
+
const logger = useLogger();
|
|
66
68
|
const helmet = await import('helmet');
|
|
67
69
|
validateEnv(['KEY', 'SECRET']);
|
|
68
70
|
if (!new Url(env['PUBLIC_URL']).isAbsolute()) {
|
|
@@ -124,7 +126,7 @@ export default async function createApp() {
|
|
|
124
126
|
}
|
|
125
127
|
await emitter.emitInit('app.before', { app });
|
|
126
128
|
await emitter.emitInit('middlewares.before', { app });
|
|
127
|
-
app.use(
|
|
129
|
+
app.use(createExpressLogger());
|
|
128
130
|
app.use((_req, res, next) => {
|
|
129
131
|
res.setHeader('X-Powered-By', 'Directus');
|
|
130
132
|
next();
|
|
@@ -234,7 +236,7 @@ export default async function createApp() {
|
|
|
234
236
|
await emitter.emitInit('routes.after', { app });
|
|
235
237
|
// Register all webhooks
|
|
236
238
|
await initWebhooks();
|
|
237
|
-
|
|
239
|
+
initTelemetry();
|
|
238
240
|
await emitter.emitInit('app.after', { app });
|
|
239
241
|
return app;
|
|
240
242
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
2
|
+
import { ErrorCode, InvalidCredentialsError, InvalidPayloadError, InvalidProviderConfigError, InvalidProviderError, ServiceUnavailableError, UnexpectedResponseError, isDirectusError, } from '@directus/errors';
|
|
2
3
|
import { Router } from 'express';
|
|
3
4
|
import Joi from 'joi';
|
|
4
5
|
import ldap from 'ldapjs';
|
|
5
6
|
import getDatabase from '../../database/index.js';
|
|
6
7
|
import emitter from '../../emitter.js';
|
|
7
|
-
import
|
|
8
|
-
import { ErrorCode, InvalidCredentialsError, InvalidPayloadError, InvalidProviderError, InvalidProviderConfigError, ServiceUnavailableError, UnexpectedResponseError, } from '@directus/errors';
|
|
9
|
-
import logger from '../../logger.js';
|
|
8
|
+
import { useLogger } from '../../logger.js';
|
|
10
9
|
import { respond } from '../../middleware/respond.js';
|
|
11
10
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
12
11
|
import { UsersService } from '../../services/users.js';
|
|
@@ -24,6 +23,7 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
24
23
|
config;
|
|
25
24
|
constructor(options, config) {
|
|
26
25
|
super(options, config);
|
|
26
|
+
const logger = useLogger();
|
|
27
27
|
const { bindDn, bindPassword, userDn, provider, clientUrl } = config;
|
|
28
28
|
if (bindDn === undefined ||
|
|
29
29
|
bindPassword === undefined ||
|
|
@@ -42,6 +42,7 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
42
42
|
this.config = config;
|
|
43
43
|
}
|
|
44
44
|
async validateBindClient() {
|
|
45
|
+
const logger = useLogger();
|
|
45
46
|
const { bindDn, bindPassword, provider } = this.config;
|
|
46
47
|
return new Promise((resolve, reject) => {
|
|
47
48
|
// Healthcheck bind user
|
|
@@ -168,6 +169,7 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
168
169
|
if (!payload['identifier']) {
|
|
169
170
|
throw new InvalidCredentialsError();
|
|
170
171
|
}
|
|
172
|
+
const logger = useLogger();
|
|
171
173
|
await this.validateBindClient();
|
|
172
174
|
const { userDn, userScope, userAttribute, groupDn, groupScope, groupAttribute, defaultRoleId } = this.config;
|
|
173
175
|
const userInfo = await this.fetchUserInfo(userDn, new ldap.EqualityFilter({
|
|
@@ -292,6 +294,7 @@ export function createLDAPAuthRouter(provider) {
|
|
|
292
294
|
otp: Joi.string(),
|
|
293
295
|
}).unknown();
|
|
294
296
|
router.post('/', asyncHandler(async (req, res, next) => {
|
|
297
|
+
const env = useEnv();
|
|
295
298
|
const accountability = {
|
|
296
299
|
ip: getIPFromReq(req),
|
|
297
300
|
role: null,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { InvalidCredentialsError, InvalidPayloadError } from '@directus/errors';
|
|
1
2
|
import argon2 from 'argon2';
|
|
2
3
|
import { Router } from 'express';
|
|
3
4
|
import Joi from 'joi';
|
|
4
5
|
import { performance } from 'perf_hooks';
|
|
5
6
|
import { COOKIE_OPTIONS } from '../../constants.js';
|
|
6
|
-
import
|
|
7
|
-
import { InvalidCredentialsError, InvalidPayloadError } from '@directus/errors';
|
|
7
|
+
import { useEnv } from '@directus/env';
|
|
8
8
|
import { respond } from '../../middleware/respond.js';
|
|
9
9
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
10
10
|
import asyncHandler from '../../utils/async-handler.js';
|
|
@@ -36,6 +36,7 @@ export class LocalAuthDriver extends AuthDriver {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
export function createLocalAuthRouter(provider) {
|
|
39
|
+
const env = useEnv();
|
|
39
40
|
const router = Router();
|
|
40
41
|
const userLoginSchema = Joi.object({
|
|
41
42
|
email: Joi.string().email().required(),
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
2
|
+
import { ErrorCode, InvalidCredentialsError, InvalidProviderConfigError, InvalidProviderError, InvalidTokenError, isDirectusError, ServiceUnavailableError, } from '@directus/errors';
|
|
2
3
|
import { parseJSON } from '@directus/utils';
|
|
3
4
|
import express, { Router } from 'express';
|
|
4
|
-
import flatten from 'flat';
|
|
5
|
+
import { flatten } from 'flat';
|
|
5
6
|
import jwt from 'jsonwebtoken';
|
|
6
7
|
import { errors, generators, Issuer } from 'openid-client';
|
|
7
8
|
import { getAuthProvider } from '../../auth.js';
|
|
8
9
|
import getDatabase from '../../database/index.js';
|
|
9
10
|
import emitter from '../../emitter.js';
|
|
10
|
-
import
|
|
11
|
-
import { ErrorCode, InvalidCredentialsError, InvalidProviderError, InvalidProviderConfigError, InvalidTokenError, ServiceUnavailableError, } from '@directus/errors';
|
|
12
|
-
import logger from '../../logger.js';
|
|
11
|
+
import { useLogger } from '../../logger.js';
|
|
13
12
|
import { respond } from '../../middleware/respond.js';
|
|
14
13
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
15
14
|
import { UsersService } from '../../services/users.js';
|
|
@@ -26,6 +25,8 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
26
25
|
config;
|
|
27
26
|
constructor(options, config) {
|
|
28
27
|
super(options, config);
|
|
28
|
+
const env = useEnv();
|
|
29
|
+
const logger = useLogger();
|
|
29
30
|
const { authorizeUrl, accessUrl, profileUrl, clientId, clientSecret, ...additionalConfig } = config;
|
|
30
31
|
if (!authorizeUrl || !accessUrl || !profileUrl || !clientId || !clientSecret || !additionalConfig['provider']) {
|
|
31
32
|
logger.error('Invalid provider config');
|
|
@@ -82,6 +83,7 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
82
83
|
return user?.id;
|
|
83
84
|
}
|
|
84
85
|
async getUserID(payload) {
|
|
86
|
+
const logger = useLogger();
|
|
85
87
|
if (!payload['code'] || !payload['codeVerifier'] || !payload['state']) {
|
|
86
88
|
logger.warn('[OAuth2] No code, codeVerifier or state in payload');
|
|
87
89
|
throw new InvalidCredentialsError();
|
|
@@ -161,6 +163,7 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
161
163
|
return this.refresh(user);
|
|
162
164
|
}
|
|
163
165
|
async refresh(user) {
|
|
166
|
+
const logger = useLogger();
|
|
164
167
|
let authData = user.auth_data;
|
|
165
168
|
if (typeof authData === 'string') {
|
|
166
169
|
try {
|
|
@@ -187,6 +190,7 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
187
190
|
}
|
|
188
191
|
}
|
|
189
192
|
const handleError = (e) => {
|
|
193
|
+
const logger = useLogger();
|
|
190
194
|
if (e instanceof errors.OPError) {
|
|
191
195
|
if (e.error === 'invalid_grant') {
|
|
192
196
|
// Invalid token
|
|
@@ -210,6 +214,7 @@ const handleError = (e) => {
|
|
|
210
214
|
};
|
|
211
215
|
export function createOAuth2AuthRouter(providerName) {
|
|
212
216
|
const router = Router();
|
|
217
|
+
const env = useEnv();
|
|
213
218
|
router.get('/', (req, res) => {
|
|
214
219
|
const provider = getAuthProvider(providerName);
|
|
215
220
|
const codeVerifier = provider.generateCodeVerifier();
|
|
@@ -228,6 +233,7 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
228
233
|
res.redirect(303, `./callback?${new URLSearchParams(req.body)}`);
|
|
229
234
|
}, respond);
|
|
230
235
|
router.get('/callback', asyncHandler(async (req, res, next) => {
|
|
236
|
+
const logger = useLogger();
|
|
231
237
|
let tokenData;
|
|
232
238
|
try {
|
|
233
239
|
tokenData = jwt.verify(req.cookies[`oauth2.${providerName}`], env['SECRET'], {
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
2
|
+
import { ErrorCode, InvalidCredentialsError, InvalidProviderConfigError, InvalidProviderError, InvalidTokenError, isDirectusError, ServiceUnavailableError, } from '@directus/errors';
|
|
2
3
|
import { parseJSON } from '@directus/utils';
|
|
3
4
|
import express, { Router } from 'express';
|
|
4
|
-
import flatten from 'flat';
|
|
5
|
+
import { flatten } from 'flat';
|
|
5
6
|
import jwt from 'jsonwebtoken';
|
|
6
7
|
import { errors, generators, Issuer } from 'openid-client';
|
|
7
8
|
import { getAuthProvider } from '../../auth.js';
|
|
8
9
|
import getDatabase from '../../database/index.js';
|
|
9
10
|
import emitter from '../../emitter.js';
|
|
10
|
-
import
|
|
11
|
-
import { ErrorCode, InvalidCredentialsError, InvalidProviderError, InvalidProviderConfigError, InvalidTokenError, ServiceUnavailableError, } from '@directus/errors';
|
|
12
|
-
import logger from '../../logger.js';
|
|
11
|
+
import { useLogger } from '../../logger.js';
|
|
13
12
|
import { respond } from '../../middleware/respond.js';
|
|
14
13
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
15
14
|
import { UsersService } from '../../services/users.js';
|
|
@@ -26,6 +25,8 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
26
25
|
config;
|
|
27
26
|
constructor(options, config) {
|
|
28
27
|
super(options, config);
|
|
28
|
+
const env = useEnv();
|
|
29
|
+
const logger = useLogger();
|
|
29
30
|
const { issuerUrl, clientId, clientSecret, ...additionalConfig } = config;
|
|
30
31
|
if (!issuerUrl || !clientId || !clientSecret || !additionalConfig['provider']) {
|
|
31
32
|
logger.error('Invalid provider config');
|
|
@@ -94,6 +95,7 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
94
95
|
return user?.id;
|
|
95
96
|
}
|
|
96
97
|
async getUserID(payload) {
|
|
98
|
+
const logger = useLogger();
|
|
97
99
|
if (!payload['code'] || !payload['codeVerifier'] || !payload['state']) {
|
|
98
100
|
logger.warn('[OpenID] No code, codeVerifier or state in payload');
|
|
99
101
|
throw new InvalidCredentialsError();
|
|
@@ -181,6 +183,7 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
181
183
|
return this.refresh(user);
|
|
182
184
|
}
|
|
183
185
|
async refresh(user) {
|
|
186
|
+
const logger = useLogger();
|
|
184
187
|
let authData = user.auth_data;
|
|
185
188
|
if (typeof authData === 'string') {
|
|
186
189
|
try {
|
|
@@ -208,6 +211,7 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
208
211
|
}
|
|
209
212
|
}
|
|
210
213
|
const handleError = (e) => {
|
|
214
|
+
const logger = useLogger();
|
|
211
215
|
if (e instanceof errors.OPError) {
|
|
212
216
|
if (e.error === 'invalid_grant') {
|
|
213
217
|
// Invalid token
|
|
@@ -230,6 +234,7 @@ const handleError = (e) => {
|
|
|
230
234
|
return e;
|
|
231
235
|
};
|
|
232
236
|
export function createOpenIDAuthRouter(providerName) {
|
|
237
|
+
const env = useEnv();
|
|
233
238
|
const router = Router();
|
|
234
239
|
router.get('/', asyncHandler(async (req, res) => {
|
|
235
240
|
const provider = getAuthProvider(providerName);
|
|
@@ -249,6 +254,7 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
249
254
|
res.redirect(303, `./callback?${new URLSearchParams(req.body)}`);
|
|
250
255
|
}, respond);
|
|
251
256
|
router.get('/callback', asyncHandler(async (req, res, next) => {
|
|
257
|
+
const logger = useLogger();
|
|
252
258
|
let tokenData;
|
|
253
259
|
try {
|
|
254
260
|
tokenData = jwt.verify(req.cookies[`openid.${providerName}`], env['SECRET'], {
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import * as validator from '@authenio/samlify-node-xmllint';
|
|
2
|
-
import {
|
|
2
|
+
import { useEnv } from '@directus/env';
|
|
3
|
+
import { ErrorCode, InvalidCredentialsError, InvalidProviderError, isDirectusError } from '@directus/errors';
|
|
3
4
|
import express, { Router } from 'express';
|
|
4
5
|
import * as samlify from 'samlify';
|
|
5
6
|
import { getAuthProvider } from '../../auth.js';
|
|
6
7
|
import { COOKIE_OPTIONS } from '../../constants.js';
|
|
7
8
|
import getDatabase from '../../database/index.js';
|
|
8
9
|
import emitter from '../../emitter.js';
|
|
9
|
-
import
|
|
10
|
-
import { ErrorCode, InvalidCredentialsError, InvalidProviderError } from '@directus/errors';
|
|
11
|
-
import logger from '../../logger.js';
|
|
10
|
+
import { useLogger } from '../../logger.js';
|
|
12
11
|
import { respond } from '../../middleware/respond.js';
|
|
13
12
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
14
13
|
import { UsersService } from '../../services/users.js';
|
|
@@ -38,6 +37,7 @@ export class SAMLAuthDriver extends LocalAuthDriver {
|
|
|
38
37
|
return user?.id;
|
|
39
38
|
}
|
|
40
39
|
async getUserID(payload) {
|
|
40
|
+
const logger = useLogger();
|
|
41
41
|
const { provider, emailKey, identifierKey, givenNameKey, familyNameKey, allowPublicRegistration } = this.config;
|
|
42
42
|
const email = payload[emailKey ?? 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'];
|
|
43
43
|
const identifier = payload[identifierKey ?? 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'];
|
|
@@ -79,6 +79,7 @@ export class SAMLAuthDriver extends LocalAuthDriver {
|
|
|
79
79
|
}
|
|
80
80
|
export function createSAMLAuthRouter(providerName) {
|
|
81
81
|
const router = Router();
|
|
82
|
+
const env = useEnv();
|
|
82
83
|
router.get('/metadata', asyncHandler(async (_req, res) => {
|
|
83
84
|
const { sp } = getAuthProvider(providerName);
|
|
84
85
|
return res.header('Content-Type', 'text/xml').send(sp.getMetadata());
|
|
@@ -106,6 +107,7 @@ export function createSAMLAuthRouter(providerName) {
|
|
|
106
107
|
return res.redirect(context);
|
|
107
108
|
}));
|
|
108
109
|
router.post('/acs', express.urlencoded({ extended: false }), asyncHandler(async (req, res, next) => {
|
|
110
|
+
const logger = useLogger();
|
|
109
111
|
const relayState = req.body?.RelayState;
|
|
110
112
|
try {
|
|
111
113
|
const { sp, idp } = getAuthProvider(providerName);
|
package/dist/auth.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
2
|
+
import { InvalidProviderConfigError } from '@directus/errors';
|
|
1
3
|
import { toArray } from '@directus/utils';
|
|
2
4
|
import { LDAPAuthDriver, LocalAuthDriver, OAuth2AuthDriver, OpenIDAuthDriver, SAMLAuthDriver, } from './auth/drivers/index.js';
|
|
3
5
|
import { DEFAULT_AUTH_PROVIDER } from './constants.js';
|
|
4
6
|
import getDatabase from './database/index.js';
|
|
5
|
-
import
|
|
6
|
-
import { InvalidProviderConfigError } from '@directus/errors';
|
|
7
|
-
import logger from './logger.js';
|
|
7
|
+
import { useLogger } from './logger.js';
|
|
8
8
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
9
9
|
import { getSchema } from './utils/get-schema.js';
|
|
10
|
-
const providerNames = toArray(env['AUTH_PROVIDERS']);
|
|
11
10
|
const providers = new Map();
|
|
12
11
|
export function getAuthProvider(provider) {
|
|
12
|
+
const logger = useLogger();
|
|
13
13
|
if (!providers.has(provider)) {
|
|
14
14
|
logger.error('Auth provider not configured');
|
|
15
15
|
throw new InvalidProviderConfigError({ provider });
|
|
@@ -17,7 +17,10 @@ export function getAuthProvider(provider) {
|
|
|
17
17
|
return providers.get(provider);
|
|
18
18
|
}
|
|
19
19
|
export async function registerAuthProviders() {
|
|
20
|
+
const env = useEnv();
|
|
21
|
+
const logger = useLogger();
|
|
20
22
|
const options = { knex: getDatabase(), schema: await getSchema() };
|
|
23
|
+
const providerNames = toArray(env['AUTH_PROVIDERS']);
|
|
21
24
|
// Register default provider if not disabled
|
|
22
25
|
if (!env['AUTH_DISABLE_DEFAULT']) {
|
|
23
26
|
const defaultProvider = getProviderInstance('local', options);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useBus } from './lib/use-bus.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useBus } from './lib/use-bus.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Bus } from '@directus/memory';
|
|
2
|
+
export declare const _cache: {
|
|
3
|
+
bus: Bus | undefined;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Returns globally shared message bus. If Redis is available, will use a redis-driven pub/sub bus.
|
|
7
|
+
* Otherwise will default to a local-only bus.
|
|
8
|
+
*/
|
|
9
|
+
export declare const useBus: () => Bus;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createBus } from '@directus/memory';
|
|
2
|
+
import { redisConfigAvailable, useRedis } from '../../redis/index.js';
|
|
3
|
+
export const _cache = {
|
|
4
|
+
bus: undefined,
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Returns globally shared message bus. If Redis is available, will use a redis-driven pub/sub bus.
|
|
8
|
+
* Otherwise will default to a local-only bus.
|
|
9
|
+
*/
|
|
10
|
+
export const useBus = () => {
|
|
11
|
+
if (_cache.bus) {
|
|
12
|
+
return _cache.bus;
|
|
13
|
+
}
|
|
14
|
+
if (redisConfigAvailable()) {
|
|
15
|
+
_cache.bus = createBus({ type: 'redis', redis: useRedis(), namespace: 'directus:bus' });
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
_cache.bus = createBus({ type: 'local' });
|
|
19
|
+
}
|
|
20
|
+
return _cache.bus;
|
|
21
|
+
};
|
package/dist/cache.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
1
2
|
import { getSimpleHash } from '@directus/utils';
|
|
2
3
|
import Keyv from 'keyv';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
4
|
+
import { useBus } from './bus/index.js';
|
|
5
|
+
import { useLogger } from './logger.js';
|
|
6
|
+
import { redisConfigAvailable } from './redis/index.js';
|
|
6
7
|
import { compress, decompress } from './utils/compress.js';
|
|
7
8
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
8
9
|
import { getMilliseconds } from './utils/get-milliseconds.js';
|
|
9
10
|
import { validateEnv } from './utils/validate-env.js';
|
|
10
11
|
import { createRequire } from 'node:module';
|
|
12
|
+
const logger = useLogger();
|
|
13
|
+
const env = useEnv();
|
|
11
14
|
const require = createRequire(import.meta.url);
|
|
12
15
|
let cache = null;
|
|
13
16
|
let systemCache = null;
|
|
@@ -15,11 +18,8 @@ let localSchemaCache = null;
|
|
|
15
18
|
let sharedSchemaCache = null;
|
|
16
19
|
let lockCache = null;
|
|
17
20
|
let messengerSubscribed = false;
|
|
18
|
-
const messenger =
|
|
19
|
-
if (env['
|
|
20
|
-
env['CACHE_STORE'] === 'memory' &&
|
|
21
|
-
env['CACHE_AUTO_PURGE'] &&
|
|
22
|
-
!messengerSubscribed) {
|
|
21
|
+
const messenger = useBus();
|
|
22
|
+
if (redisConfigAvailable() && env['CACHE_STORE'] === 'memory' && env['CACHE_AUTO_PURGE'] && !messengerSubscribed) {
|
|
23
23
|
messengerSubscribed = true;
|
|
24
24
|
messenger.subscribe('schemaChanged', async (opts) => {
|
|
25
25
|
if (cache && opts?.['autoPurgeCache'] !== false) {
|
|
@@ -122,7 +122,7 @@ function getConfig(store = 'memory', ttl, namespaceSuffix = '') {
|
|
|
122
122
|
};
|
|
123
123
|
if (store === 'redis') {
|
|
124
124
|
const KeyvRedis = require('@keyv/redis');
|
|
125
|
-
config.store = new KeyvRedis(env['REDIS'] || getConfigFromEnv('REDIS'));
|
|
125
|
+
config.store = new KeyvRedis(env['REDIS'] || getConfigFromEnv('REDIS'), { useRedisSets: false });
|
|
126
126
|
}
|
|
127
127
|
return config;
|
|
128
128
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
1
2
|
import getDatabase, { hasDatabaseConnection, isInstalled, validateDatabaseConnection, } from '../../../database/index.js';
|
|
2
3
|
import runMigrations from '../../../database/migrations/run.js';
|
|
3
4
|
import installDatabase from '../../../database/seeds/run.js';
|
|
4
|
-
import
|
|
5
|
-
import logger from '../../../logger.js';
|
|
5
|
+
import { useLogger } from '../../../logger.js';
|
|
6
6
|
import { RolesService } from '../../../services/roles.js';
|
|
7
7
|
import { SettingsService } from '../../../services/settings.js';
|
|
8
8
|
import { UsersService } from '../../../services/users.js';
|
|
9
9
|
import { getSchema } from '../../../utils/get-schema.js';
|
|
10
10
|
import { defaultAdminRole, defaultAdminUser } from '../../utils/defaults.js';
|
|
11
11
|
export default async function bootstrap({ skipAdminInit }) {
|
|
12
|
+
const logger = useLogger();
|
|
12
13
|
logger.info('Initializing bootstrap...');
|
|
14
|
+
const env = useEnv();
|
|
13
15
|
const database = getDatabase();
|
|
14
16
|
await waitForDatabase(database);
|
|
15
17
|
if ((await isInstalled()) === false) {
|
|
@@ -52,6 +54,8 @@ async function waitForDatabase(database) {
|
|
|
52
54
|
return database;
|
|
53
55
|
}
|
|
54
56
|
async function createDefaultAdmin(schema) {
|
|
57
|
+
const logger = useLogger();
|
|
58
|
+
const env = useEnv();
|
|
55
59
|
const { nanoid } = await import('nanoid');
|
|
56
60
|
logger.info('Setting up first admin role...');
|
|
57
61
|
const rolesService = new RolesService({ schema });
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import getDatabase from '../../../database/index.js';
|
|
2
|
-
import
|
|
2
|
+
import { useLogger } from '../../../logger.js';
|
|
3
3
|
export default async function count(collection) {
|
|
4
4
|
const database = getDatabase();
|
|
5
|
+
const logger = useLogger();
|
|
5
6
|
if (!collection) {
|
|
6
7
|
logger.error('Collection is required');
|
|
7
8
|
process.exit(1);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import installSeeds from '../../../database/seeds/run.js';
|
|
2
2
|
import getDatabase from '../../../database/index.js';
|
|
3
|
-
import
|
|
3
|
+
import { useLogger } from '../../../logger.js';
|
|
4
4
|
export default async function start() {
|
|
5
5
|
const database = getDatabase();
|
|
6
|
+
const logger = useLogger();
|
|
6
7
|
try {
|
|
7
8
|
await installSeeds(database);
|
|
8
9
|
database.destroy();
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import run from '../../../database/migrations/run.js';
|
|
2
2
|
import getDatabase from '../../../database/index.js';
|
|
3
|
-
import
|
|
3
|
+
import { useLogger } from '../../../logger.js';
|
|
4
4
|
export default async function migrate(direction) {
|
|
5
5
|
const database = getDatabase();
|
|
6
|
+
const logger = useLogger();
|
|
6
7
|
try {
|
|
7
8
|
logger.info('Running migrations...');
|
|
8
9
|
await run(database, direction);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { getSchema } from '../../../utils/get-schema.js';
|
|
2
2
|
import { RolesService } from '../../../services/roles.js';
|
|
3
3
|
import getDatabase from '../../../database/index.js';
|
|
4
|
-
import
|
|
4
|
+
import { useLogger } from '../../../logger.js';
|
|
5
5
|
export default async function rolesCreate({ role: name, admin }) {
|
|
6
6
|
const database = getDatabase();
|
|
7
|
+
const logger = useLogger();
|
|
7
8
|
if (!name) {
|
|
8
9
|
logger.error('Name is required');
|
|
9
10
|
process.exit(1);
|