@directus/api 30.0.0 → 32.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 +7 -0
- package/dist/auth/auth.d.ts +2 -1
- package/dist/auth/auth.js +7 -2
- package/dist/auth/drivers/ldap.d.ts +0 -2
- package/dist/auth/drivers/ldap.js +9 -7
- package/dist/auth/drivers/oauth2.d.ts +0 -2
- package/dist/auth/drivers/oauth2.js +28 -11
- package/dist/auth/drivers/openid.d.ts +0 -2
- package/dist/auth/drivers/openid.js +28 -11
- package/dist/auth/drivers/saml.d.ts +0 -2
- package/dist/auth/drivers/saml.js +5 -5
- package/dist/auth.js +1 -2
- package/dist/cli/commands/bootstrap/index.js +12 -33
- package/dist/cli/commands/init/index.js +1 -1
- package/dist/cli/commands/schema/apply.d.ts +4 -0
- package/dist/cli/commands/schema/apply.js +26 -3
- package/dist/controllers/collections.js +7 -2
- package/dist/controllers/fields.js +31 -8
- package/dist/controllers/mcp.d.ts +2 -0
- package/dist/controllers/mcp.js +33 -0
- package/dist/controllers/server.js +26 -1
- package/dist/controllers/settings.js +9 -2
- package/dist/controllers/users.js +17 -7
- package/dist/controllers/versions.js +3 -2
- package/dist/database/errors/dialects/mssql.d.ts +1 -1
- package/dist/database/errors/dialects/mssql.js +18 -10
- package/dist/database/helpers/fn/types.js +3 -3
- package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/cockroachdb.js +13 -0
- package/dist/database/helpers/schema/dialects/mssql.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/mssql.js +23 -0
- package/dist/database/helpers/schema/dialects/mysql.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/mysql.js +25 -0
- package/dist/database/helpers/schema/dialects/oracle.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/oracle.js +13 -0
- package/dist/database/helpers/schema/dialects/postgres.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/postgres.js +13 -0
- package/dist/database/helpers/schema/types.d.ts +5 -0
- package/dist/database/helpers/schema/types.js +6 -0
- package/dist/database/migrations/20250813A-add-mcp.d.ts +3 -0
- package/dist/database/migrations/20250813A-add-mcp.js +18 -0
- package/dist/database/migrations/20251012A-add-field-searchable.d.ts +3 -0
- package/dist/database/migrations/20251012A-add-field-searchable.js +10 -0
- package/dist/database/migrations/20251014A-add-project-owner.d.ts +3 -0
- package/dist/database/migrations/20251014A-add-project-owner.js +37 -0
- package/dist/database/migrations/20251028A-add-retention-indexes.d.ts +3 -0
- package/dist/database/migrations/20251028A-add-retention-indexes.js +42 -0
- package/dist/database/run-ast/README.md +46 -0
- package/dist/database/run-ast/lib/apply-query/add-join.js +2 -2
- package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.d.ts +2 -2
- package/dist/database/run-ast/lib/apply-query/index.d.ts +0 -1
- package/dist/database/run-ast/lib/apply-query/index.js +4 -6
- package/dist/database/run-ast/lib/apply-query/search.js +2 -0
- package/dist/database/run-ast/lib/get-db-query.js +7 -6
- package/dist/database/run-ast/utils/generate-alias.d.ts +6 -0
- package/dist/database/run-ast/utils/generate-alias.js +57 -0
- package/dist/flows.js +1 -0
- package/dist/mcp/define.d.ts +2 -0
- package/dist/mcp/define.js +3 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/schema.d.ts +485 -0
- package/dist/mcp/schema.js +219 -0
- package/dist/mcp/server.d.ts +103 -0
- package/dist/mcp/server.js +310 -0
- package/dist/mcp/tools/assets.d.ts +3 -0
- package/dist/mcp/tools/assets.js +54 -0
- package/dist/mcp/tools/collections.d.ts +84 -0
- package/dist/mcp/tools/collections.js +90 -0
- package/dist/mcp/tools/fields.d.ts +101 -0
- package/dist/mcp/tools/fields.js +157 -0
- package/dist/mcp/tools/files.d.ts +235 -0
- package/dist/mcp/tools/files.js +103 -0
- package/dist/mcp/tools/flows.d.ts +323 -0
- package/dist/mcp/tools/flows.js +85 -0
- package/dist/mcp/tools/folders.d.ts +95 -0
- package/dist/mcp/tools/folders.js +96 -0
- package/dist/mcp/tools/index.d.ts +15 -0
- package/dist/mcp/tools/index.js +29 -0
- package/dist/mcp/tools/items.d.ts +87 -0
- package/dist/mcp/tools/items.js +141 -0
- package/dist/mcp/tools/operations.d.ts +171 -0
- package/dist/mcp/tools/operations.js +77 -0
- package/dist/mcp/tools/prompts/assets.md +8 -0
- package/dist/mcp/tools/prompts/collections.md +336 -0
- package/dist/mcp/tools/prompts/fields.md +521 -0
- package/dist/mcp/tools/prompts/files.md +180 -0
- package/dist/mcp/tools/prompts/flows.md +495 -0
- package/dist/mcp/tools/prompts/folders.md +34 -0
- package/dist/mcp/tools/prompts/index.d.ts +16 -0
- package/dist/mcp/tools/prompts/index.js +19 -0
- package/dist/mcp/tools/prompts/items.md +317 -0
- package/dist/mcp/tools/prompts/operations.md +721 -0
- package/dist/mcp/tools/prompts/relations.md +386 -0
- package/dist/mcp/tools/prompts/schema.md +130 -0
- package/dist/mcp/tools/prompts/system-prompt-description.md +1 -0
- package/dist/mcp/tools/prompts/system-prompt.md +44 -0
- package/dist/mcp/tools/prompts/trigger-flow.md +214 -0
- package/dist/mcp/tools/relations.d.ts +73 -0
- package/dist/mcp/tools/relations.js +93 -0
- package/dist/mcp/tools/schema.d.ts +54 -0
- package/dist/mcp/tools/schema.js +317 -0
- package/dist/mcp/tools/system.d.ts +3 -0
- package/dist/mcp/tools/system.js +22 -0
- package/dist/mcp/tools/trigger-flow.d.ts +8 -0
- package/dist/mcp/tools/trigger-flow.js +48 -0
- package/dist/mcp/transport.d.ts +13 -0
- package/dist/mcp/transport.js +18 -0
- package/dist/mcp/types.d.ts +56 -0
- package/dist/mcp/types.js +1 -0
- package/dist/metrics/lib/create-metrics.js +16 -25
- package/dist/middleware/collection-exists.js +2 -2
- package/dist/operations/mail/index.js +3 -1
- package/dist/operations/mail/rate-limiter.d.ts +1 -0
- package/dist/operations/mail/rate-limiter.js +29 -0
- package/dist/permissions/modules/process-payload/process-payload.js +3 -10
- package/dist/permissions/modules/validate-access/validate-access.js +2 -3
- package/dist/schedules/metrics.js +6 -2
- package/dist/schedules/project.d.ts +4 -0
- package/dist/schedules/project.js +27 -0
- package/dist/services/authentication.js +36 -0
- package/dist/services/collections.d.ts +3 -3
- package/dist/services/collections.js +16 -1
- package/dist/services/fields.d.ts +21 -5
- package/dist/services/fields.js +109 -32
- package/dist/services/graphql/resolvers/query.js +1 -1
- package/dist/services/graphql/resolvers/system-admin.js +49 -5
- package/dist/services/graphql/schema/parse-query.js +8 -8
- package/dist/services/graphql/utils/aggregate-query.d.ts +1 -1
- package/dist/services/graphql/utils/aggregate-query.js +5 -1
- package/dist/services/graphql/utils/filter-replace-m2a.js +2 -1
- package/dist/services/import-export.d.ts +9 -1
- package/dist/services/import-export.js +287 -101
- package/dist/services/items.d.ts +1 -1
- package/dist/services/items.js +50 -24
- package/dist/services/mail/index.js +2 -0
- package/dist/services/mail/rate-limiter.d.ts +1 -0
- package/dist/services/mail/rate-limiter.js +29 -0
- package/dist/services/meta.js +28 -24
- package/dist/services/payload.d.ts +7 -3
- package/dist/services/payload.js +26 -12
- package/dist/services/schema.js +4 -1
- package/dist/services/server.d.ts +1 -0
- package/dist/services/server.js +15 -18
- package/dist/services/settings.d.ts +2 -1
- package/dist/services/settings.js +15 -0
- package/dist/services/tfa.d.ts +1 -1
- package/dist/services/tfa.js +20 -5
- package/dist/services/tus/server.js +14 -9
- package/dist/services/versions.d.ts +6 -4
- package/dist/services/versions.js +84 -25
- package/dist/telemetry/lib/get-report.js +4 -4
- package/dist/telemetry/lib/send-report.d.ts +6 -1
- package/dist/telemetry/lib/send-report.js +3 -1
- package/dist/telemetry/types/report.d.ts +17 -1
- package/dist/telemetry/utils/get-settings.d.ts +9 -0
- package/dist/telemetry/utils/get-settings.js +14 -0
- package/dist/test-utils/README.md +760 -0
- package/dist/test-utils/cache.d.ts +51 -0
- package/dist/test-utils/cache.js +59 -0
- package/dist/test-utils/database.d.ts +48 -0
- package/dist/test-utils/database.js +52 -0
- package/dist/test-utils/emitter.d.ts +35 -0
- package/dist/test-utils/emitter.js +38 -0
- package/dist/test-utils/fields-service.d.ts +28 -0
- package/dist/test-utils/fields-service.js +36 -0
- package/dist/test-utils/items-service.d.ts +23 -0
- package/dist/test-utils/items-service.js +37 -0
- package/dist/test-utils/knex.d.ts +164 -0
- package/dist/test-utils/knex.js +268 -0
- package/dist/test-utils/schema.d.ts +26 -0
- package/dist/test-utils/schema.js +35 -0
- package/dist/types/auth.d.ts +2 -3
- package/dist/utils/apply-diff.js +15 -0
- package/dist/utils/create-admin.d.ts +11 -0
- package/dist/utils/create-admin.js +50 -0
- package/dist/utils/get-schema.js +5 -3
- package/dist/utils/get-snapshot-diff.js +49 -5
- package/dist/utils/get-snapshot.js +13 -7
- package/dist/utils/sanitize-schema.d.ts +11 -4
- package/dist/utils/sanitize-schema.js +9 -6
- package/dist/utils/schedule.js +15 -19
- package/dist/utils/validate-diff.js +31 -0
- package/dist/utils/validate-snapshot.js +7 -0
- package/dist/utils/versioning/deep-map-with-schema.d.ts +23 -0
- package/dist/utils/versioning/deep-map-with-schema.js +81 -0
- package/dist/utils/versioning/handle-version.d.ts +2 -2
- package/dist/utils/versioning/handle-version.js +47 -43
- package/dist/utils/versioning/split-recursive.d.ts +4 -0
- package/dist/utils/versioning/split-recursive.js +27 -0
- package/dist/websocket/controllers/hooks.js +12 -20
- package/dist/websocket/messages.d.ts +3 -3
- package/package.json +65 -66
- package/dist/cli/utils/defaults.d.ts +0 -4
- package/dist/cli/utils/defaults.js +0 -17
- package/dist/telemetry/utils/get-project-id.d.ts +0 -2
- package/dist/telemetry/utils/get-project-id.js +0 -4
package/dist/app.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEnv } from '@directus/env';
|
|
2
2
|
import { InvalidPayloadError, ServiceUnavailableError } from '@directus/errors';
|
|
3
3
|
import { handlePressure } from '@directus/pressure';
|
|
4
|
+
import { toBoolean } from '@directus/utils';
|
|
4
5
|
import cookieParser from 'cookie-parser';
|
|
5
6
|
import express from 'express';
|
|
6
7
|
import { merge } from 'lodash-es';
|
|
@@ -23,6 +24,7 @@ import flowsRouter from './controllers/flows.js';
|
|
|
23
24
|
import foldersRouter from './controllers/folders.js';
|
|
24
25
|
import graphqlRouter from './controllers/graphql.js';
|
|
25
26
|
import itemsRouter from './controllers/items.js';
|
|
27
|
+
import mcpRouter from './controllers/mcp.js';
|
|
26
28
|
import metricsRouter from './controllers/metrics.js';
|
|
27
29
|
import notFoundHandler from './controllers/not-found.js';
|
|
28
30
|
import notificationsRouter from './controllers/notifications.js';
|
|
@@ -62,6 +64,7 @@ import metricsSchedule from './schedules/metrics.js';
|
|
|
62
64
|
import retentionSchedule from './schedules/retention.js';
|
|
63
65
|
import telemetrySchedule from './schedules/telemetry.js';
|
|
64
66
|
import tusSchedule from './schedules/tus.js';
|
|
67
|
+
import projectSchedule from './schedules/project.js';
|
|
65
68
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
66
69
|
import { Url } from './utils/url.js';
|
|
67
70
|
import { validateStorage } from './utils/validate-storage.js';
|
|
@@ -225,6 +228,9 @@ export default async function createApp() {
|
|
|
225
228
|
app.use('/flows', flowsRouter);
|
|
226
229
|
app.use('/folders', foldersRouter);
|
|
227
230
|
app.use('/items', itemsRouter);
|
|
231
|
+
if (toBoolean(env['MCP_ENABLED']) === true) {
|
|
232
|
+
app.use('/mcp', mcpRouter);
|
|
233
|
+
}
|
|
228
234
|
if (env['METRICS_ENABLED'] === true) {
|
|
229
235
|
app.use('/metrics', metricsRouter);
|
|
230
236
|
}
|
|
@@ -257,6 +263,7 @@ export default async function createApp() {
|
|
|
257
263
|
await telemetrySchedule();
|
|
258
264
|
await tusSchedule();
|
|
259
265
|
await metricsSchedule();
|
|
266
|
+
await projectSchedule();
|
|
260
267
|
await emitter.emitInit('app.after', { app });
|
|
261
268
|
return app;
|
|
262
269
|
}
|
package/dist/auth/auth.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { SchemaOverview } from '@directus/types';
|
|
2
2
|
import type { Knex } from 'knex';
|
|
3
|
+
import { UsersService } from '../services/users.js';
|
|
3
4
|
import type { AuthDriverOptions, User } from '../types/index.js';
|
|
4
5
|
export declare abstract class AuthDriver {
|
|
5
6
|
knex: Knex;
|
|
6
|
-
schema: SchemaOverview;
|
|
7
7
|
constructor(options: AuthDriverOptions, _config: Record<string, any>);
|
|
8
|
+
protected getUsersService(schema: SchemaOverview): UsersService;
|
|
8
9
|
/**
|
|
9
10
|
* Get user id for a given provider payload
|
|
10
11
|
*
|
package/dist/auth/auth.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import { UsersService } from '../services/users.js';
|
|
1
2
|
export class AuthDriver {
|
|
2
3
|
knex;
|
|
3
|
-
schema;
|
|
4
4
|
constructor(options, _config) {
|
|
5
5
|
this.knex = options.knex;
|
|
6
|
-
|
|
6
|
+
}
|
|
7
|
+
getUsersService(schema) {
|
|
8
|
+
return new UsersService({
|
|
9
|
+
knex: this.knex,
|
|
10
|
+
schema,
|
|
11
|
+
});
|
|
7
12
|
}
|
|
8
13
|
/**
|
|
9
14
|
* Check with the (external) provider if the user is allowed entry to Directus
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import type { Client } from 'ldapjs';
|
|
3
|
-
import { UsersService } from '../../services/users.js';
|
|
4
3
|
import type { AuthDriverOptions, User } from '../../types/index.js';
|
|
5
4
|
import { AuthDriver } from '../auth.js';
|
|
6
5
|
export declare class LDAPAuthDriver extends AuthDriver {
|
|
7
6
|
bindClient: Client;
|
|
8
|
-
usersService: UsersService;
|
|
9
7
|
config: Record<string, any>;
|
|
10
8
|
constructor(options: AuthDriverOptions, config: Record<string, any>);
|
|
11
9
|
private validateBindClient;
|
|
@@ -10,17 +10,16 @@ import { useLogger } from '../../logger/index.js';
|
|
|
10
10
|
import { respond } from '../../middleware/respond.js';
|
|
11
11
|
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
12
12
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
13
|
-
import { UsersService } from '../../services/users.js';
|
|
14
13
|
import asyncHandler from '../../utils/async-handler.js';
|
|
15
14
|
import { getIPFromReq } from '../../utils/get-ip-from-req.js';
|
|
16
15
|
import { AuthDriver } from '../auth.js';
|
|
16
|
+
import { getSchema } from '../../utils/get-schema.js';
|
|
17
17
|
// 0x2: ACCOUNTDISABLE
|
|
18
18
|
// 0x10: LOCKOUT
|
|
19
19
|
// 0x800000: PASSWORD_EXPIRED
|
|
20
20
|
const INVALID_ACCOUNT_FLAGS = 0x800012;
|
|
21
21
|
export class LDAPAuthDriver extends AuthDriver {
|
|
22
22
|
bindClient;
|
|
23
|
-
usersService;
|
|
24
23
|
config;
|
|
25
24
|
constructor(options, config) {
|
|
26
25
|
super(options, config);
|
|
@@ -39,7 +38,6 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
39
38
|
this.bindClient.on('error', (err) => {
|
|
40
39
|
logger.warn(err);
|
|
41
40
|
});
|
|
42
|
-
this.usersService = new UsersService({ knex: this.knex, schema: this.schema });
|
|
43
41
|
this.config = config;
|
|
44
42
|
}
|
|
45
43
|
async validateBindClient() {
|
|
@@ -216,9 +214,11 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
216
214
|
email: userInfo.email,
|
|
217
215
|
};
|
|
218
216
|
}
|
|
219
|
-
const
|
|
217
|
+
const schema = await getSchema();
|
|
218
|
+
const updatedUserPayload = await emitter.emitFilter(`auth.update`, emitPayload, { identifier: userInfo.dn, provider: this.config['provider'], providerPayload: { userInfo, userRole } }, { database: getDatabase(), schema, accountability: null });
|
|
220
219
|
// Update user to update properties that might have changed
|
|
221
|
-
|
|
220
|
+
const usersService = this.getUsersService(schema);
|
|
221
|
+
await usersService.updateOne(userId, updatedUserPayload);
|
|
222
222
|
return userId;
|
|
223
223
|
}
|
|
224
224
|
if (!userInfo) {
|
|
@@ -232,11 +232,13 @@ export class LDAPAuthDriver extends AuthDriver {
|
|
|
232
232
|
external_identifier: userInfo.dn,
|
|
233
233
|
role: userRole?.id ?? defaultRoleId,
|
|
234
234
|
};
|
|
235
|
+
const schema = await getSchema();
|
|
235
236
|
// Run hook so the end user has the chance to augment the
|
|
236
237
|
// user that is about to be created
|
|
237
|
-
const updatedUserPayload = await emitter.emitFilter(`auth.create`, userPayload, { identifier: userInfo.dn, provider: this.config['provider'], providerPayload: { userInfo, userRole } }, { database: getDatabase(), schema
|
|
238
|
+
const updatedUserPayload = await emitter.emitFilter(`auth.create`, userPayload, { identifier: userInfo.dn, provider: this.config['provider'], providerPayload: { userInfo, userRole } }, { database: getDatabase(), schema, accountability: null });
|
|
238
239
|
try {
|
|
239
|
-
|
|
240
|
+
const usersService = this.getUsersService(schema);
|
|
241
|
+
await usersService.createOne(updatedUserPayload);
|
|
240
242
|
}
|
|
241
243
|
catch (e) {
|
|
242
244
|
if (isDirectusError(e, ErrorCode.RecordNotUnique)) {
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import type { Client } from 'openid-client';
|
|
3
|
-
import { UsersService } from '../../services/users.js';
|
|
4
3
|
import type { AuthDriverOptions, User } from '../../types/index.js';
|
|
5
4
|
import type { RoleMap } from '../../types/rolemap.js';
|
|
6
5
|
import { LocalAuthDriver } from './local.js';
|
|
7
6
|
export declare class OAuth2AuthDriver extends LocalAuthDriver {
|
|
8
7
|
client: Client;
|
|
9
8
|
redirectUrl: string;
|
|
10
|
-
usersService: UsersService;
|
|
11
9
|
config: Record<string, any>;
|
|
12
10
|
roleMap: RoleMap;
|
|
13
11
|
constructor(options: AuthDriverOptions, config: Record<string, any>);
|
|
@@ -13,7 +13,6 @@ import { useLogger } from '../../logger/index.js';
|
|
|
13
13
|
import { respond } from '../../middleware/respond.js';
|
|
14
14
|
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
15
15
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
16
|
-
import { UsersService } from '../../services/users.js';
|
|
17
16
|
import asyncHandler from '../../utils/async-handler.js';
|
|
18
17
|
import { getConfigFromEnv } from '../../utils/get-config-from-env.js';
|
|
19
18
|
import { getIPFromReq } from '../../utils/get-ip-from-req.js';
|
|
@@ -22,10 +21,10 @@ import { isLoginRedirectAllowed } from '../../utils/is-login-redirect-allowed.js
|
|
|
22
21
|
import { verifyJWT } from '../../utils/jwt.js';
|
|
23
22
|
import { Url } from '../../utils/url.js';
|
|
24
23
|
import { LocalAuthDriver } from './local.js';
|
|
24
|
+
import { getSchema } from '../../utils/get-schema.js';
|
|
25
25
|
export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
26
26
|
client;
|
|
27
27
|
redirectUrl;
|
|
28
|
-
usersService;
|
|
29
28
|
config;
|
|
30
29
|
roleMap;
|
|
31
30
|
constructor(options, config) {
|
|
@@ -39,7 +38,6 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
39
38
|
}
|
|
40
39
|
const redirectUrl = new Url(env['PUBLIC_URL']).addPath('auth', 'login', additionalConfig['provider'], 'callback');
|
|
41
40
|
this.redirectUrl = redirectUrl.toString();
|
|
42
|
-
this.usersService = new UsersService({ knex: this.knex, schema: this.schema });
|
|
43
41
|
this.config = additionalConfig;
|
|
44
42
|
this.roleMap = {};
|
|
45
43
|
const roleMapping = this.config['roleMapping'];
|
|
@@ -177,14 +175,16 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
177
175
|
email: userPayload.email,
|
|
178
176
|
};
|
|
179
177
|
}
|
|
178
|
+
const schema = await getSchema();
|
|
180
179
|
const updatedUserPayload = await emitter.emitFilter(`auth.update`, emitPayload, {
|
|
181
180
|
identifier,
|
|
182
181
|
provider: this.config['provider'],
|
|
183
182
|
providerPayload: { accessToken: tokenSet.access_token, idToken: tokenSet.id_token, userInfo },
|
|
184
|
-
}, { database: getDatabase(), schema
|
|
183
|
+
}, { database: getDatabase(), schema, accountability: null });
|
|
185
184
|
// Update user to update refresh_token and other properties that might have changed
|
|
186
185
|
if (Object.values(updatedUserPayload).some((value) => value !== undefined)) {
|
|
187
|
-
|
|
186
|
+
const usersService = this.getUsersService(schema);
|
|
187
|
+
await usersService.updateOne(userId, updatedUserPayload);
|
|
188
188
|
}
|
|
189
189
|
return userId;
|
|
190
190
|
}
|
|
@@ -193,15 +193,17 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
193
193
|
logger.warn(`[OAuth2] User doesn't exist, and public registration not allowed for provider "${provider}"`);
|
|
194
194
|
throw new InvalidCredentialsError();
|
|
195
195
|
}
|
|
196
|
+
const schema = await getSchema();
|
|
196
197
|
// Run hook so the end user has the chance to augment the
|
|
197
198
|
// user that is about to be created
|
|
198
199
|
const updatedUserPayload = await emitter.emitFilter(`auth.create`, userPayload, {
|
|
199
200
|
identifier,
|
|
200
201
|
provider: this.config['provider'],
|
|
201
202
|
providerPayload: { accessToken: tokenSet.access_token, idToken: tokenSet.id_token, userInfo },
|
|
202
|
-
}, { database: getDatabase(), schema
|
|
203
|
+
}, { database: getDatabase(), schema, accountability: null });
|
|
203
204
|
try {
|
|
204
|
-
|
|
205
|
+
const usersService = this.getUsersService(schema);
|
|
206
|
+
await usersService.createOne(updatedUserPayload);
|
|
205
207
|
}
|
|
206
208
|
catch (e) {
|
|
207
209
|
if (isDirectusError(e, ErrorCode.RecordNotUnique)) {
|
|
@@ -231,7 +233,8 @@ export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
231
233
|
const tokenSet = await this.client.refresh(authData['refreshToken']);
|
|
232
234
|
// Update user refreshToken if provided
|
|
233
235
|
if (tokenSet.refresh_token) {
|
|
234
|
-
|
|
236
|
+
const usersService = this.getUsersService(await getSchema());
|
|
237
|
+
await usersService.updateOne(user.id, {
|
|
235
238
|
auth_data: JSON.stringify({ refreshToken: tokenSet.refresh_token }),
|
|
236
239
|
});
|
|
237
240
|
}
|
|
@@ -273,10 +276,11 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
273
276
|
const codeVerifier = provider.generateCodeVerifier();
|
|
274
277
|
const prompt = !!req.query['prompt'];
|
|
275
278
|
const redirect = req.query['redirect'];
|
|
279
|
+
const otp = req.query['otp'];
|
|
276
280
|
if (isLoginRedirectAllowed(redirect, providerName) === false) {
|
|
277
281
|
throw new InvalidPayloadError({ reason: `URL "${redirect}" can't be used to redirect after login` });
|
|
278
282
|
}
|
|
279
|
-
const token = jwt.sign({ verifier: codeVerifier, redirect, prompt }, getSecret(), {
|
|
283
|
+
const token = jwt.sign({ verifier: codeVerifier, redirect, prompt, otp }, getSecret(), {
|
|
280
284
|
expiresIn: '5m',
|
|
281
285
|
issuer: 'directus',
|
|
282
286
|
});
|
|
@@ -299,7 +303,8 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
299
303
|
logger.warn(e, `[OAuth2] Couldn't verify OAuth2 cookie`);
|
|
300
304
|
throw new InvalidCredentialsError();
|
|
301
305
|
}
|
|
302
|
-
const { verifier,
|
|
306
|
+
const { verifier, prompt, otp } = tokenData;
|
|
307
|
+
let { redirect } = tokenData;
|
|
303
308
|
const accountability = createDefaultAccountability({
|
|
304
309
|
ip: getIPFromReq(req),
|
|
305
310
|
});
|
|
@@ -321,7 +326,7 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
321
326
|
code: req.query['code'],
|
|
322
327
|
codeVerifier: verifier,
|
|
323
328
|
state: req.query['state'],
|
|
324
|
-
}, { session: authMode === 'session' });
|
|
329
|
+
}, { session: authMode === 'session', ...(otp ? { otp: String(otp) } : {}) });
|
|
325
330
|
}
|
|
326
331
|
catch (error) {
|
|
327
332
|
// Prompt user for a new refresh_token if invalidated
|
|
@@ -342,6 +347,18 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
342
347
|
throw error;
|
|
343
348
|
}
|
|
344
349
|
const { accessToken, refreshToken, expires } = authResponse;
|
|
350
|
+
try {
|
|
351
|
+
const claims = verifyJWT(accessToken, getSecret());
|
|
352
|
+
if (claims?.enforce_tfa === true) {
|
|
353
|
+
const url = new Url(env['PUBLIC_URL']).addPath('admin', 'tfa-setup');
|
|
354
|
+
if (redirect)
|
|
355
|
+
url.setQuery('redirect', redirect);
|
|
356
|
+
redirect = url.toString();
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
catch (e) {
|
|
360
|
+
logger.warn(e, `[OAuth2] Unexpected error during OAuth2 login`);
|
|
361
|
+
}
|
|
345
362
|
if (redirect) {
|
|
346
363
|
if (authMode === 'session') {
|
|
347
364
|
res.cookie(env['SESSION_COOKIE_NAME'], accessToken, SESSION_COOKIE_OPTIONS);
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import type { Client } from 'openid-client';
|
|
3
|
-
import { UsersService } from '../../services/users.js';
|
|
4
3
|
import type { AuthDriverOptions, User } from '../../types/index.js';
|
|
5
4
|
import type { RoleMap } from '../../types/rolemap.js';
|
|
6
5
|
import { LocalAuthDriver } from './local.js';
|
|
7
6
|
export declare class OpenIDAuthDriver extends LocalAuthDriver {
|
|
8
7
|
client: null | Client;
|
|
9
8
|
redirectUrl: string;
|
|
10
|
-
usersService: UsersService;
|
|
11
9
|
config: Record<string, any>;
|
|
12
10
|
roleMap: RoleMap;
|
|
13
11
|
constructor(options: AuthDriverOptions, config: Record<string, any>);
|
|
@@ -13,7 +13,6 @@ import { useLogger } from '../../logger/index.js';
|
|
|
13
13
|
import { respond } from '../../middleware/respond.js';
|
|
14
14
|
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
15
15
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
16
|
-
import { UsersService } from '../../services/users.js';
|
|
17
16
|
import asyncHandler from '../../utils/async-handler.js';
|
|
18
17
|
import { getConfigFromEnv } from '../../utils/get-config-from-env.js';
|
|
19
18
|
import { getIPFromReq } from '../../utils/get-ip-from-req.js';
|
|
@@ -22,10 +21,10 @@ import { isLoginRedirectAllowed } from '../../utils/is-login-redirect-allowed.js
|
|
|
22
21
|
import { verifyJWT } from '../../utils/jwt.js';
|
|
23
22
|
import { Url } from '../../utils/url.js';
|
|
24
23
|
import { LocalAuthDriver } from './local.js';
|
|
24
|
+
import { getSchema } from '../../utils/get-schema.js';
|
|
25
25
|
export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
26
26
|
client;
|
|
27
27
|
redirectUrl;
|
|
28
|
-
usersService;
|
|
29
28
|
config;
|
|
30
29
|
roleMap;
|
|
31
30
|
constructor(options, config) {
|
|
@@ -40,7 +39,6 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
40
39
|
}
|
|
41
40
|
const redirectUrl = new Url(env['PUBLIC_URL']).addPath('auth', 'login', provider, 'callback');
|
|
42
41
|
this.redirectUrl = redirectUrl.toString();
|
|
43
|
-
this.usersService = new UsersService({ knex: this.knex, schema: this.schema });
|
|
44
42
|
this.config = config;
|
|
45
43
|
this.roleMap = {};
|
|
46
44
|
const roleMapping = this.config['roleMapping'];
|
|
@@ -227,14 +225,16 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
227
225
|
email: userPayload.email,
|
|
228
226
|
};
|
|
229
227
|
}
|
|
228
|
+
const schema = await getSchema();
|
|
230
229
|
const updatedUserPayload = await emitter.emitFilter(`auth.update`, emitPayload, {
|
|
231
230
|
identifier,
|
|
232
231
|
provider: this.config['provider'],
|
|
233
232
|
providerPayload: { accessToken: tokenSet.access_token, idToken: tokenSet.id_token, userInfo },
|
|
234
|
-
}, { database: getDatabase(), schema
|
|
233
|
+
}, { database: getDatabase(), schema, accountability: null });
|
|
235
234
|
// Update user to update refresh_token and other properties that might have changed
|
|
236
235
|
if (Object.values(updatedUserPayload).some((value) => value !== undefined)) {
|
|
237
|
-
|
|
236
|
+
const usersService = this.getUsersService(schema);
|
|
237
|
+
await usersService.updateOne(userId, updatedUserPayload);
|
|
238
238
|
}
|
|
239
239
|
return userId;
|
|
240
240
|
}
|
|
@@ -244,15 +244,17 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
244
244
|
logger.warn(`[OpenID] User doesn't exist, and public registration not allowed for provider "${provider}"`);
|
|
245
245
|
throw new InvalidCredentialsError();
|
|
246
246
|
}
|
|
247
|
+
const schema = await getSchema();
|
|
247
248
|
// Run hook so the end user has the chance to augment the
|
|
248
249
|
// user that is about to be created
|
|
249
250
|
const updatedUserPayload = await emitter.emitFilter(`auth.create`, userPayload, {
|
|
250
251
|
identifier,
|
|
251
252
|
provider: this.config['provider'],
|
|
252
253
|
providerPayload: { accessToken: tokenSet.access_token, idToken: tokenSet.id_token, userInfo },
|
|
253
|
-
}, { database: getDatabase(), schema
|
|
254
|
+
}, { database: getDatabase(), schema, accountability: null });
|
|
254
255
|
try {
|
|
255
|
-
|
|
256
|
+
const usersService = this.getUsersService(schema);
|
|
257
|
+
await usersService.createOne(updatedUserPayload);
|
|
256
258
|
}
|
|
257
259
|
catch (e) {
|
|
258
260
|
if (isDirectusError(e, ErrorCode.RecordNotUnique)) {
|
|
@@ -283,7 +285,8 @@ export class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
283
285
|
const tokenSet = await client.refresh(authData['refreshToken']);
|
|
284
286
|
// Update user refreshToken if provided
|
|
285
287
|
if (tokenSet.refresh_token) {
|
|
286
|
-
|
|
288
|
+
const usersService = this.getUsersService(await getSchema());
|
|
289
|
+
await usersService.updateOne(user.id, {
|
|
287
290
|
auth_data: JSON.stringify({ refreshToken: tokenSet.refresh_token }),
|
|
288
291
|
});
|
|
289
292
|
}
|
|
@@ -325,10 +328,11 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
325
328
|
const codeVerifier = provider.generateCodeVerifier();
|
|
326
329
|
const prompt = !!req.query['prompt'];
|
|
327
330
|
const redirect = req.query['redirect'];
|
|
331
|
+
const otp = req.query['otp'];
|
|
328
332
|
if (isLoginRedirectAllowed(redirect, providerName) === false) {
|
|
329
333
|
throw new InvalidPayloadError({ reason: `URL "${redirect}" can't be used to redirect after login` });
|
|
330
334
|
}
|
|
331
|
-
const token = jwt.sign({ verifier: codeVerifier, redirect, prompt }, getSecret(), {
|
|
335
|
+
const token = jwt.sign({ verifier: codeVerifier, redirect, prompt, otp }, getSecret(), {
|
|
332
336
|
expiresIn: (env[`AUTH_${providerName.toUpperCase()}_LOGIN_TIMEOUT`] ?? '5m'),
|
|
333
337
|
issuer: 'directus',
|
|
334
338
|
});
|
|
@@ -361,7 +365,8 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
361
365
|
const url = new Url(env['PUBLIC_URL']).addPath('admin', 'login');
|
|
362
366
|
return res.redirect(`${url.toString()}?reason=${ErrorCode.InvalidCredentials}`);
|
|
363
367
|
}
|
|
364
|
-
const { verifier,
|
|
368
|
+
const { verifier, prompt, otp } = tokenData;
|
|
369
|
+
let { redirect } = tokenData;
|
|
365
370
|
const accountability = createDefaultAccountability({ ip: getIPFromReq(req) });
|
|
366
371
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
367
372
|
if (userAgent)
|
|
@@ -382,7 +387,7 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
382
387
|
codeVerifier: verifier,
|
|
383
388
|
state: req.query['state'],
|
|
384
389
|
iss: req.query['iss'],
|
|
385
|
-
}, { session: authMode === 'session' });
|
|
390
|
+
}, { session: authMode === 'session', ...(otp ? { otp: String(otp) } : {}) });
|
|
386
391
|
}
|
|
387
392
|
catch (error) {
|
|
388
393
|
// Prompt user for a new refresh_token if invalidated
|
|
@@ -404,6 +409,18 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
404
409
|
throw error;
|
|
405
410
|
}
|
|
406
411
|
const { accessToken, refreshToken, expires } = authResponse;
|
|
412
|
+
try {
|
|
413
|
+
const claims = verifyJWT(accessToken, getSecret());
|
|
414
|
+
if (claims?.enforce_tfa === true) {
|
|
415
|
+
const url = new Url(env['PUBLIC_URL']).addPath('admin', 'tfa-setup');
|
|
416
|
+
if (redirect)
|
|
417
|
+
url.setQuery('redirect', redirect);
|
|
418
|
+
redirect = url.toString();
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
catch (e) {
|
|
422
|
+
logger.warn(e, `[OpenID] Unexpected error during OpenID login`);
|
|
423
|
+
}
|
|
407
424
|
if (redirect) {
|
|
408
425
|
if (authMode === 'session') {
|
|
409
426
|
res.cookie(env['SESSION_COOKIE_NAME'], accessToken, SESSION_COOKIE_OPTIONS);
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import * as samlify from 'samlify';
|
|
2
|
-
import { UsersService } from '../../services/users.js';
|
|
3
2
|
import type { AuthDriverOptions, User } from '../../types/index.js';
|
|
4
3
|
import { LocalAuthDriver } from './local.js';
|
|
5
4
|
export declare class SAMLAuthDriver extends LocalAuthDriver {
|
|
6
5
|
sp: samlify.ServiceProviderInstance;
|
|
7
6
|
idp: samlify.IdentityProviderInstance;
|
|
8
|
-
usersService: UsersService;
|
|
9
7
|
config: Record<string, any>;
|
|
10
8
|
constructor(options: AuthDriverOptions, config: Record<string, any>);
|
|
11
9
|
fetchUserID(identifier: string): Promise<any>;
|
|
@@ -10,22 +10,20 @@ import emitter from '../../emitter.js';
|
|
|
10
10
|
import { useLogger } from '../../logger/index.js';
|
|
11
11
|
import { respond } from '../../middleware/respond.js';
|
|
12
12
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
13
|
-
import { UsersService } from '../../services/users.js';
|
|
14
13
|
import asyncHandler from '../../utils/async-handler.js';
|
|
15
14
|
import { getConfigFromEnv } from '../../utils/get-config-from-env.js';
|
|
16
15
|
import { LocalAuthDriver } from './local.js';
|
|
17
16
|
import { isLoginRedirectAllowed } from '../../utils/is-login-redirect-allowed.js';
|
|
17
|
+
import { getSchema } from '../../utils/get-schema.js';
|
|
18
18
|
// Register the samlify schema validator
|
|
19
19
|
samlify.setSchemaValidator(validator);
|
|
20
20
|
export class SAMLAuthDriver extends LocalAuthDriver {
|
|
21
21
|
sp;
|
|
22
22
|
idp;
|
|
23
|
-
usersService;
|
|
24
23
|
config;
|
|
25
24
|
constructor(options, config) {
|
|
26
25
|
super(options, config);
|
|
27
26
|
this.config = config;
|
|
28
|
-
this.usersService = new UsersService({ knex: this.knex, schema: this.schema });
|
|
29
27
|
this.sp = samlify.ServiceProvider(getConfigFromEnv(`AUTH_${config['provider'].toUpperCase()}_SP`));
|
|
30
28
|
this.idp = samlify.IdentityProvider(getConfigFromEnv(`AUTH_${config['provider'].toUpperCase()}_IDP`));
|
|
31
29
|
}
|
|
@@ -63,11 +61,13 @@ export class SAMLAuthDriver extends LocalAuthDriver {
|
|
|
63
61
|
external_identifier: identifier.toLowerCase(),
|
|
64
62
|
role: this.config['defaultRoleId'],
|
|
65
63
|
};
|
|
64
|
+
const schema = await getSchema();
|
|
66
65
|
// Run hook so the end user has the chance to augment the
|
|
67
66
|
// user that is about to be created
|
|
68
|
-
const updatedUserPayload = await emitter.emitFilter(`auth.create`, userPayload, { identifier: identifier.toLowerCase(), provider: this.config['provider'], providerPayload: { ...payload } }, { database: getDatabase(), schema
|
|
67
|
+
const updatedUserPayload = await emitter.emitFilter(`auth.create`, userPayload, { identifier: identifier.toLowerCase(), provider: this.config['provider'], providerPayload: { ...payload } }, { database: getDatabase(), schema, accountability: null });
|
|
69
68
|
try {
|
|
70
|
-
|
|
69
|
+
const usersService = this.getUsersService(schema);
|
|
70
|
+
return await usersService.createOne(updatedUserPayload);
|
|
71
71
|
}
|
|
72
72
|
catch (error) {
|
|
73
73
|
if (isDirectusError(error, ErrorCode.RecordNotUnique)) {
|
package/dist/auth.js
CHANGED
|
@@ -6,7 +6,6 @@ import { DEFAULT_AUTH_PROVIDER } from './constants.js';
|
|
|
6
6
|
import getDatabase from './database/index.js';
|
|
7
7
|
import { useLogger } from './logger/index.js';
|
|
8
8
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
9
|
-
import { getSchema } from './utils/get-schema.js';
|
|
10
9
|
const providers = new Map();
|
|
11
10
|
export function getAuthProvider(provider) {
|
|
12
11
|
const logger = useLogger();
|
|
@@ -19,7 +18,7 @@ export function getAuthProvider(provider) {
|
|
|
19
18
|
export async function registerAuthProviders() {
|
|
20
19
|
const env = useEnv();
|
|
21
20
|
const logger = useLogger();
|
|
22
|
-
const options = { knex: getDatabase()
|
|
21
|
+
const options = { knex: getDatabase() };
|
|
23
22
|
const providerNames = toArray(env['AUTH_PROVIDERS']);
|
|
24
23
|
// Register default provider if not disabled
|
|
25
24
|
if (!env['AUTH_DISABLE_DEFAULT']) {
|
|
@@ -3,13 +3,10 @@ import getDatabase, { hasDatabaseConnection, isInstalled, validateDatabaseConnec
|
|
|
3
3
|
import runMigrations from '../../../database/migrations/run.js';
|
|
4
4
|
import installDatabase from '../../../database/seeds/run.js';
|
|
5
5
|
import { useLogger } from '../../../logger/index.js';
|
|
6
|
-
import { AccessService } from '../../../services/access.js';
|
|
7
|
-
import { PoliciesService } from '../../../services/policies.js';
|
|
8
|
-
import { RolesService } from '../../../services/roles.js';
|
|
9
6
|
import { SettingsService } from '../../../services/settings.js';
|
|
10
|
-
import { UsersService } from '../../../services/users.js';
|
|
11
7
|
import { getSchema } from '../../../utils/get-schema.js';
|
|
12
|
-
import {
|
|
8
|
+
import { createAdmin } from '../../../utils/create-admin.js';
|
|
9
|
+
import { email } from 'zod';
|
|
13
10
|
export default async function bootstrap({ skipAdminInit }) {
|
|
14
11
|
const logger = useLogger();
|
|
15
12
|
logger.info('Initializing bootstrap...');
|
|
@@ -23,15 +20,23 @@ export default async function bootstrap({ skipAdminInit }) {
|
|
|
23
20
|
await runMigrations(database, 'latest');
|
|
24
21
|
const schema = await getSchema();
|
|
25
22
|
if (skipAdminInit == null) {
|
|
26
|
-
await
|
|
23
|
+
await createAdmin(schema);
|
|
27
24
|
}
|
|
28
25
|
else {
|
|
29
26
|
logger.info('Skipping creation of default Admin user and role...');
|
|
30
27
|
}
|
|
28
|
+
const settingsService = new SettingsService({ schema });
|
|
31
29
|
if (env['PROJECT_NAME'] && typeof env['PROJECT_NAME'] === 'string' && env['PROJECT_NAME'].length > 0) {
|
|
32
|
-
const settingsService = new SettingsService({ schema });
|
|
33
30
|
await settingsService.upsertSingleton({ project_name: env['PROJECT_NAME'] });
|
|
34
31
|
}
|
|
32
|
+
if (email().safeParse(env['PROJECT_OWNER']).success) {
|
|
33
|
+
await settingsService.setOwner({
|
|
34
|
+
project_owner: env['PROJECT_OWNER'],
|
|
35
|
+
org_name: null,
|
|
36
|
+
project_usage: null,
|
|
37
|
+
product_updates: false,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
35
40
|
}
|
|
36
41
|
else {
|
|
37
42
|
logger.info('Database already initialized, skipping install');
|
|
@@ -55,29 +60,3 @@ async function waitForDatabase(database) {
|
|
|
55
60
|
await validateDatabaseConnection(database);
|
|
56
61
|
return database;
|
|
57
62
|
}
|
|
58
|
-
async function createDefaultAdmin(schema) {
|
|
59
|
-
const logger = useLogger();
|
|
60
|
-
const env = useEnv();
|
|
61
|
-
const { nanoid } = await import('nanoid');
|
|
62
|
-
logger.info('Setting up first admin role...');
|
|
63
|
-
const accessService = new AccessService({ schema });
|
|
64
|
-
const policiesService = new PoliciesService({ schema });
|
|
65
|
-
const rolesService = new RolesService({ schema });
|
|
66
|
-
const role = await rolesService.createOne(defaultAdminRole);
|
|
67
|
-
const policy = await policiesService.createOne(defaultAdminPolicy);
|
|
68
|
-
await accessService.createOne({ policy, role });
|
|
69
|
-
logger.info('Adding first admin user...');
|
|
70
|
-
const usersService = new UsersService({ schema });
|
|
71
|
-
let adminEmail = env['ADMIN_EMAIL'];
|
|
72
|
-
if (!adminEmail) {
|
|
73
|
-
logger.info('No admin email provided. Defaulting to "admin@example.com"');
|
|
74
|
-
adminEmail = 'admin@example.com';
|
|
75
|
-
}
|
|
76
|
-
let adminPassword = env['ADMIN_PASSWORD'];
|
|
77
|
-
if (!adminPassword) {
|
|
78
|
-
adminPassword = nanoid(12);
|
|
79
|
-
logger.info(`No admin password provided. Defaulting to "${adminPassword}"`);
|
|
80
|
-
}
|
|
81
|
-
const token = env['ADMIN_TOKEN'] ?? null;
|
|
82
|
-
await usersService.createOne({ ...defaultAdminUser, email: adminEmail, password: adminPassword, token, role });
|
|
83
|
-
}
|
|
@@ -9,7 +9,7 @@ import runSeed from '../../../database/seeds/run.js';
|
|
|
9
9
|
import { generateHash } from '../../../utils/generate-hash.js';
|
|
10
10
|
import createDBConnection from '../../utils/create-db-connection.js';
|
|
11
11
|
import createEnv from '../../utils/create-env/index.js';
|
|
12
|
-
import { defaultAdminPolicy, defaultAdminRole, defaultAdminUser } from '
|
|
12
|
+
import { defaultAdminPolicy, defaultAdminRole, defaultAdminUser } from '../../../utils/create-admin.js';
|
|
13
13
|
import { drivers, getDriverForClient } from '../../utils/drivers.js';
|
|
14
14
|
import { databaseQuestions } from './questions.js';
|
|
15
15
|
export default async function init() {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import type { SnapshotDiff } from '@directus/types';
|
|
2
|
+
export declare function filterSnapshotDiff(snapshot: SnapshotDiff, filters: string[]): SnapshotDiff;
|
|
1
3
|
export declare function apply(snapshotPath: string, options?: {
|
|
2
4
|
yes: boolean;
|
|
3
5
|
dryRun: boolean;
|
|
4
6
|
ignoreRules: string;
|
|
5
7
|
}): Promise<void>;
|
|
8
|
+
export declare function formatPath(path: any[]): string;
|
|
9
|
+
export declare function formatRelatedCollection(relatedCollection: string | null): string;
|