@directus/api 11.0.1 → 12.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 +3 -4
- package/dist/auth/auth.d.ts +4 -4
- package/dist/auth/auth.js +2 -2
- package/dist/auth/drivers/ldap.js +20 -17
- package/dist/auth/drivers/local.js +5 -5
- package/dist/auth/drivers/oauth2.js +16 -16
- package/dist/auth/drivers/openid.js +18 -17
- package/dist/auth/drivers/saml.js +6 -7
- package/dist/auth.js +3 -2
- package/dist/cache.js +3 -13
- package/dist/cli/utils/create-env/env-stub.liquid +5 -7
- package/dist/controllers/activity.js +7 -6
- package/dist/controllers/assets.js +25 -12
- package/dist/controllers/auth.js +8 -7
- package/dist/controllers/collections.js +4 -3
- package/dist/controllers/dashboards.js +5 -4
- package/dist/controllers/extensions.js +3 -3
- package/dist/controllers/fields.js +9 -8
- package/dist/controllers/files.js +11 -11
- package/dist/controllers/flows.js +5 -4
- package/dist/controllers/folders.js +5 -4
- package/dist/controllers/items.js +14 -13
- package/dist/controllers/not-found.js +2 -2
- package/dist/controllers/notifications.js +5 -4
- package/dist/controllers/operations.js +5 -4
- package/dist/controllers/panels.js +5 -4
- package/dist/controllers/permissions.js +5 -4
- package/dist/controllers/presets.js +5 -4
- package/dist/controllers/relations.js +6 -5
- package/dist/controllers/roles.js +5 -4
- package/dist/controllers/schema.js +8 -8
- package/dist/controllers/server.js +2 -2
- package/dist/controllers/settings.js +3 -2
- package/dist/controllers/shares.js +7 -6
- package/dist/controllers/translations.js +6 -5
- package/dist/controllers/users.js +22 -21
- package/dist/controllers/utils.js +10 -10
- package/dist/controllers/webhooks.js +5 -4
- package/dist/{exceptions/database → database/errors}/dialects/mssql.js +8 -18
- package/dist/{exceptions/database → database/errors}/dialects/mysql.js +9 -19
- package/dist/{exceptions/database → database/errors}/dialects/oracle.js +2 -2
- package/dist/{exceptions/database → database/errors}/dialects/postgres.js +7 -18
- package/dist/{exceptions/database → database/errors}/dialects/sqlite.js +7 -10
- package/dist/{exceptions/database → database/errors}/translate.js +1 -1
- package/dist/database/migrations/run.js +10 -1
- package/dist/emitter.d.ts +3 -2
- package/dist/emitter.js +12 -4
- package/dist/env.js +21 -17
- package/dist/errors/codes.d.ts +29 -0
- package/dist/errors/codes.js +30 -0
- package/dist/errors/contains-null-values.d.ts +7 -0
- package/dist/errors/contains-null-values.js +4 -0
- package/dist/errors/content-too-large.d.ts +1 -0
- package/dist/errors/content-too-large.js +3 -0
- package/dist/errors/forbidden.d.ts +1 -0
- package/dist/errors/forbidden.js +3 -0
- package/dist/errors/hit-rate-limit.d.ts +6 -0
- package/dist/errors/hit-rate-limit.js +8 -0
- package/dist/errors/illegal-asset-transformation.d.ts +4 -0
- package/dist/errors/illegal-asset-transformation.js +3 -0
- package/dist/errors/index.d.ts +28 -0
- package/dist/errors/index.js +28 -0
- package/dist/errors/invalid-credentials.d.ts +1 -0
- package/dist/errors/invalid-credentials.js +3 -0
- package/dist/errors/invalid-foreign-key.d.ts +6 -0
- package/dist/errors/invalid-foreign-key.js +14 -0
- package/dist/errors/invalid-ip.d.ts +1 -0
- package/dist/errors/invalid-ip.js +3 -0
- package/dist/errors/invalid-otp.d.ts +1 -0
- package/dist/errors/invalid-otp.js +3 -0
- package/dist/errors/invalid-payload.d.ts +5 -0
- package/dist/errors/invalid-payload.js +4 -0
- package/dist/errors/invalid-provider-config.d.ts +5 -0
- package/dist/errors/invalid-provider-config.js +3 -0
- package/dist/errors/invalid-provider.d.ts +1 -0
- package/dist/errors/invalid-provider.js +3 -0
- package/dist/errors/invalid-query.d.ts +5 -0
- package/dist/errors/invalid-query.js +4 -0
- package/dist/errors/invalid-token.d.ts +1 -0
- package/dist/errors/invalid-token.js +3 -0
- package/dist/errors/method-not-allowed.d.ts +6 -0
- package/dist/errors/method-not-allowed.js +6 -0
- package/dist/errors/not-null-violation.d.ts +6 -0
- package/dist/errors/not-null-violation.js +14 -0
- package/dist/errors/range-not-satisfiable.d.ts +7 -0
- package/dist/errors/range-not-satisfiable.js +7 -0
- package/dist/errors/record-not-unique.d.ts +6 -0
- package/dist/errors/record-not-unique.js +14 -0
- package/dist/errors/route-not-found.d.ts +5 -0
- package/dist/errors/route-not-found.js +4 -0
- package/dist/errors/service-unavailable.d.ts +7 -0
- package/dist/errors/service-unavailable.js +4 -0
- package/dist/errors/token-expired.d.ts +1 -0
- package/dist/errors/token-expired.js +3 -0
- package/dist/errors/unexpected-response.d.ts +1 -0
- package/dist/errors/unexpected-response.js +3 -0
- package/dist/errors/unprocessable-content.d.ts +5 -0
- package/dist/errors/unprocessable-content.js +4 -0
- package/dist/errors/unsupported-media-type.d.ts +6 -0
- package/dist/errors/unsupported-media-type.js +4 -0
- package/dist/errors/user-suspended.d.ts +1 -0
- package/dist/errors/user-suspended.js +3 -0
- package/dist/errors/value-out-of-range.d.ts +6 -0
- package/dist/errors/value-out-of-range.js +14 -0
- package/dist/errors/value-too-long.d.ts +6 -0
- package/dist/errors/value-too-long.js +14 -0
- package/dist/extensions.js +0 -4
- package/dist/flows.js +6 -8
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/messenger.d.ts +3 -3
- package/dist/messenger.js +18 -9
- package/dist/middleware/authenticate.js +2 -38
- package/dist/middleware/check-ip.js +2 -2
- package/dist/middleware/collection-exists.js +2 -2
- package/dist/middleware/error-handler.js +7 -7
- package/dist/middleware/graphql.js +11 -9
- package/dist/middleware/rate-limiter-global.d.ts +2 -2
- package/dist/middleware/rate-limiter-global.js +2 -3
- package/dist/middleware/rate-limiter-ip.d.ts +2 -2
- package/dist/middleware/rate-limiter-ip.js +2 -3
- package/dist/middleware/validate-batch.js +3 -4
- package/dist/rate-limiter.js +2 -9
- package/dist/server.js +10 -0
- package/dist/services/activity.js +3 -2
- package/dist/services/assets.js +9 -10
- package/dist/services/authentication.js +12 -11
- package/dist/services/authorization.d.ts +1 -1
- package/dist/services/authorization.js +16 -16
- package/dist/services/collections.js +17 -16
- package/dist/services/fields.js +16 -14
- package/dist/services/files.js +7 -6
- package/dist/services/graphql/errors/execution.d.ts +6 -0
- package/dist/services/graphql/errors/execution.js +2 -0
- package/dist/services/graphql/errors/index.d.ts +2 -0
- package/dist/services/graphql/errors/index.js +2 -0
- package/dist/services/graphql/errors/validation.d.ts +6 -0
- package/dist/services/graphql/errors/validation.js +2 -0
- package/dist/services/graphql/index.d.ts +2 -8
- package/dist/services/graphql/index.js +125 -66
- package/dist/services/graphql/subscription.d.ts +16 -0
- package/dist/services/graphql/subscription.js +77 -0
- package/dist/services/graphql/utils/process-error.js +3 -3
- package/dist/services/import-export.js +7 -7
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/items.js +14 -13
- package/dist/services/mail/index.js +3 -3
- package/dist/services/meta.js +3 -3
- package/dist/services/payload.js +11 -7
- package/dist/services/relations.js +32 -22
- package/dist/services/revisions.js +3 -3
- package/dist/services/roles.js +10 -9
- package/dist/services/schema.js +5 -5
- package/dist/services/server.js +24 -0
- package/dist/services/shares.js +4 -4
- package/dist/services/tfa.js +6 -6
- package/dist/services/translations.d.ts +2 -2
- package/dist/services/translations.js +4 -4
- package/dist/services/users.js +26 -29
- package/dist/services/utils.js +4 -4
- package/dist/services/websocket.d.ts +14 -0
- package/dist/services/websocket.js +26 -0
- package/dist/synchronization.js +3 -3
- package/dist/types/items.d.ts +2 -2
- package/dist/utils/apply-diff.js +13 -4
- package/dist/utils/apply-query.js +22 -13
- package/dist/utils/get-accountability-for-role.js +1 -2
- package/dist/utils/get-accountability-for-token.d.ts +2 -0
- package/dist/utils/get-accountability-for-token.js +50 -0
- package/dist/utils/get-column-path.js +5 -3
- package/dist/utils/get-column.js +3 -3
- package/dist/utils/get-service.d.ts +7 -0
- package/dist/utils/get-service.js +49 -0
- package/dist/utils/jwt.js +5 -5
- package/dist/utils/redact.d.ts +4 -0
- package/dist/utils/redact.js +15 -1
- package/dist/utils/to-boolean.d.ts +4 -0
- package/dist/utils/to-boolean.js +6 -0
- package/dist/utils/validate-diff.js +23 -9
- package/dist/utils/validate-keys.js +3 -3
- package/dist/utils/validate-query.d.ts +2 -0
- package/dist/utils/validate-query.js +27 -21
- package/dist/utils/validate-snapshot.js +11 -5
- package/dist/websocket/authenticate.d.ts +6 -0
- package/dist/websocket/authenticate.js +59 -0
- package/dist/websocket/controllers/base.d.ts +42 -0
- package/dist/websocket/controllers/base.js +279 -0
- package/dist/websocket/controllers/graphql.d.ts +12 -0
- package/dist/websocket/controllers/graphql.js +102 -0
- package/dist/websocket/controllers/hooks.d.ts +1 -0
- package/dist/websocket/controllers/hooks.js +122 -0
- package/dist/websocket/controllers/index.d.ts +10 -0
- package/dist/websocket/controllers/index.js +31 -0
- package/dist/websocket/controllers/rest.d.ts +9 -0
- package/dist/websocket/controllers/rest.js +47 -0
- package/dist/websocket/errors.d.ts +16 -0
- package/dist/websocket/errors.js +55 -0
- package/dist/websocket/handlers/heartbeat.d.ts +11 -0
- package/dist/websocket/handlers/heartbeat.js +72 -0
- package/dist/websocket/handlers/index.d.ts +4 -0
- package/dist/websocket/handlers/index.js +11 -0
- package/dist/websocket/handlers/items.d.ts +6 -0
- package/dist/websocket/handlers/items.js +103 -0
- package/dist/websocket/handlers/subscribe.d.ts +43 -0
- package/dist/websocket/handlers/subscribe.js +278 -0
- package/dist/websocket/messages.d.ts +311 -0
- package/dist/websocket/messages.js +96 -0
- package/dist/websocket/types.d.ts +34 -0
- package/dist/websocket/types.js +1 -0
- package/dist/websocket/utils/get-expires-at-for-token.d.ts +1 -0
- package/dist/websocket/utils/get-expires-at-for-token.js +8 -0
- package/dist/websocket/utils/message.d.ts +4 -0
- package/dist/websocket/utils/message.js +27 -0
- package/dist/websocket/utils/wait-for-message.d.ts +4 -0
- package/dist/websocket/utils/wait-for-message.js +45 -0
- package/package.json +21 -16
- package/dist/exceptions/content-too-large.d.ts +0 -4
- package/dist/exceptions/content-too-large.js +0 -6
- package/dist/exceptions/database/contains-null-values.d.ts +0 -9
- package/dist/exceptions/database/contains-null-values.js +0 -6
- package/dist/exceptions/database/invalid-foreign-key.d.ts +0 -10
- package/dist/exceptions/database/invalid-foreign-key.js +0 -11
- package/dist/exceptions/database/not-null-violation.d.ts +0 -9
- package/dist/exceptions/database/not-null-violation.js +0 -6
- package/dist/exceptions/database/record-not-unique.d.ts +0 -10
- package/dist/exceptions/database/record-not-unique.js +0 -11
- package/dist/exceptions/database/value-out-of-range.d.ts +0 -10
- package/dist/exceptions/database/value-out-of-range.js +0 -11
- package/dist/exceptions/database/value-too-long.d.ts +0 -9
- package/dist/exceptions/database/value-too-long.js +0 -11
- package/dist/exceptions/forbidden.d.ts +0 -6
- package/dist/exceptions/forbidden.js +0 -13
- package/dist/exceptions/graphql-validation.d.ts +0 -4
- package/dist/exceptions/graphql-validation.js +0 -6
- package/dist/exceptions/hit-rate-limit.d.ts +0 -9
- package/dist/exceptions/hit-rate-limit.js +0 -6
- package/dist/exceptions/illegal-asset-transformation.d.ts +0 -4
- package/dist/exceptions/illegal-asset-transformation.js +0 -6
- package/dist/exceptions/index.d.ts +0 -21
- package/dist/exceptions/index.js +0 -21
- package/dist/exceptions/invalid-config.d.ts +0 -4
- package/dist/exceptions/invalid-config.js +0 -6
- package/dist/exceptions/invalid-credentials.d.ts +0 -4
- package/dist/exceptions/invalid-credentials.js +0 -6
- package/dist/exceptions/invalid-ip.d.ts +0 -4
- package/dist/exceptions/invalid-ip.js +0 -6
- package/dist/exceptions/invalid-otp.d.ts +0 -4
- package/dist/exceptions/invalid-otp.js +0 -6
- package/dist/exceptions/invalid-payload.d.ts +0 -4
- package/dist/exceptions/invalid-payload.js +0 -6
- package/dist/exceptions/invalid-provider.d.ts +0 -4
- package/dist/exceptions/invalid-provider.js +0 -6
- package/dist/exceptions/invalid-query.d.ts +0 -4
- package/dist/exceptions/invalid-query.js +0 -6
- package/dist/exceptions/invalid-token.d.ts +0 -4
- package/dist/exceptions/invalid-token.js +0 -6
- package/dist/exceptions/method-not-allowed.d.ts +0 -8
- package/dist/exceptions/method-not-allowed.js +0 -6
- package/dist/exceptions/range-not-satisfiable.d.ts +0 -5
- package/dist/exceptions/range-not-satisfiable.js +0 -9
- package/dist/exceptions/route-not-found.d.ts +0 -4
- package/dist/exceptions/route-not-found.js +0 -6
- package/dist/exceptions/service-unavailable.d.ts +0 -9
- package/dist/exceptions/service-unavailable.js +0 -6
- package/dist/exceptions/token-expired.d.ts +0 -4
- package/dist/exceptions/token-expired.js +0 -6
- package/dist/exceptions/unexpected-response.d.ts +0 -4
- package/dist/exceptions/unexpected-response.js +0 -6
- package/dist/exceptions/unprocessable-entity.d.ts +0 -4
- package/dist/exceptions/unprocessable-entity.js +0 -6
- package/dist/exceptions/unsupported-media-type.d.ts +0 -4
- package/dist/exceptions/unsupported-media-type.js +0 -6
- package/dist/exceptions/user-suspended.d.ts +0 -4
- package/dist/exceptions/user-suspended.js +0 -6
- /package/dist/{exceptions/database → database/errors}/dialects/mssql.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/mysql.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/oracle.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/postgres.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/sqlite.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/types.d.ts +0 -0
- /package/dist/{exceptions/database → database/errors}/dialects/types.js +0 -0
- /package/dist/{exceptions/database → database/errors}/translate.d.ts +0 -0
package/dist/app.js
CHANGED
|
@@ -39,8 +39,7 @@ import webhooksRouter from './controllers/webhooks.js';
|
|
|
39
39
|
import { isInstalled, validateDatabaseConnection, validateDatabaseExtensions, validateMigrations, } from './database/index.js';
|
|
40
40
|
import emitter from './emitter.js';
|
|
41
41
|
import env from './env.js';
|
|
42
|
-
import {
|
|
43
|
-
import { ServiceUnavailableException } from './exceptions/service-unavailable.js';
|
|
42
|
+
import { InvalidPayloadError, ServiceUnavailableError } from './errors/index.js';
|
|
44
43
|
import { getExtensionManager } from './extensions.js';
|
|
45
44
|
import { getFlowManager } from './flows.js';
|
|
46
45
|
import logger, { expressLogger } from './logger.js';
|
|
@@ -98,7 +97,7 @@ export default async function createApp() {
|
|
|
98
97
|
maxEventLoopDelay: env['PRESSURE_LIMITER_MAX_EVENT_LOOP_DELAY'],
|
|
99
98
|
maxMemoryRss: env['PRESSURE_LIMITER_MAX_MEMORY_RSS'],
|
|
100
99
|
maxMemoryHeapUsed: env['PRESSURE_LIMITER_MAX_MEMORY_HEAP_USED'],
|
|
101
|
-
error: new
|
|
100
|
+
error: new ServiceUnavailableError({ service: 'api', reason: 'Under pressure' }),
|
|
102
101
|
retryAfter: env['PRESSURE_LIMITER_RETRY_AFTER'],
|
|
103
102
|
}));
|
|
104
103
|
}
|
|
@@ -137,7 +136,7 @@ export default async function createApp() {
|
|
|
137
136
|
limit: env['MAX_PAYLOAD_SIZE'],
|
|
138
137
|
})(req, res, (err) => {
|
|
139
138
|
if (err) {
|
|
140
|
-
return next(new
|
|
139
|
+
return next(new InvalidPayloadError({ reason: err.message }));
|
|
141
140
|
}
|
|
142
141
|
return next();
|
|
143
142
|
});
|
package/dist/auth/auth.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare abstract class AuthDriver {
|
|
|
9
9
|
* Get user id for a given provider payload
|
|
10
10
|
*
|
|
11
11
|
* @param payload Any data that the user might've provided
|
|
12
|
-
* @throws
|
|
12
|
+
* @throws InvalidCredentialsError
|
|
13
13
|
* @return User id of the identifier
|
|
14
14
|
*/
|
|
15
15
|
abstract getUserID(payload: Record<string, any>): Promise<string>;
|
|
@@ -18,7 +18,7 @@ export declare abstract class AuthDriver {
|
|
|
18
18
|
*
|
|
19
19
|
* @param user User information
|
|
20
20
|
* @param password User password
|
|
21
|
-
* @throws
|
|
21
|
+
* @throws InvalidCredentialsError
|
|
22
22
|
*/
|
|
23
23
|
abstract verify(user: User, password?: string): Promise<void>;
|
|
24
24
|
/**
|
|
@@ -26,7 +26,7 @@ export declare abstract class AuthDriver {
|
|
|
26
26
|
*
|
|
27
27
|
* @param _user User information
|
|
28
28
|
* @param _payload Any data that the user might've provided
|
|
29
|
-
* @throws
|
|
29
|
+
* @throws InvalidCredentialsError
|
|
30
30
|
* @returns Data to be stored with the session
|
|
31
31
|
*/
|
|
32
32
|
login(_user: User, _payload: Record<string, any>): Promise<void>;
|
|
@@ -34,7 +34,7 @@ export declare abstract class AuthDriver {
|
|
|
34
34
|
* Handle user session refresh
|
|
35
35
|
*
|
|
36
36
|
* @param _user User information
|
|
37
|
-
* @throws
|
|
37
|
+
* @throws InvalidCredentialsError
|
|
38
38
|
*/
|
|
39
39
|
refresh(_user: User): Promise<void>;
|
|
40
40
|
/**
|
package/dist/auth/auth.js
CHANGED
|
@@ -10,7 +10,7 @@ export class AuthDriver {
|
|
|
10
10
|
*
|
|
11
11
|
* @param _user User information
|
|
12
12
|
* @param _payload Any data that the user might've provided
|
|
13
|
-
* @throws
|
|
13
|
+
* @throws InvalidCredentialsError
|
|
14
14
|
* @returns Data to be stored with the session
|
|
15
15
|
*/
|
|
16
16
|
async login(_user, _payload) {
|
|
@@ -20,7 +20,7 @@ export class AuthDriver {
|
|
|
20
20
|
* Handle user session refresh
|
|
21
21
|
*
|
|
22
22
|
* @param _user User information
|
|
23
|
-
* @throws
|
|
23
|
+
* @throws InvalidCredentialsError
|
|
24
24
|
*/
|
|
25
25
|
async refresh(_user) {
|
|
26
26
|
return;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
1
2
|
import { Router } from 'express';
|
|
2
3
|
import Joi from 'joi';
|
|
3
4
|
import ldap from 'ldapjs';
|
|
4
5
|
import getDatabase from '../../database/index.js';
|
|
5
6
|
import emitter from '../../emitter.js';
|
|
6
7
|
import env from '../../env.js';
|
|
7
|
-
import {
|
|
8
|
-
import { InvalidConfigException, InvalidCredentialsException, InvalidPayloadException, InvalidProviderException, ServiceUnavailableException, UnexpectedResponseException, } from '../../exceptions/index.js';
|
|
8
|
+
import { ErrorCode, InvalidCredentialsError, InvalidPayloadError, InvalidProviderError, InvalidProviderConfigError, ServiceUnavailableError, UnexpectedResponseError, } from '../../errors/index.js';
|
|
9
9
|
import logger from '../../logger.js';
|
|
10
10
|
import { respond } from '../../middleware/respond.js';
|
|
11
11
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
@@ -30,7 +30,8 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
30
30
|
!userDn ||
|
|
31
31
|
!provider ||
|
|
32
32
|
(!clientUrl && !config['client']?.socketPath)) {
|
|
33
|
-
|
|
33
|
+
logger.error('Invalid provider config');
|
|
34
|
+
throw new InvalidProviderConfigError({ provider });
|
|
34
35
|
}
|
|
35
36
|
const clientConfig = typeof config['client'] === 'object' ? config['client'] : {};
|
|
36
37
|
this.bindClient = ldap.createClient({ url: clientUrl, reconnect: true, ...clientConfig });
|
|
@@ -57,8 +58,9 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
57
58
|
this.bindClient.bind(bindDn, bindPassword, (err) => {
|
|
58
59
|
if (err) {
|
|
59
60
|
const error = handleError(err);
|
|
60
|
-
if (error
|
|
61
|
-
|
|
61
|
+
if (isDirectusError(error, ErrorCode.InvalidCredentials)) {
|
|
62
|
+
logger.warn('Invalid bind user');
|
|
63
|
+
reject(new InvalidProviderConfigError({ provider }));
|
|
62
64
|
}
|
|
63
65
|
else {
|
|
64
66
|
reject(error);
|
|
@@ -72,7 +74,8 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
72
74
|
res.on('end', (result) => {
|
|
73
75
|
// Handle edge case where authenticated bind user cannot read their own DN
|
|
74
76
|
if (result?.status === 0) {
|
|
75
|
-
|
|
77
|
+
logger.warn('[LDAP] Failed to find bind user record');
|
|
78
|
+
reject(new UnexpectedResponseError());
|
|
76
79
|
}
|
|
77
80
|
});
|
|
78
81
|
});
|
|
@@ -162,7 +165,7 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
162
165
|
}
|
|
163
166
|
async getUserID(payload) {
|
|
164
167
|
if (!payload['identifier']) {
|
|
165
|
-
throw new
|
|
168
|
+
throw new InvalidCredentialsError();
|
|
166
169
|
}
|
|
167
170
|
await this.validateBindClient();
|
|
168
171
|
const { userDn, userScope, userAttribute, groupDn, groupScope, groupAttribute, defaultRoleId } = this.config;
|
|
@@ -171,7 +174,7 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
171
174
|
value: payload['identifier'],
|
|
172
175
|
}), userScope ?? 'one');
|
|
173
176
|
if (!userInfo?.dn) {
|
|
174
|
-
throw new
|
|
177
|
+
throw new InvalidCredentialsError();
|
|
175
178
|
}
|
|
176
179
|
let userRole;
|
|
177
180
|
if (groupDn) {
|
|
@@ -204,7 +207,7 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
204
207
|
return userId;
|
|
205
208
|
}
|
|
206
209
|
if (!userInfo) {
|
|
207
|
-
throw new
|
|
210
|
+
throw new InvalidCredentialsError();
|
|
208
211
|
}
|
|
209
212
|
const userPayload = {
|
|
210
213
|
provider: this.config['provider'],
|
|
@@ -221,9 +224,9 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
221
224
|
await this.usersService.createOne(updatedUserPayload);
|
|
222
225
|
}
|
|
223
226
|
catch (e) {
|
|
224
|
-
if (e
|
|
227
|
+
if (isDirectusError(e, ErrorCode.RecordNotUnique)) {
|
|
225
228
|
logger.warn(e, '[LDAP] Failed to register user. User not unique');
|
|
226
|
-
throw new
|
|
229
|
+
throw new InvalidProviderError();
|
|
227
230
|
}
|
|
228
231
|
throw e;
|
|
229
232
|
}
|
|
@@ -231,7 +234,7 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
231
234
|
}
|
|
232
235
|
async verify(user, password) {
|
|
233
236
|
if (!user.external_identifier || !password) {
|
|
234
|
-
throw new
|
|
237
|
+
throw new InvalidCredentialsError();
|
|
235
238
|
}
|
|
236
239
|
return new Promise((resolve, reject) => {
|
|
237
240
|
const clientConfig = typeof this.config['client'] === 'object' ? this.config['client'] : {};
|
|
@@ -261,7 +264,7 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
261
264
|
await this.validateBindClient();
|
|
262
265
|
const userInfo = await this.fetchUserInfo(user.external_identifier);
|
|
263
266
|
if (userInfo?.userAccountControl && userInfo.userAccountControl & INVALID_ACCOUNT_FLAGS) {
|
|
264
|
-
throw new
|
|
267
|
+
throw new InvalidCredentialsError();
|
|
265
268
|
}
|
|
266
269
|
}
|
|
267
270
|
}
|
|
@@ -269,11 +272,11 @@ const handleError = (e) => {
|
|
|
269
272
|
if (e instanceof ldap.InappropriateAuthenticationError ||
|
|
270
273
|
e instanceof ldap.InvalidCredentialsError ||
|
|
271
274
|
e instanceof ldap.InsufficientAccessRightsError) {
|
|
272
|
-
return new
|
|
275
|
+
return new InvalidCredentialsError();
|
|
273
276
|
}
|
|
274
|
-
return new
|
|
277
|
+
return new ServiceUnavailableError({
|
|
275
278
|
service: 'ldap',
|
|
276
|
-
|
|
279
|
+
reason: `Service returned unexpected error: ${e.message}`,
|
|
277
280
|
});
|
|
278
281
|
};
|
|
279
282
|
const getEntryValue = (value) => {
|
|
@@ -304,7 +307,7 @@ export function createLDAPAuthRouter(provider) {
|
|
|
304
307
|
});
|
|
305
308
|
const { error } = loginSchema.validate(req.body);
|
|
306
309
|
if (error) {
|
|
307
|
-
throw new
|
|
310
|
+
throw new InvalidPayloadError({ reason: error.message });
|
|
308
311
|
}
|
|
309
312
|
const mode = req.body.mode || 'json';
|
|
310
313
|
const { accessToken, refreshToken, expires } = await authenticationService.login(provider, req.body, req.body?.otp);
|
|
@@ -4,7 +4,7 @@ import Joi from 'joi';
|
|
|
4
4
|
import { performance } from 'perf_hooks';
|
|
5
5
|
import { COOKIE_OPTIONS } from '../../constants.js';
|
|
6
6
|
import env from '../../env.js';
|
|
7
|
-
import {
|
|
7
|
+
import { InvalidCredentialsError, InvalidPayloadError } from '../../errors/index.js';
|
|
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';
|
|
@@ -14,7 +14,7 @@ import { AuthDriver } from '../auth.js';
|
|
|
14
14
|
export class LocalAuthDriver extends AuthDriver {
|
|
15
15
|
async getUserID(payload) {
|
|
16
16
|
if (!payload['email']) {
|
|
17
|
-
throw new
|
|
17
|
+
throw new InvalidCredentialsError();
|
|
18
18
|
}
|
|
19
19
|
const user = await this.knex
|
|
20
20
|
.select('id')
|
|
@@ -22,13 +22,13 @@ export class LocalAuthDriver extends AuthDriver {
|
|
|
22
22
|
.whereRaw('LOWER(??) = ?', ['email', payload['email'].toLowerCase()])
|
|
23
23
|
.first();
|
|
24
24
|
if (!user) {
|
|
25
|
-
throw new
|
|
25
|
+
throw new InvalidCredentialsError();
|
|
26
26
|
}
|
|
27
27
|
return user.id;
|
|
28
28
|
}
|
|
29
29
|
async verify(user, password) {
|
|
30
30
|
if (!user.password || !(await argon2.verify(user.password, password))) {
|
|
31
|
-
throw new
|
|
31
|
+
throw new InvalidCredentialsError();
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
async login(user, payload) {
|
|
@@ -63,7 +63,7 @@ export function createLocalAuthRouter(provider) {
|
|
|
63
63
|
const { error } = userLoginSchema.validate(req.body);
|
|
64
64
|
if (error) {
|
|
65
65
|
await stall(STALL_TIME, timeStart);
|
|
66
|
-
throw new
|
|
66
|
+
throw new InvalidPayloadError({ reason: error.message });
|
|
67
67
|
}
|
|
68
68
|
const mode = req.body.mode || 'json';
|
|
69
69
|
const { accessToken, refreshToken, expires } = await authenticationService.login(provider, req.body, req.body?.otp);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
2
2
|
import { parseJSON } from '@directus/utils';
|
|
3
3
|
import express, { Router } from 'express';
|
|
4
4
|
import flatten from 'flat';
|
|
@@ -8,8 +8,7 @@ import { getAuthProvider } from '../../auth.js';
|
|
|
8
8
|
import getDatabase from '../../database/index.js';
|
|
9
9
|
import emitter from '../../emitter.js';
|
|
10
10
|
import env from '../../env.js';
|
|
11
|
-
import {
|
|
12
|
-
import { InvalidConfigException, InvalidCredentialsException, InvalidProviderException, InvalidTokenException, ServiceUnavailableException, } from '../../exceptions/index.js';
|
|
11
|
+
import { ErrorCode, InvalidCredentialsError, InvalidProviderError, InvalidProviderConfigError, InvalidTokenError, ServiceUnavailableError, } from '../../errors/index.js';
|
|
13
12
|
import logger from '../../logger.js';
|
|
14
13
|
import { respond } from '../../middleware/respond.js';
|
|
15
14
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
@@ -29,7 +28,8 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
29
28
|
super(options, config);
|
|
30
29
|
const { authorizeUrl, accessUrl, profileUrl, clientId, clientSecret, ...additionalConfig } = config;
|
|
31
30
|
if (!authorizeUrl || !accessUrl || !profileUrl || !clientId || !clientSecret || !additionalConfig['provider']) {
|
|
32
|
-
|
|
31
|
+
logger.error('Invalid provider config');
|
|
32
|
+
throw new InvalidProviderConfigError({ provider: additionalConfig['provider'] });
|
|
33
33
|
}
|
|
34
34
|
const redirectUrl = new Url(env['PUBLIC_URL']).addPath('auth', 'login', additionalConfig['provider'], 'callback');
|
|
35
35
|
this.redirectUrl = redirectUrl.toString();
|
|
@@ -83,7 +83,7 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
83
83
|
async getUserID(payload) {
|
|
84
84
|
if (!payload['code'] || !payload['codeVerifier'] || !payload['state']) {
|
|
85
85
|
logger.warn('[OAuth2] No code, codeVerifier or state in payload');
|
|
86
|
-
throw new
|
|
86
|
+
throw new InvalidCredentialsError();
|
|
87
87
|
}
|
|
88
88
|
let tokenSet;
|
|
89
89
|
let userInfo;
|
|
@@ -102,7 +102,7 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
102
102
|
const identifier = userInfo[identifierKey] ? String(userInfo[identifierKey]) : email;
|
|
103
103
|
if (!identifier) {
|
|
104
104
|
logger.warn(`[OAuth2] Failed to find user identifier for provider "${provider}"`);
|
|
105
|
-
throw new
|
|
105
|
+
throw new InvalidCredentialsError();
|
|
106
106
|
}
|
|
107
107
|
const userPayload = {
|
|
108
108
|
provider,
|
|
@@ -129,7 +129,7 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
129
129
|
// Is public registration allowed?
|
|
130
130
|
if (!allowPublicRegistration) {
|
|
131
131
|
logger.warn(`[OAuth2] User doesn't exist, and public registration not allowed for provider "${provider}"`);
|
|
132
|
-
throw new
|
|
132
|
+
throw new InvalidCredentialsError();
|
|
133
133
|
}
|
|
134
134
|
// Run hook so the end user has the chance to augment the
|
|
135
135
|
// user that is about to be created
|
|
@@ -142,9 +142,9 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
142
142
|
await this.usersService.createOne(updatedUserPayload);
|
|
143
143
|
}
|
|
144
144
|
catch (e) {
|
|
145
|
-
if (e
|
|
145
|
+
if (isDirectusError(e, ErrorCode.RecordNotUnique)) {
|
|
146
146
|
logger.warn(e, '[OAuth2] Failed to register user. User not unique');
|
|
147
|
-
throw new
|
|
147
|
+
throw new InvalidProviderError();
|
|
148
148
|
}
|
|
149
149
|
throw e;
|
|
150
150
|
}
|
|
@@ -184,19 +184,19 @@ const handleError = (e) => {
|
|
|
184
184
|
if (e.error === 'invalid_grant') {
|
|
185
185
|
// Invalid token
|
|
186
186
|
logger.trace(e, `[OAuth2] Invalid grant`);
|
|
187
|
-
return new
|
|
187
|
+
return new InvalidTokenError();
|
|
188
188
|
}
|
|
189
189
|
// Server response error
|
|
190
190
|
logger.trace(e, `[OAuth2] Unknown OP error`);
|
|
191
|
-
return new
|
|
191
|
+
return new ServiceUnavailableError({
|
|
192
192
|
service: 'oauth2',
|
|
193
|
-
|
|
193
|
+
reason: `Service returned unexpected response: ${e.error_description}`,
|
|
194
194
|
});
|
|
195
195
|
}
|
|
196
196
|
else if (e instanceof errors.RPError) {
|
|
197
197
|
// Internal client error
|
|
198
198
|
logger.trace(e, `[OAuth2] Unknown RP error`);
|
|
199
|
-
return new
|
|
199
|
+
return new InvalidCredentialsError();
|
|
200
200
|
}
|
|
201
201
|
logger.trace(e, `[OAuth2] Unknown error`);
|
|
202
202
|
return e;
|
|
@@ -229,7 +229,7 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
229
229
|
}
|
|
230
230
|
catch (e) {
|
|
231
231
|
logger.warn(e, `[OAuth2] Couldn't verify OAuth2 cookie`);
|
|
232
|
-
throw new
|
|
232
|
+
throw new InvalidCredentialsError();
|
|
233
233
|
}
|
|
234
234
|
const { verifier, redirect, prompt } = tokenData;
|
|
235
235
|
const accountability = {
|
|
@@ -257,12 +257,12 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
257
257
|
}
|
|
258
258
|
catch (error) {
|
|
259
259
|
// Prompt user for a new refresh_token if invalidated
|
|
260
|
-
if (error
|
|
260
|
+
if (isDirectusError(error, ErrorCode.InvalidToken) && !prompt) {
|
|
261
261
|
return res.redirect(`./?${redirect ? `redirect=${redirect}&` : ''}prompt=true`);
|
|
262
262
|
}
|
|
263
263
|
if (redirect) {
|
|
264
264
|
let reason = 'UNKNOWN_EXCEPTION';
|
|
265
|
-
if (error
|
|
265
|
+
if (isDirectusError(error)) {
|
|
266
266
|
reason = error.code;
|
|
267
267
|
}
|
|
268
268
|
else {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDirectusError } from '@directus/errors';
|
|
2
2
|
import { parseJSON } from '@directus/utils';
|
|
3
3
|
import express, { Router } from 'express';
|
|
4
4
|
import flatten from 'flat';
|
|
@@ -8,8 +8,7 @@ import { getAuthProvider } from '../../auth.js';
|
|
|
8
8
|
import getDatabase from '../../database/index.js';
|
|
9
9
|
import emitter from '../../emitter.js';
|
|
10
10
|
import env from '../../env.js';
|
|
11
|
-
import {
|
|
12
|
-
import { InvalidConfigException, InvalidCredentialsException, InvalidProviderException, InvalidTokenException, ServiceUnavailableException, } from '../../exceptions/index.js';
|
|
11
|
+
import { ErrorCode, InvalidCredentialsError, InvalidProviderError, InvalidProviderConfigError, InvalidTokenError, ServiceUnavailableError, } from '../../errors/index.js';
|
|
13
12
|
import logger from '../../logger.js';
|
|
14
13
|
import { respond } from '../../middleware/respond.js';
|
|
15
14
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
@@ -29,7 +28,8 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
29
28
|
super(options, config);
|
|
30
29
|
const { issuerUrl, clientId, clientSecret, ...additionalConfig } = config;
|
|
31
30
|
if (!issuerUrl || !clientId || !clientSecret || !additionalConfig['provider']) {
|
|
32
|
-
|
|
31
|
+
logger.error('Invalid provider config');
|
|
32
|
+
throw new InvalidProviderConfigError({ provider: additionalConfig['provider'] });
|
|
33
33
|
}
|
|
34
34
|
const redirectUrl = new Url(env['PUBLIC_URL']).addPath('auth', 'login', additionalConfig['provider'], 'callback');
|
|
35
35
|
const clientOptionsOverrides = getConfigFromEnv(`AUTH_${config['provider'].toUpperCase()}_CLIENT_`, [`AUTH_${config['provider'].toUpperCase()}_CLIENT_ID`, `AUTH_${config['provider'].toUpperCase()}_CLIENT_SECRET`], 'underscore');
|
|
@@ -41,7 +41,8 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
41
41
|
.then((issuer) => {
|
|
42
42
|
const supportedTypes = issuer.metadata['response_types_supported'];
|
|
43
43
|
if (!supportedTypes?.includes('code')) {
|
|
44
|
-
|
|
44
|
+
logger.error('OpenID provider does not support required code flow');
|
|
45
|
+
reject(new InvalidProviderConfigError({
|
|
45
46
|
provider: additionalConfig['provider'],
|
|
46
47
|
}));
|
|
47
48
|
}
|
|
@@ -94,7 +95,7 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
94
95
|
async getUserID(payload) {
|
|
95
96
|
if (!payload['code'] || !payload['codeVerifier'] || !payload['state']) {
|
|
96
97
|
logger.warn('[OpenID] No code, codeVerifier or state in payload');
|
|
97
|
-
throw new
|
|
98
|
+
throw new InvalidCredentialsError();
|
|
98
99
|
}
|
|
99
100
|
let tokenSet;
|
|
100
101
|
let userInfo;
|
|
@@ -121,7 +122,7 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
121
122
|
const identifier = userInfo[identifierKey ?? 'sub'] ? String(userInfo[identifierKey ?? 'sub']) : email;
|
|
122
123
|
if (!identifier) {
|
|
123
124
|
logger.warn(`[OpenID] Failed to find user identifier for provider "${provider}"`);
|
|
124
|
-
throw new
|
|
125
|
+
throw new InvalidCredentialsError();
|
|
125
126
|
}
|
|
126
127
|
const userPayload = {
|
|
127
128
|
provider,
|
|
@@ -149,7 +150,7 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
149
150
|
// Is public registration allowed?
|
|
150
151
|
if (!allowPublicRegistration || !isEmailVerified) {
|
|
151
152
|
logger.warn(`[OpenID] User doesn't exist, and public registration not allowed for provider "${provider}"`);
|
|
152
|
-
throw new
|
|
153
|
+
throw new InvalidCredentialsError();
|
|
153
154
|
}
|
|
154
155
|
// Run hook so the end user has the chance to augment the
|
|
155
156
|
// user that is about to be created
|
|
@@ -162,9 +163,9 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
162
163
|
await this.usersService.createOne(updatedUserPayload);
|
|
163
164
|
}
|
|
164
165
|
catch (e) {
|
|
165
|
-
if (e
|
|
166
|
+
if (isDirectusError(e, ErrorCode.RecordNotUnique)) {
|
|
166
167
|
logger.warn(e, '[OpenID] Failed to register user. User not unique');
|
|
167
|
-
throw new
|
|
168
|
+
throw new InvalidProviderError();
|
|
168
169
|
}
|
|
169
170
|
throw e;
|
|
170
171
|
}
|
|
@@ -205,19 +206,19 @@ const handleError = (e) => {
|
|
|
205
206
|
if (e.error === 'invalid_grant') {
|
|
206
207
|
// Invalid token
|
|
207
208
|
logger.trace(e, `[OpenID] Invalid grant`);
|
|
208
|
-
return new
|
|
209
|
+
return new InvalidTokenError();
|
|
209
210
|
}
|
|
210
211
|
// Server response error
|
|
211
212
|
logger.trace(e, `[OpenID] Unknown OP error`);
|
|
212
|
-
return new
|
|
213
|
+
return new ServiceUnavailableError({
|
|
213
214
|
service: 'openid',
|
|
214
|
-
|
|
215
|
+
reason: `Service returned unexpected response: ${e.error_description}`,
|
|
215
216
|
});
|
|
216
217
|
}
|
|
217
218
|
else if (e instanceof errors.RPError) {
|
|
218
219
|
// Internal client error
|
|
219
220
|
logger.trace(e, `[OpenID] Unknown RP error`);
|
|
220
|
-
return new
|
|
221
|
+
return new InvalidCredentialsError();
|
|
221
222
|
}
|
|
222
223
|
logger.trace(e, `[OpenID] Unknown error`);
|
|
223
224
|
return e;
|
|
@@ -250,7 +251,7 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
250
251
|
}
|
|
251
252
|
catch (e) {
|
|
252
253
|
logger.warn(e, `[OpenID] Couldn't verify OpenID cookie`);
|
|
253
|
-
throw new
|
|
254
|
+
throw new InvalidCredentialsError();
|
|
254
255
|
}
|
|
255
256
|
const { verifier, redirect, prompt } = tokenData;
|
|
256
257
|
const accountability = {
|
|
@@ -279,13 +280,13 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
279
280
|
}
|
|
280
281
|
catch (error) {
|
|
281
282
|
// Prompt user for a new refresh_token if invalidated
|
|
282
|
-
if (error
|
|
283
|
+
if (isDirectusError(error, ErrorCode.InvalidToken) && !prompt) {
|
|
283
284
|
return res.redirect(`./?${redirect ? `redirect=${redirect}&` : ''}prompt=true`);
|
|
284
285
|
}
|
|
285
286
|
logger.warn(error);
|
|
286
287
|
if (redirect) {
|
|
287
288
|
let reason = 'UNKNOWN_EXCEPTION';
|
|
288
|
-
if (error
|
|
289
|
+
if (isDirectusError(error)) {
|
|
289
290
|
reason = error.code;
|
|
290
291
|
}
|
|
291
292
|
else {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as validator from '@authenio/samlify-node-xmllint';
|
|
2
|
-
import {
|
|
2
|
+
import { isDirectusError } from '@directus/errors';
|
|
3
3
|
import express, { Router } from 'express';
|
|
4
4
|
import * as samlify from 'samlify';
|
|
5
5
|
import { getAuthProvider } from '../../auth.js';
|
|
@@ -7,8 +7,7 @@ import { COOKIE_OPTIONS } from '../../constants.js';
|
|
|
7
7
|
import getDatabase from '../../database/index.js';
|
|
8
8
|
import emitter from '../../emitter.js';
|
|
9
9
|
import env from '../../env.js';
|
|
10
|
-
import {
|
|
11
|
-
import { InvalidCredentialsException, InvalidProviderException } from '../../exceptions/index.js';
|
|
10
|
+
import { ErrorCode, InvalidCredentialsError, InvalidProviderError } from '../../errors/index.js';
|
|
12
11
|
import logger from '../../logger.js';
|
|
13
12
|
import { respond } from '../../middleware/respond.js';
|
|
14
13
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
@@ -47,7 +46,7 @@ export class SAMLAuthDriver extends LocalAuthDriver {
|
|
|
47
46
|
return userID;
|
|
48
47
|
if (!allowPublicRegistration) {
|
|
49
48
|
logger.trace(`[SAML] User doesn't exist, and public registration not allowed for provider "${provider}"`);
|
|
50
|
-
throw new
|
|
49
|
+
throw new InvalidCredentialsError();
|
|
51
50
|
}
|
|
52
51
|
const firstName = payload[givenNameKey ?? 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'];
|
|
53
52
|
const lastName = payload[familyNameKey ?? 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname'];
|
|
@@ -66,9 +65,9 @@ export class SAMLAuthDriver extends LocalAuthDriver {
|
|
|
66
65
|
return await this.usersService.createOne(updatedUserPayload);
|
|
67
66
|
}
|
|
68
67
|
catch (error) {
|
|
69
|
-
if (error
|
|
68
|
+
if (isDirectusError(error, ErrorCode.RecordNotUnique)) {
|
|
70
69
|
logger.warn(error, '[SAML] Failed to register user. User not unique');
|
|
71
|
-
throw new
|
|
70
|
+
throw new InvalidProviderError();
|
|
72
71
|
}
|
|
73
72
|
throw error;
|
|
74
73
|
}
|
|
@@ -129,7 +128,7 @@ export function createSAMLAuthRouter(providerName) {
|
|
|
129
128
|
catch (error) {
|
|
130
129
|
if (relayState) {
|
|
131
130
|
let reason = 'UNKNOWN_EXCEPTION';
|
|
132
|
-
if (error
|
|
131
|
+
if (isDirectusError(error)) {
|
|
133
132
|
reason = error.code;
|
|
134
133
|
}
|
|
135
134
|
else {
|
package/dist/auth.js
CHANGED
|
@@ -3,7 +3,7 @@ import { LDAPAuthDriver, LocalAuthDriver, OAuth2AuthDriver, OpenIDAuthDriver, SA
|
|
|
3
3
|
import { DEFAULT_AUTH_PROVIDER } from './constants.js';
|
|
4
4
|
import getDatabase from './database/index.js';
|
|
5
5
|
import env from './env.js';
|
|
6
|
-
import {
|
|
6
|
+
import { InvalidProviderConfigError } from './errors/index.js';
|
|
7
7
|
import logger from './logger.js';
|
|
8
8
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
9
9
|
import { getSchema } from './utils/get-schema.js';
|
|
@@ -11,7 +11,8 @@ const providerNames = toArray(env['AUTH_PROVIDERS']);
|
|
|
11
11
|
const providers = new Map();
|
|
12
12
|
export function getAuthProvider(provider) {
|
|
13
13
|
if (!providers.has(provider)) {
|
|
14
|
-
|
|
14
|
+
logger.error('Auth provider not configured');
|
|
15
|
+
throw new InvalidProviderConfigError({ provider });
|
|
15
16
|
}
|
|
16
17
|
return providers.get(provider);
|
|
17
18
|
}
|
package/dist/cache.js
CHANGED
|
@@ -57,13 +57,14 @@ export async function flushCaches(forced) {
|
|
|
57
57
|
await cache?.clear();
|
|
58
58
|
}
|
|
59
59
|
export async function clearSystemCache(opts) {
|
|
60
|
-
const { systemCache, localSchemaCache, lockCache } = getCache();
|
|
60
|
+
const { systemCache, localSchemaCache, lockCache, sharedSchemaCache } = getCache();
|
|
61
61
|
// Flush system cache when forced or when system cache lock not set
|
|
62
62
|
if (opts?.forced || !(await lockCache.get('system-cache-lock'))) {
|
|
63
63
|
await lockCache.set('system-cache-lock', true, 10000);
|
|
64
64
|
await systemCache.clear();
|
|
65
65
|
await lockCache.delete('system-cache-lock');
|
|
66
66
|
}
|
|
67
|
+
await sharedSchemaCache.clear();
|
|
67
68
|
await localSchemaCache.clear();
|
|
68
69
|
messenger.publish('schemaChanged', { autoPurgeCache: opts?.autoPurgeCache });
|
|
69
70
|
}
|
|
@@ -109,8 +110,6 @@ function getKeyvInstance(store, ttl, namespaceSuffix) {
|
|
|
109
110
|
switch (store) {
|
|
110
111
|
case 'redis':
|
|
111
112
|
return new Keyv(getConfig('redis', ttl, namespaceSuffix));
|
|
112
|
-
case 'memcache':
|
|
113
|
-
return new Keyv(getConfig('memcache', ttl, namespaceSuffix));
|
|
114
113
|
case 'memory':
|
|
115
114
|
default:
|
|
116
115
|
return new Keyv(getConfig('memory', ttl, namespaceSuffix));
|
|
@@ -123,16 +122,7 @@ function getConfig(store = 'memory', ttl, namespaceSuffix = '') {
|
|
|
123
122
|
};
|
|
124
123
|
if (store === 'redis') {
|
|
125
124
|
const KeyvRedis = require('@keyv/redis');
|
|
126
|
-
config.store = new KeyvRedis(env['
|
|
127
|
-
}
|
|
128
|
-
if (store === 'memcache') {
|
|
129
|
-
const KeyvMemcache = require('keyv-memcache');
|
|
130
|
-
// keyv-memcache uses memjs which only accepts a comma separated string instead of an array,
|
|
131
|
-
// so we need to join array into a string when applicable. See #7986
|
|
132
|
-
const cacheMemcache = Array.isArray(env['CACHE_MEMCACHE'])
|
|
133
|
-
? env['CACHE_MEMCACHE'].join(',')
|
|
134
|
-
: env['CACHE_MEMCACHE'];
|
|
135
|
-
config.store = new KeyvMemcache(cacheMemcache);
|
|
125
|
+
config.store = new KeyvRedis(env['REDIS'] || getConfigFromEnv('REDIS'));
|
|
136
126
|
}
|
|
137
127
|
return config;
|
|
138
128
|
}
|
|
@@ -50,6 +50,9 @@ PUBLIC_URL="/"
|
|
|
50
50
|
# The maximum number of items for batch mutations when creating, updating and deleting. ["Infinity"]
|
|
51
51
|
# MAX_BATCH_MUTATION="Infinity"
|
|
52
52
|
|
|
53
|
+
# Shared Redis server for things like caching, rate limiting, container synchronization, etc
|
|
54
|
+
# REDIS="redis://@127.0.0.1:6379"
|
|
55
|
+
|
|
53
56
|
####################################################################################################
|
|
54
57
|
### Database
|
|
55
58
|
|
|
@@ -127,10 +130,8 @@ PUBLIC_URL="/"
|
|
|
127
130
|
RATE_LIMITER_ENABLED=false
|
|
128
131
|
|
|
129
132
|
# Where to store the rate limiter counts [memory]
|
|
130
|
-
# memory, redis
|
|
133
|
+
# memory, redis
|
|
131
134
|
RATE_LIMITER_STORE=memory
|
|
132
|
-
# RATE_LIMITER_REDIS="redis://@127.0.0.1:5105"
|
|
133
|
-
# RATE_LIMITER_MEMCACHE="localhost:5109"
|
|
134
135
|
|
|
135
136
|
# The amount of allowed hits per duration [50]
|
|
136
137
|
RATE_LIMITER_POINTS=25
|
|
@@ -156,15 +157,12 @@ CACHE_ENABLED=false
|
|
|
156
157
|
# List of collections that prevent cache purging when `CACHE_AUTO_PURGE` is enabled. ["directus_activity,directus_presets"]
|
|
157
158
|
# CACHE_AUTO_PURGE_IGNORE_LIST="directus_activity,directus_presets"
|
|
158
159
|
|
|
159
|
-
# memory | redis
|
|
160
|
+
# memory | redis
|
|
160
161
|
CACHE_STORE=memory
|
|
161
162
|
|
|
162
163
|
# How long assets will be cached for in the browser. Sets the max-age value of the Cache-Control header ["30d"]
|
|
163
164
|
ASSETS_CACHE_TTL="30d"
|
|
164
165
|
|
|
165
|
-
# CACHE_REDIS="redis://@127.0.0.1:5105"
|
|
166
|
-
# CACHE_MEMCACHE="localhost:5109"
|
|
167
|
-
|
|
168
166
|
####################################################################################################
|
|
169
167
|
### File Storage
|
|
170
168
|
|