@directus/api 20.0.0-rc.1 → 20.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 +9 -4
- package/dist/auth/drivers/ldap.js +4 -4
- package/dist/auth/drivers/local.js +4 -4
- package/dist/auth/drivers/oauth2.js +4 -4
- package/dist/auth/drivers/openid.js +4 -2
- package/dist/cache.js +0 -3
- package/dist/cli/commands/bootstrap/index.js +2 -8
- package/dist/cli/commands/init/index.js +10 -9
- package/dist/cli/utils/defaults.d.ts +11 -4
- package/dist/cli/utils/defaults.js +1 -7
- package/dist/constants.d.ts +9 -1
- package/dist/constants.js +10 -0
- package/dist/controllers/auth.js +16 -5
- package/dist/controllers/permissions.js +2 -14
- package/dist/controllers/roles.js +1 -22
- package/dist/controllers/{access.d.ts → tus.d.ts} +1 -0
- package/dist/controllers/tus.js +72 -0
- package/dist/controllers/users.js +55 -0
- package/dist/database/helpers/fn/types.d.ts +1 -2
- package/dist/database/helpers/fn/types.js +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.js +2 -4
- package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.js +3 -5
- package/dist/database/helpers/geometry/types.d.ts +1 -1
- package/dist/database/helpers/geometry/types.js +2 -4
- package/dist/database/index.js +1 -2
- package/dist/database/migrations/20240701A-add-tus-data.js +12 -0
- package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
- package/dist/database/run-ast.js +450 -0
- package/dist/flows.js +4 -3
- package/dist/middleware/authenticate.js +7 -2
- package/dist/middleware/cache.js +1 -1
- package/dist/middleware/check-ip.d.ts +2 -0
- package/dist/middleware/check-ip.js +37 -0
- package/dist/middleware/get-permissions.d.ts +3 -0
- package/dist/middleware/get-permissions.js +10 -0
- package/dist/middleware/respond.js +1 -1
- package/dist/services/activity.js +10 -22
- package/dist/services/assets.d.ts +3 -2
- package/dist/services/assets.js +5 -10
- package/dist/services/authentication.js +26 -32
- package/dist/services/authorization.d.ts +17 -0
- package/dist/services/authorization.js +456 -0
- package/dist/services/collections.js +17 -18
- package/dist/services/fields.d.ts +1 -0
- package/dist/services/fields.js +24 -53
- package/dist/services/files/lib/extract-metadata.d.ts +3 -0
- package/dist/services/files/lib/extract-metadata.js +32 -0
- package/dist/services/files/utils/get-metadata.d.ts +5 -0
- package/dist/services/files/utils/get-metadata.js +107 -0
- package/dist/services/files.d.ts +4 -6
- package/dist/services/files.js +24 -140
- package/dist/services/graphql/index.d.ts +3 -3
- package/dist/services/graphql/index.js +22 -126
- package/dist/services/graphql/subscription.js +4 -2
- package/dist/services/import-export.js +4 -18
- package/dist/services/index.d.ts +2 -3
- package/dist/services/index.js +2 -3
- package/dist/services/items.js +44 -115
- package/dist/services/meta.js +23 -60
- package/dist/services/payload.d.ts +10 -9
- package/dist/services/payload.js +3 -18
- package/dist/services/{permissions.d.ts → permissions/index.d.ts} +7 -5
- package/dist/services/{permissions.js → permissions/index.js} +54 -30
- package/dist/{permissions → services/permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
- package/dist/services/permissions/lib/with-app-minimal-permissions.js +13 -0
- package/dist/services/relations.d.ts +6 -0
- package/dist/services/relations.js +29 -26
- package/dist/services/roles.d.ts +12 -4
- package/dist/services/roles.js +424 -57
- package/dist/services/server.js +6 -0
- package/dist/services/shares.d.ts +2 -0
- package/dist/services/shares.js +8 -12
- package/dist/services/specifications.d.ts +2 -2
- package/dist/services/specifications.js +27 -39
- package/dist/services/tus/data-store.d.ts +36 -0
- package/dist/services/tus/data-store.js +214 -0
- package/dist/services/tus/index.d.ts +2 -0
- package/dist/services/tus/index.js +2 -0
- package/dist/services/tus/lockers.d.ts +36 -0
- package/dist/services/tus/lockers.js +83 -0
- package/dist/services/tus/server.d.ts +8 -0
- package/dist/services/tus/server.js +80 -0
- package/dist/services/tus/utils/wait-timeout.d.ts +1 -0
- package/dist/services/tus/utils/wait-timeout.js +13 -0
- package/dist/services/users.d.ts +5 -1
- package/dist/services/users.js +161 -78
- package/dist/services/utils.js +7 -11
- package/dist/services/versions.d.ts +2 -0
- package/dist/services/versions.js +10 -34
- package/dist/storage/register-locations.js +5 -1
- package/dist/telemetry/lib/get-report.js +2 -2
- package/dist/telemetry/utils/check-increased-user-limits.d.ts +7 -0
- package/dist/telemetry/utils/check-increased-user-limits.js +25 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +6 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.js +27 -0
- package/dist/telemetry/utils/get-role-counts-by-users.d.ts +11 -0
- package/dist/telemetry/utils/get-role-counts-by-users.js +34 -0
- package/dist/telemetry/utils/get-user-count.d.ts +8 -0
- package/dist/telemetry/utils/get-user-count.js +33 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +7 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.js +35 -0
- package/dist/types/ast.d.ts +1 -43
- package/dist/types/items.d.ts +0 -11
- package/dist/utils/apply-query.d.ts +3 -4
- package/dist/utils/apply-query.js +8 -37
- package/dist/utils/get-accountability-for-role.js +25 -16
- package/dist/utils/get-accountability-for-token.js +16 -17
- package/dist/utils/get-ast-from-query.d.ts +13 -0
- package/dist/utils/get-ast-from-query.js +297 -0
- package/dist/utils/get-cache-key.d.ts +1 -1
- package/dist/utils/get-cache-key.js +1 -12
- package/dist/utils/get-column.d.ts +1 -2
- package/dist/utils/get-column.js +0 -1
- package/dist/utils/get-permissions.d.ts +2 -0
- package/dist/utils/get-permissions.js +150 -0
- package/dist/utils/get-service.js +1 -5
- package/dist/utils/merge-permissions-for-share.d.ts +4 -0
- package/dist/utils/merge-permissions-for-share.js +109 -0
- package/dist/utils/merge-permissions.d.ts +3 -0
- package/dist/utils/merge-permissions.js +95 -0
- package/dist/utils/reduce-schema.d.ts +6 -4
- package/dist/utils/reduce-schema.js +34 -14
- package/dist/utils/verify-session-jwt.js +2 -1
- package/dist/websocket/authenticate.d.ts +2 -0
- package/dist/websocket/authenticate.js +12 -0
- package/dist/websocket/controllers/graphql.js +4 -1
- package/dist/websocket/controllers/hooks.js +0 -4
- package/dist/websocket/controllers/rest.js +2 -0
- package/dist/websocket/handlers/subscribe.js +2 -0
- package/dist/websocket/utils/items.d.ts +1 -1
- package/package.json +35 -33
- package/dist/controllers/access.js +0 -148
- package/dist/controllers/policies.d.ts +0 -2
- package/dist/controllers/policies.js +0 -169
- package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +0 -16
- package/dist/database/get-ast-from-query/get-ast-from-query.js +0 -82
- package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +0 -13
- package/dist/database/get-ast-from-query/lib/convert-wildcards.js +0 -69
- package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +0 -15
- package/dist/database/get-ast-from-query/lib/parse-fields.js +0 -190
- package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +0 -14
- package/dist/database/get-ast-from-query/utils/get-deep-query.js +0 -17
- package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-related-collection.js +0 -13
- package/dist/database/get-ast-from-query/utils/get-relation.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-relation.js +0 -7
- package/dist/database/migrations/20240619A-permissions-policies.js +0 -164
- package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
- package/dist/database/run-ast/lib/get-db-query.js +0 -194
- package/dist/database/run-ast/lib/parse-current-level.d.ts +0 -7
- package/dist/database/run-ast/lib/parse-current-level.js +0 -41
- package/dist/database/run-ast/run-ast.d.ts +0 -7
- package/dist/database/run-ast/run-ast.js +0 -107
- package/dist/database/run-ast/types.js +0 -1
- package/dist/database/run-ast/utils/apply-case-when.d.ts +0 -16
- package/dist/database/run-ast/utils/apply-case-when.js +0 -26
- package/dist/database/run-ast/utils/apply-parent-filters.d.ts +0 -3
- package/dist/database/run-ast/utils/apply-parent-filters.js +0 -55
- package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +0 -10
- package/dist/database/run-ast/utils/get-column-pre-processor.js +0 -57
- package/dist/database/run-ast/utils/get-field-alias.d.ts +0 -2
- package/dist/database/run-ast/utils/get-field-alias.js +0 -4
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +0 -5
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +0 -23
- package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +0 -3
- package/dist/database/run-ast/utils/merge-with-parent-items.js +0 -87
- package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +0 -3
- package/dist/database/run-ast/utils/remove-temporary-fields.js +0 -73
- package/dist/permissions/cache.d.ts +0 -2
- package/dist/permissions/cache.js +0 -23
- package/dist/permissions/lib/fetch-permissions.d.ts +0 -10
- package/dist/permissions/lib/fetch-permissions.js +0 -55
- package/dist/permissions/lib/fetch-policies.d.ts +0 -7
- package/dist/permissions/lib/fetch-policies.js +0 -28
- package/dist/permissions/lib/fetch-roles-tree.d.ts +0 -3
- package/dist/permissions/lib/fetch-roles-tree.js +0 -28
- package/dist/permissions/lib/with-app-minimal-permissions.js +0 -10
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +0 -7
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +0 -56
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +0 -3
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +0 -16
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +0 -8
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +0 -24
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +0 -9
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +0 -31
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +0 -16
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +0 -27
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +0 -10
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +0 -23
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
- package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/types.js +0 -1
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +0 -12
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +0 -32
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +0 -4
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +0 -29
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +0 -49
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +0 -3
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +0 -56
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +0 -8
- package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +0 -9
- package/dist/permissions/modules/process-ast/lib/inject-cases.js +0 -93
- package/dist/permissions/modules/process-ast/process-ast.d.ts +0 -9
- package/dist/permissions/modules/process-ast/process-ast.js +0 -39
- package/dist/permissions/modules/process-ast/types.d.ts +0 -24
- package/dist/permissions/modules/process-ast/types.js +0 -1
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +0 -7
- package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +0 -12
- package/dist/permissions/modules/process-ast/utils/dedupe-access.js +0 -30
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +0 -15
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +0 -50
- package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/find-related-collection.js +0 -9
- package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/flatten-filter.js +0 -24
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +0 -1
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +0 -3
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +0 -5
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +0 -7
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +0 -3
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +0 -16
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +0 -12
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +0 -28
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +0 -5
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +0 -12
- package/dist/permissions/modules/process-payload/process-payload.d.ts +0 -13
- package/dist/permissions/modules/process-payload/process-payload.js +0 -77
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +0 -12
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +0 -11
- package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +0 -9
- package/dist/permissions/modules/validate-access/lib/validate-item-access.js +0 -33
- package/dist/permissions/modules/validate-access/validate-access.d.ts +0 -14
- package/dist/permissions/modules/validate-access/validate-access.js +0 -28
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +0 -1
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +0 -8
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +0 -5
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +0 -10
- package/dist/permissions/types.d.ts +0 -6
- package/dist/permissions/types.js +0 -1
- package/dist/permissions/utils/create-default-accountability.d.ts +0 -2
- package/dist/permissions/utils/create-default-accountability.js +0 -11
- package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +0 -8
- package/dist/permissions/utils/extract-required-dynamic-variable-context.js +0 -27
- package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +0 -9
- package/dist/permissions/utils/fetch-dynamic-variable-context.js +0 -43
- package/dist/permissions/utils/filter-policies-by-ip.d.ts +0 -2
- package/dist/permissions/utils/filter-policies-by-ip.js +0 -15
- package/dist/permissions/utils/get-unaliased-field-key.d.ts +0 -5
- package/dist/permissions/utils/get-unaliased-field-key.js +0 -17
- package/dist/permissions/utils/process-permissions.d.ts +0 -7
- package/dist/permissions/utils/process-permissions.js +0 -9
- package/dist/permissions/utils/with-cache.d.ts +0 -10
- package/dist/permissions/utils/with-cache.js +0 -25
- package/dist/services/access.d.ts +0 -10
- package/dist/services/access.js +0 -43
- package/dist/services/policies.d.ts +0 -12
- package/dist/services/policies.js +0 -87
- package/dist/telemetry/utils/check-user-limits.d.ts +0 -5
- package/dist/telemetry/utils/check-user-limits.js +0 -19
- package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +0 -17
- package/dist/utils/fetch-user-count/fetch-access-lookup.js +0 -22
- package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +0 -16
- package/dist/utils/fetch-user-count/fetch-access-roles.js +0 -37
- package/dist/utils/fetch-user-count/fetch-active-users.d.ts +0 -6
- package/dist/utils/fetch-user-count/fetch-active-users.js +0 -3
- package/dist/utils/fetch-user-count/fetch-user-count.d.ts +0 -12
- package/dist/utils/fetch-user-count/fetch-user-count.js +0 -57
- package/dist/utils/fetch-user-count/get-user-count-query.d.ts +0 -20
- package/dist/utils/fetch-user-count/get-user-count-query.js +0 -17
- package/dist/utils/validate-user-count-integrity.d.ts +0 -13
- package/dist/utils/validate-user-count-integrity.js +0 -29
- /package/dist/database/migrations/{20240619A-permissions-policies.d.ts → 20240701A-add-tus-data.d.ts} +0 -0
- /package/dist/{utils → services/files/utils}/parse-image-metadata.d.ts +0 -0
- /package/dist/{utils → services/files/utils}/parse-image-metadata.js +0 -0
package/dist/app.js
CHANGED
|
@@ -10,7 +10,6 @@ import path from 'path';
|
|
|
10
10
|
import qs from 'qs';
|
|
11
11
|
import { registerAuthProviders } from './auth.js';
|
|
12
12
|
import activityRouter from './controllers/activity.js';
|
|
13
|
-
import accessRouter from './controllers/access.js';
|
|
14
13
|
import assetsRouter from './controllers/assets.js';
|
|
15
14
|
import authRouter from './controllers/auth.js';
|
|
16
15
|
import collectionsRouter from './controllers/collections.js';
|
|
@@ -27,7 +26,6 @@ import notificationsRouter from './controllers/notifications.js';
|
|
|
27
26
|
import operationsRouter from './controllers/operations.js';
|
|
28
27
|
import panelsRouter from './controllers/panels.js';
|
|
29
28
|
import permissionsRouter from './controllers/permissions.js';
|
|
30
|
-
import policiesRouter from './controllers/policies.js';
|
|
31
29
|
import presetsRouter from './controllers/presets.js';
|
|
32
30
|
import relationsRouter from './controllers/relations.js';
|
|
33
31
|
import revisionsRouter from './controllers/revisions.js';
|
|
@@ -37,6 +35,7 @@ import serverRouter from './controllers/server.js';
|
|
|
37
35
|
import settingsRouter from './controllers/settings.js';
|
|
38
36
|
import sharesRouter from './controllers/shares.js';
|
|
39
37
|
import translationsRouter from './controllers/translations.js';
|
|
38
|
+
import { default as tusRouter, scheduleTusCleanup } from './controllers/tus.js';
|
|
40
39
|
import usersRouter from './controllers/users.js';
|
|
41
40
|
import utilsRouter from './controllers/utils.js';
|
|
42
41
|
import versionsRouter from './controllers/versions.js';
|
|
@@ -48,9 +47,11 @@ import { getFlowManager } from './flows.js';
|
|
|
48
47
|
import { createExpressLogger, useLogger } from './logger.js';
|
|
49
48
|
import authenticate from './middleware/authenticate.js';
|
|
50
49
|
import cache from './middleware/cache.js';
|
|
50
|
+
import { checkIP } from './middleware/check-ip.js';
|
|
51
51
|
import cors from './middleware/cors.js';
|
|
52
52
|
import errorHandler from './middleware/error-handler.js';
|
|
53
53
|
import extractToken from './middleware/extract-token.js';
|
|
54
|
+
import getPermissions from './middleware/get-permissions.js';
|
|
54
55
|
import rateLimiterGlobal from './middleware/rate-limiter-global.js';
|
|
55
56
|
import rateLimiter from './middleware/rate-limiter-ip.js';
|
|
56
57
|
import sanitizeQuery from './middleware/sanitize-query.js';
|
|
@@ -197,20 +198,24 @@ export default async function createApp() {
|
|
|
197
198
|
}
|
|
198
199
|
app.get('/server/ping', (_req, res) => res.send('pong'));
|
|
199
200
|
app.use(authenticate);
|
|
201
|
+
app.use(checkIP);
|
|
200
202
|
app.use(sanitizeQuery);
|
|
201
203
|
app.use(cache);
|
|
202
204
|
app.use(schema);
|
|
205
|
+
app.use(getPermissions);
|
|
203
206
|
await emitter.emitInit('middlewares.after', { app });
|
|
204
207
|
await emitter.emitInit('routes.before', { app });
|
|
205
208
|
app.use('/auth', authRouter);
|
|
206
209
|
app.use('/graphql', graphqlRouter);
|
|
207
210
|
app.use('/activity', activityRouter);
|
|
208
|
-
app.use('/access', accessRouter);
|
|
209
211
|
app.use('/assets', assetsRouter);
|
|
210
212
|
app.use('/collections', collectionsRouter);
|
|
211
213
|
app.use('/dashboards', dashboardsRouter);
|
|
212
214
|
app.use('/extensions', extensionsRouter);
|
|
213
215
|
app.use('/fields', fieldsRouter);
|
|
216
|
+
if (env['TUS_ENABLED'] === true) {
|
|
217
|
+
app.use('/files/tus', tusRouter);
|
|
218
|
+
}
|
|
214
219
|
app.use('/files', filesRouter);
|
|
215
220
|
app.use('/flows', flowsRouter);
|
|
216
221
|
app.use('/folders', foldersRouter);
|
|
@@ -219,7 +224,6 @@ export default async function createApp() {
|
|
|
219
224
|
app.use('/operations', operationsRouter);
|
|
220
225
|
app.use('/panels', panelsRouter);
|
|
221
226
|
app.use('/permissions', permissionsRouter);
|
|
222
|
-
app.use('/policies', policiesRouter);
|
|
223
227
|
app.use('/presets', presetsRouter);
|
|
224
228
|
app.use('/translations', translationsRouter);
|
|
225
229
|
app.use('/relations', relationsRouter);
|
|
@@ -241,6 +245,7 @@ export default async function createApp() {
|
|
|
241
245
|
app.use(errorHandler);
|
|
242
246
|
await emitter.emitInit('routes.after', { app });
|
|
243
247
|
initTelemetry();
|
|
248
|
+
scheduleTusCleanup();
|
|
244
249
|
await emitter.emitInit('app.after', { app });
|
|
245
250
|
return app;
|
|
246
251
|
}
|
|
@@ -3,17 +3,16 @@ import { ErrorCode, InvalidCredentialsError, InvalidPayloadError, InvalidProvide
|
|
|
3
3
|
import { Router } from 'express';
|
|
4
4
|
import Joi from 'joi';
|
|
5
5
|
import ldap from 'ldapjs';
|
|
6
|
-
import { REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS } from '../../constants.js';
|
|
7
6
|
import getDatabase from '../../database/index.js';
|
|
8
7
|
import emitter from '../../emitter.js';
|
|
9
8
|
import { useLogger } from '../../logger.js';
|
|
10
9
|
import { respond } from '../../middleware/respond.js';
|
|
11
|
-
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
12
10
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
13
11
|
import { UsersService } from '../../services/users.js';
|
|
14
12
|
import asyncHandler from '../../utils/async-handler.js';
|
|
15
13
|
import { getIPFromReq } from '../../utils/get-ip-from-req.js';
|
|
16
14
|
import { AuthDriver } from '../auth.js';
|
|
15
|
+
import { REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS } from '../../constants.js';
|
|
17
16
|
// 0x2: ACCOUNTDISABLE
|
|
18
17
|
// 0x10: LOCKOUT
|
|
19
18
|
// 0x800000: PASSWORD_EXPIRED
|
|
@@ -296,9 +295,10 @@ export function createLDAPAuthRouter(provider) {
|
|
|
296
295
|
}).unknown();
|
|
297
296
|
router.post('/', asyncHandler(async (req, res, next) => {
|
|
298
297
|
const env = useEnv();
|
|
299
|
-
const accountability =
|
|
298
|
+
const accountability = {
|
|
300
299
|
ip: getIPFromReq(req),
|
|
301
|
-
|
|
300
|
+
role: null,
|
|
301
|
+
};
|
|
302
302
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
303
303
|
if (userAgent)
|
|
304
304
|
accountability.userAgent = userAgent;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { useEnv } from '@directus/env';
|
|
2
1
|
import { InvalidCredentialsError, InvalidPayloadError } from '@directus/errors';
|
|
3
2
|
import argon2 from 'argon2';
|
|
4
3
|
import { Router } from 'express';
|
|
5
4
|
import Joi from 'joi';
|
|
6
5
|
import { performance } from 'perf_hooks';
|
|
7
6
|
import { REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS } from '../../constants.js';
|
|
7
|
+
import { useEnv } from '@directus/env';
|
|
8
8
|
import { respond } from '../../middleware/respond.js';
|
|
9
|
-
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
10
9
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
11
10
|
import asyncHandler from '../../utils/async-handler.js';
|
|
12
11
|
import { getIPFromReq } from '../../utils/get-ip-from-req.js';
|
|
@@ -48,9 +47,10 @@ export function createLocalAuthRouter(provider) {
|
|
|
48
47
|
router.post('/', asyncHandler(async (req, res, next) => {
|
|
49
48
|
const STALL_TIME = env['LOGIN_STALL_TIME'];
|
|
50
49
|
const timeStart = performance.now();
|
|
51
|
-
const accountability =
|
|
50
|
+
const accountability = {
|
|
52
51
|
ip: getIPFromReq(req),
|
|
53
|
-
|
|
52
|
+
role: null,
|
|
53
|
+
};
|
|
54
54
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
55
55
|
if (userAgent)
|
|
56
56
|
accountability.userAgent = userAgent;
|
|
@@ -11,16 +11,15 @@ import getDatabase from '../../database/index.js';
|
|
|
11
11
|
import emitter from '../../emitter.js';
|
|
12
12
|
import { useLogger } from '../../logger.js';
|
|
13
13
|
import { respond } from '../../middleware/respond.js';
|
|
14
|
-
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
15
14
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
16
15
|
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';
|
|
20
|
-
import { getSecret } from '../../utils/get-secret.js';
|
|
21
19
|
import { isLoginRedirectAllowed } from '../../utils/is-login-redirect-allowed.js';
|
|
22
20
|
import { Url } from '../../utils/url.js';
|
|
23
21
|
import { LocalAuthDriver } from './local.js';
|
|
22
|
+
import { getSecret } from '../../utils/get-secret.js';
|
|
24
23
|
export class OAuth2AuthDriver extends LocalAuthDriver {
|
|
25
24
|
client;
|
|
26
25
|
redirectUrl;
|
|
@@ -252,9 +251,10 @@ export function createOAuth2AuthRouter(providerName) {
|
|
|
252
251
|
throw new InvalidCredentialsError();
|
|
253
252
|
}
|
|
254
253
|
const { verifier, redirect, prompt } = tokenData;
|
|
255
|
-
const accountability =
|
|
254
|
+
const accountability = {
|
|
256
255
|
ip: getIPFromReq(req),
|
|
257
|
-
|
|
256
|
+
role: null,
|
|
257
|
+
};
|
|
258
258
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
259
259
|
if (userAgent)
|
|
260
260
|
accountability.userAgent = userAgent;
|
|
@@ -11,7 +11,6 @@ import getDatabase from '../../database/index.js';
|
|
|
11
11
|
import emitter from '../../emitter.js';
|
|
12
12
|
import { useLogger } from '../../logger.js';
|
|
13
13
|
import { respond } from '../../middleware/respond.js';
|
|
14
|
-
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
15
14
|
import { AuthenticationService } from '../../services/authentication.js';
|
|
16
15
|
import { UsersService } from '../../services/users.js';
|
|
17
16
|
import asyncHandler from '../../utils/async-handler.js';
|
|
@@ -273,7 +272,10 @@ export function createOpenIDAuthRouter(providerName) {
|
|
|
273
272
|
throw new InvalidCredentialsError();
|
|
274
273
|
}
|
|
275
274
|
const { verifier, redirect, prompt } = tokenData;
|
|
276
|
-
const accountability =
|
|
275
|
+
const accountability = {
|
|
276
|
+
ip: getIPFromReq(req),
|
|
277
|
+
role: null,
|
|
278
|
+
};
|
|
277
279
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
278
280
|
if (userAgent)
|
|
279
281
|
accountability.userAgent = userAgent;
|
package/dist/cache.js
CHANGED
|
@@ -8,7 +8,6 @@ import { compress, decompress } from './utils/compress.js';
|
|
|
8
8
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
9
9
|
import { getMilliseconds } from './utils/get-milliseconds.js';
|
|
10
10
|
import { validateEnv } from './utils/validate-env.js';
|
|
11
|
-
import { clearCache as clearPermissionCache } from './permissions/cache.js';
|
|
12
11
|
import { createRequire } from 'node:module';
|
|
13
12
|
const logger = useLogger();
|
|
14
13
|
const env = useEnv();
|
|
@@ -67,8 +66,6 @@ export async function clearSystemCache(opts) {
|
|
|
67
66
|
}
|
|
68
67
|
await sharedSchemaCache.clear();
|
|
69
68
|
await localSchemaCache.clear();
|
|
70
|
-
// Since a lot of cached permission function rely on the schema it needs to be cleared as well
|
|
71
|
-
await clearPermissionCache();
|
|
72
69
|
messenger.publish('schemaChanged', { autoPurgeCache: opts?.autoPurgeCache });
|
|
73
70
|
}
|
|
74
71
|
export async function setSystemCache(key, value, ttl) {
|
|
@@ -3,13 +3,11 @@ 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.js';
|
|
6
|
-
import { AccessService } from '../../../services/access.js';
|
|
7
|
-
import { PoliciesService } from '../../../services/policies.js';
|
|
8
6
|
import { RolesService } from '../../../services/roles.js';
|
|
9
7
|
import { SettingsService } from '../../../services/settings.js';
|
|
10
8
|
import { UsersService } from '../../../services/users.js';
|
|
11
9
|
import { getSchema } from '../../../utils/get-schema.js';
|
|
12
|
-
import {
|
|
10
|
+
import { defaultAdminRole, defaultAdminUser } from '../../utils/defaults.js';
|
|
13
11
|
export default async function bootstrap({ skipAdminInit }) {
|
|
14
12
|
const logger = useLogger();
|
|
15
13
|
logger.info('Initializing bootstrap...');
|
|
@@ -60,12 +58,8 @@ async function createDefaultAdmin(schema) {
|
|
|
60
58
|
const env = useEnv();
|
|
61
59
|
const { nanoid } = await import('nanoid');
|
|
62
60
|
logger.info('Setting up first admin role...');
|
|
63
|
-
const accessService = new AccessService({ schema });
|
|
64
|
-
const policiesService = new PoliciesService({ schema });
|
|
65
61
|
const rolesService = new RolesService({ schema });
|
|
66
62
|
const role = await rolesService.createOne(defaultAdminRole);
|
|
67
|
-
const policy = await policiesService.createOne(defaultAdminPolicy);
|
|
68
|
-
await accessService.createOne({ policy, role });
|
|
69
63
|
logger.info('Adding first admin user...');
|
|
70
64
|
const usersService = new UsersService({ schema });
|
|
71
65
|
let adminEmail = env['ADMIN_EMAIL'];
|
|
@@ -78,5 +72,5 @@ async function createDefaultAdmin(schema) {
|
|
|
78
72
|
adminPassword = nanoid(12);
|
|
79
73
|
logger.info(`No admin password provided. Defaulting to "${adminPassword}"`);
|
|
80
74
|
}
|
|
81
|
-
await usersService.createOne({
|
|
75
|
+
await usersService.createOne({ email: adminEmail, password: adminPassword, role, ...defaultAdminUser });
|
|
82
76
|
}
|
|
@@ -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 {
|
|
12
|
+
import { defaultAdminRole, defaultAdminUser } from '../../utils/defaults.js';
|
|
13
13
|
import { drivers, getDriverForClient } from '../../utils/drivers.js';
|
|
14
14
|
import { databaseQuestions } from './questions.js';
|
|
15
15
|
export default async function init() {
|
|
@@ -79,17 +79,18 @@ export default async function init() {
|
|
|
79
79
|
},
|
|
80
80
|
]);
|
|
81
81
|
firstUser.password = await generateHash(firstUser.password);
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
await db('directus_roles').insert({
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
const userID = randomUUID();
|
|
83
|
+
const roleID = randomUUID();
|
|
84
|
+
await db('directus_roles').insert({
|
|
85
|
+
id: roleID,
|
|
86
|
+
...defaultAdminRole,
|
|
87
|
+
});
|
|
87
88
|
await db('directus_users').insert({
|
|
88
|
-
|
|
89
|
-
id: randomUUID(),
|
|
89
|
+
id: userID,
|
|
90
90
|
email: firstUser.email,
|
|
91
91
|
password: firstUser.password,
|
|
92
|
-
role,
|
|
92
|
+
role: roleID,
|
|
93
|
+
...defaultAdminUser,
|
|
93
94
|
});
|
|
94
95
|
await db.destroy();
|
|
95
96
|
process.stdout.write(`\nYour project has been created at ${chalk.green(rootPath)}.\n`);
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export declare const defaultAdminRole: {
|
|
2
|
+
name: string;
|
|
3
|
+
icon: string;
|
|
4
|
+
admin_access: boolean;
|
|
5
|
+
description: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const defaultAdminUser: {
|
|
8
|
+
status: string;
|
|
9
|
+
first_name: string;
|
|
10
|
+
last_name: string;
|
|
11
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const defaultAdminRole = {
|
|
2
2
|
name: 'Administrator',
|
|
3
3
|
icon: 'verified',
|
|
4
|
+
admin_access: true,
|
|
4
5
|
description: '$t:admin_description',
|
|
5
6
|
};
|
|
6
7
|
export const defaultAdminUser = {
|
|
@@ -8,10 +9,3 @@ export const defaultAdminUser = {
|
|
|
8
9
|
first_name: 'Admin',
|
|
9
10
|
last_name: 'User',
|
|
10
11
|
};
|
|
11
|
-
export const defaultAdminPolicy = {
|
|
12
|
-
name: 'Administrator',
|
|
13
|
-
icon: 'verified',
|
|
14
|
-
admin_access: true,
|
|
15
|
-
app_access: true,
|
|
16
|
-
description: '$t:admin_description',
|
|
17
|
-
};
|
package/dist/constants.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare const FILTER_VARIABLES: string[];
|
|
|
6
6
|
export declare const ALIAS_TYPES: string[];
|
|
7
7
|
export declare const DEFAULT_AUTH_PROVIDER = "default";
|
|
8
8
|
export declare const COLUMN_TRANSFORMS: string[];
|
|
9
|
-
export declare const GENERATE_SPECIAL:
|
|
9
|
+
export declare const GENERATE_SPECIAL: string[];
|
|
10
10
|
export declare const UUID_REGEX = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
|
11
11
|
export declare const REFRESH_COOKIE_OPTIONS: CookieOptions;
|
|
12
12
|
export declare const SESSION_COOKIE_OPTIONS: CookieOptions;
|
|
@@ -15,3 +15,11 @@ export declare const OAS_REQUIRED_SCHEMAS: string[];
|
|
|
15
15
|
export declare const SUPPORTED_IMAGE_TRANSFORM_FORMATS: string[];
|
|
16
16
|
/** Formats where metadata extraction is supported */
|
|
17
17
|
export declare const SUPPORTED_IMAGE_METADATA_FORMATS: string[];
|
|
18
|
+
/** Resumable uploads */
|
|
19
|
+
export declare const RESUMABLE_UPLOADS: {
|
|
20
|
+
ENABLED: boolean;
|
|
21
|
+
CHUNK_SIZE: number;
|
|
22
|
+
MAX_SIZE: number;
|
|
23
|
+
EXPIRATION_TIME: number;
|
|
24
|
+
SCHEDULE: string;
|
|
25
|
+
};
|
package/dist/constants.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getMilliseconds } from './utils/get-milliseconds.js';
|
|
2
2
|
import { useEnv } from '@directus/env';
|
|
3
|
+
import { toBoolean } from '@directus/utils';
|
|
4
|
+
import bytes from 'bytes';
|
|
3
5
|
const env = useEnv();
|
|
4
6
|
export const SYSTEM_ASSET_ALLOW_LIST = [
|
|
5
7
|
{
|
|
@@ -77,3 +79,11 @@ export const SUPPORTED_IMAGE_METADATA_FORMATS = [
|
|
|
77
79
|
'image/tiff',
|
|
78
80
|
'image/avif',
|
|
79
81
|
];
|
|
82
|
+
/** Resumable uploads */
|
|
83
|
+
export const RESUMABLE_UPLOADS = {
|
|
84
|
+
ENABLED: toBoolean(env['TUS_ENABLED']),
|
|
85
|
+
CHUNK_SIZE: bytes(env['TUS_CHUNK_SIZE']),
|
|
86
|
+
MAX_SIZE: bytes(env['FILES_MAX_UPLOAD_SIZE']),
|
|
87
|
+
EXPIRATION_TIME: getMilliseconds(env['TUS_UPLOAD_EXPIRATION'], 600_000 /* 10min */),
|
|
88
|
+
SCHEDULE: String(env['TUS_CLEANUP_SCHEDULE']),
|
|
89
|
+
};
|
package/dist/controllers/auth.js
CHANGED
|
@@ -5,7 +5,6 @@ import { createLDAPAuthRouter, createLocalAuthRouter, createOAuth2AuthRouter, cr
|
|
|
5
5
|
import { DEFAULT_AUTH_PROVIDER, REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS } from '../constants.js';
|
|
6
6
|
import { useLogger } from '../logger.js';
|
|
7
7
|
import { respond } from '../middleware/respond.js';
|
|
8
|
-
import { createDefaultAccountability } from '../permissions/utils/create-default-accountability.js';
|
|
9
8
|
import { AuthenticationService } from '../services/authentication.js';
|
|
10
9
|
import { UsersService } from '../services/users.js';
|
|
11
10
|
import asyncHandler from '../utils/async-handler.js';
|
|
@@ -72,7 +71,10 @@ function getCurrentRefreshToken(req, mode) {
|
|
|
72
71
|
return undefined;
|
|
73
72
|
}
|
|
74
73
|
router.post('/refresh', asyncHandler(async (req, res, next) => {
|
|
75
|
-
const accountability =
|
|
74
|
+
const accountability = {
|
|
75
|
+
ip: getIPFromReq(req),
|
|
76
|
+
role: null,
|
|
77
|
+
};
|
|
76
78
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
77
79
|
if (userAgent)
|
|
78
80
|
accountability.userAgent = userAgent;
|
|
@@ -109,7 +111,10 @@ router.post('/refresh', asyncHandler(async (req, res, next) => {
|
|
|
109
111
|
return next();
|
|
110
112
|
}), respond);
|
|
111
113
|
router.post('/logout', asyncHandler(async (req, res, next) => {
|
|
112
|
-
const accountability =
|
|
114
|
+
const accountability = {
|
|
115
|
+
ip: getIPFromReq(req),
|
|
116
|
+
role: null,
|
|
117
|
+
};
|
|
113
118
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
114
119
|
if (userAgent)
|
|
115
120
|
accountability.userAgent = userAgent;
|
|
@@ -140,7 +145,10 @@ router.post('/password/request', asyncHandler(async (req, _res, next) => {
|
|
|
140
145
|
if (typeof req.body.email !== 'string') {
|
|
141
146
|
throw new InvalidPayloadError({ reason: `"email" field is required` });
|
|
142
147
|
}
|
|
143
|
-
const accountability =
|
|
148
|
+
const accountability = {
|
|
149
|
+
ip: getIPFromReq(req),
|
|
150
|
+
role: null,
|
|
151
|
+
};
|
|
144
152
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
145
153
|
if (userAgent)
|
|
146
154
|
accountability.userAgent = userAgent;
|
|
@@ -169,7 +177,10 @@ router.post('/password/reset', asyncHandler(async (req, _res, next) => {
|
|
|
169
177
|
if (typeof req.body.password !== 'string') {
|
|
170
178
|
throw new InvalidPayloadError({ reason: `"password" field is required` });
|
|
171
179
|
}
|
|
172
|
-
const accountability =
|
|
180
|
+
const accountability = {
|
|
181
|
+
ip: getIPFromReq(req),
|
|
182
|
+
role: null,
|
|
183
|
+
};
|
|
173
184
|
const userAgent = req.get('user-agent')?.substring(0, 1024);
|
|
174
185
|
if (userAgent)
|
|
175
186
|
accountability.userAgent = userAgent;
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { ErrorCode,
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import getDatabase from '../database/index.js';
|
|
4
3
|
import { respond } from '../middleware/respond.js';
|
|
5
4
|
import useCollection from '../middleware/use-collection.js';
|
|
6
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
7
|
-
import { fetchAccountabilityCollectionAccess } from '../permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js';
|
|
8
6
|
import { MetaService } from '../services/meta.js';
|
|
9
|
-
import { PermissionsService } from '../services/permissions.js';
|
|
7
|
+
import { PermissionsService } from '../services/permissions/index.js';
|
|
10
8
|
import asyncHandler from '../utils/async-handler.js';
|
|
11
9
|
import { sanitizeQuery } from '../utils/sanitize-query.js';
|
|
12
10
|
const router = express.Router();
|
|
@@ -71,16 +69,6 @@ const readHandler = asyncHandler(async (req, res, next) => {
|
|
|
71
69
|
});
|
|
72
70
|
router.get('/', validateBatch('read'), readHandler, respond);
|
|
73
71
|
router.search('/', validateBatch('read'), readHandler, respond);
|
|
74
|
-
router.get('/me', asyncHandler(async (req, res, next) => {
|
|
75
|
-
if (!req.accountability?.user && !req.accountability?.role)
|
|
76
|
-
throw new ForbiddenError();
|
|
77
|
-
const result = await fetchAccountabilityCollectionAccess(req.accountability, {
|
|
78
|
-
schema: req.schema,
|
|
79
|
-
knex: getDatabase(),
|
|
80
|
-
});
|
|
81
|
-
res.locals['payload'] = { data: result };
|
|
82
|
-
return next();
|
|
83
|
-
}), respond);
|
|
84
72
|
router.get('/:pk', asyncHandler(async (req, res, next) => {
|
|
85
73
|
if (req.path.endsWith('me'))
|
|
86
74
|
return next();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ErrorCode,
|
|
1
|
+
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import { respond } from '../middleware/respond.js';
|
|
4
4
|
import useCollection from '../middleware/use-collection.js';
|
|
@@ -57,27 +57,6 @@ const readHandler = asyncHandler(async (req, res, next) => {
|
|
|
57
57
|
});
|
|
58
58
|
router.get('/', validateBatch('read'), readHandler, respond);
|
|
59
59
|
router.search('/', validateBatch('read'), readHandler, respond);
|
|
60
|
-
router.get('/me', asyncHandler(async (req, res, next) => {
|
|
61
|
-
if (!req.accountability?.user && !req.accountability?.role)
|
|
62
|
-
throw new ForbiddenError();
|
|
63
|
-
const service = new RolesService({
|
|
64
|
-
accountability: req.accountability,
|
|
65
|
-
schema: req.schema,
|
|
66
|
-
});
|
|
67
|
-
const query = { ...req.sanitizedQuery, limit: -1 };
|
|
68
|
-
try {
|
|
69
|
-
const roles = await service.readMany(req.accountability.roles, query);
|
|
70
|
-
res.locals['payload'] = { data: roles || null };
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
74
|
-
res.locals['payload'] = { data: req.accountability.roles.map((id) => ({ id })) };
|
|
75
|
-
return next();
|
|
76
|
-
}
|
|
77
|
-
throw error;
|
|
78
|
-
}
|
|
79
|
-
return next();
|
|
80
|
-
}), respond);
|
|
81
60
|
router.get('/:pk', asyncHandler(async (req, res, next) => {
|
|
82
61
|
const service = new RolesService({
|
|
83
62
|
accountability: req.accountability,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { getSchema } from '../utils/get-schema.js';
|
|
3
|
+
import { scheduleSynchronizedJob, validateCron } from '../utils/schedule.js';
|
|
4
|
+
import { createTusServer } from '../services/tus/index.js';
|
|
5
|
+
import { AuthorizationService } from '../services/authorization.js';
|
|
6
|
+
import asyncHandler from '../utils/async-handler.js';
|
|
7
|
+
import { ForbiddenError } from '@directus/errors';
|
|
8
|
+
import { RESUMABLE_UPLOADS } from '../constants.js';
|
|
9
|
+
const mapAction = (method) => {
|
|
10
|
+
switch (method) {
|
|
11
|
+
case 'POST':
|
|
12
|
+
return 'create';
|
|
13
|
+
case 'PATCH':
|
|
14
|
+
return 'update';
|
|
15
|
+
case 'DELETE':
|
|
16
|
+
return 'delete';
|
|
17
|
+
default:
|
|
18
|
+
return 'read';
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const checkFileAccess = asyncHandler(async (req, _res, next) => {
|
|
22
|
+
const auth = new AuthorizationService({
|
|
23
|
+
accountability: req.accountability,
|
|
24
|
+
schema: req.schema,
|
|
25
|
+
});
|
|
26
|
+
if (!req.accountability?.admin) {
|
|
27
|
+
const action = mapAction(req.method);
|
|
28
|
+
if (action === 'create') {
|
|
29
|
+
// checkAccess doesnt seem to work as expected for "create" actions
|
|
30
|
+
const hasPermission = Boolean(req.accountability?.permissions?.find((permission) => {
|
|
31
|
+
return permission.collection === 'directus_files' && permission.action === action;
|
|
32
|
+
}));
|
|
33
|
+
if (!hasPermission)
|
|
34
|
+
throw new ForbiddenError();
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
try {
|
|
38
|
+
await auth.checkAccess(action, 'directus_files');
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
throw new ForbiddenError();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return next();
|
|
46
|
+
});
|
|
47
|
+
const handler = asyncHandler(async (req, res) => {
|
|
48
|
+
const tusServer = await createTusServer({
|
|
49
|
+
schema: req.schema,
|
|
50
|
+
accountability: req.accountability,
|
|
51
|
+
});
|
|
52
|
+
await tusServer.handle(req, res);
|
|
53
|
+
});
|
|
54
|
+
export function scheduleTusCleanup() {
|
|
55
|
+
if (!RESUMABLE_UPLOADS.ENABLED)
|
|
56
|
+
return;
|
|
57
|
+
if (validateCron(RESUMABLE_UPLOADS.SCHEDULE)) {
|
|
58
|
+
scheduleSynchronizedJob('tus-cleanup', RESUMABLE_UPLOADS.SCHEDULE, async () => {
|
|
59
|
+
const tusServer = await createTusServer({
|
|
60
|
+
schema: await getSchema(),
|
|
61
|
+
});
|
|
62
|
+
await tusServer.cleanUpExpiredUploads();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const router = Router();
|
|
67
|
+
router.post('/', checkFileAccess, handler);
|
|
68
|
+
router.patch('/:id', checkFileAccess, handler);
|
|
69
|
+
router.delete('/:id', checkFileAccess, handler);
|
|
70
|
+
router.options('/:id', checkFileAccess, handler);
|
|
71
|
+
router.head('/:id', checkFileAccess, handler);
|
|
72
|
+
export default router;
|
|
@@ -7,6 +7,7 @@ import useCollection from '../middleware/use-collection.js';
|
|
|
7
7
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
8
8
|
import { AuthenticationService } from '../services/authentication.js';
|
|
9
9
|
import { MetaService } from '../services/meta.js';
|
|
10
|
+
import { RolesService } from '../services/roles.js';
|
|
10
11
|
import { TFAService } from '../services/tfa.js';
|
|
11
12
|
import { UsersService } from '../services/users.js';
|
|
12
13
|
import asyncHandler from '../utils/async-handler.js';
|
|
@@ -261,6 +262,33 @@ router.post('/me/tfa/enable/', asyncHandler(async (req, _res, next) => {
|
|
|
261
262
|
if (!req.body.otp) {
|
|
262
263
|
throw new InvalidPayloadError({ reason: `"otp" is required` });
|
|
263
264
|
}
|
|
265
|
+
// Override permissions only when enforce TFA is enabled in role
|
|
266
|
+
if (req.accountability.role) {
|
|
267
|
+
const rolesService = new RolesService({
|
|
268
|
+
schema: req.schema,
|
|
269
|
+
});
|
|
270
|
+
const role = (await rolesService.readOne(req.accountability.role));
|
|
271
|
+
if (role && role.enforce_tfa) {
|
|
272
|
+
const existingPermission = await req.accountability.permissions?.find((p) => p.collection === 'directus_users' && p.action === 'update');
|
|
273
|
+
if (existingPermission) {
|
|
274
|
+
existingPermission.fields = ['tfa_secret'];
|
|
275
|
+
existingPermission.permissions = { id: { _eq: req.accountability.user } };
|
|
276
|
+
existingPermission.presets = null;
|
|
277
|
+
existingPermission.validation = null;
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
(req.accountability.permissions || (req.accountability.permissions = [])).push({
|
|
281
|
+
action: 'update',
|
|
282
|
+
collection: 'directus_users',
|
|
283
|
+
fields: ['tfa_secret'],
|
|
284
|
+
permissions: { id: { _eq: req.accountability.user } },
|
|
285
|
+
presets: null,
|
|
286
|
+
role: req.accountability.role,
|
|
287
|
+
validation: null,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
264
292
|
const service = new TFAService({
|
|
265
293
|
accountability: req.accountability,
|
|
266
294
|
schema: req.schema,
|
|
@@ -275,6 +303,33 @@ router.post('/me/tfa/disable', asyncHandler(async (req, _res, next) => {
|
|
|
275
303
|
if (!req.body.otp) {
|
|
276
304
|
throw new InvalidPayloadError({ reason: `"otp" is required` });
|
|
277
305
|
}
|
|
306
|
+
// Override permissions only when enforce TFA is enabled in role
|
|
307
|
+
if (req.accountability.role) {
|
|
308
|
+
const rolesService = new RolesService({
|
|
309
|
+
schema: req.schema,
|
|
310
|
+
});
|
|
311
|
+
const role = (await rolesService.readOne(req.accountability.role));
|
|
312
|
+
if (role && role.enforce_tfa) {
|
|
313
|
+
const existingPermission = await req.accountability.permissions?.find((p) => p.collection === 'directus_users' && p.action === 'update');
|
|
314
|
+
if (existingPermission) {
|
|
315
|
+
existingPermission.fields = ['tfa_secret'];
|
|
316
|
+
existingPermission.permissions = { id: { _eq: req.accountability.user } };
|
|
317
|
+
existingPermission.presets = null;
|
|
318
|
+
existingPermission.validation = null;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
(req.accountability.permissions || (req.accountability.permissions = [])).push({
|
|
322
|
+
action: 'update',
|
|
323
|
+
collection: 'directus_users',
|
|
324
|
+
fields: ['tfa_secret'],
|
|
325
|
+
permissions: { id: { _eq: req.accountability.user } },
|
|
326
|
+
presets: null,
|
|
327
|
+
role: req.accountability.role,
|
|
328
|
+
validation: null,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
278
333
|
const service = new TFAService({
|
|
279
334
|
accountability: req.accountability,
|
|
280
335
|
schema: req.schema,
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Query, SchemaOverview } from '@directus/types';
|
|
2
2
|
import type { Knex } from 'knex';
|
|
3
3
|
import { DatabaseHelper } from '../types.js';
|
|
4
4
|
export type FnHelperOptions = {
|
|
5
5
|
type: string | undefined;
|
|
6
6
|
query: Query | undefined;
|
|
7
|
-
cases: Filter[] | undefined;
|
|
8
7
|
originalCollectionName: string | undefined;
|
|
9
8
|
};
|
|
10
9
|
export declare abstract class FnHelper extends DatabaseHelper {
|
|
@@ -28,7 +28,7 @@ export class FnHelper extends DatabaseHelper {
|
|
|
28
28
|
collection: relation.collection,
|
|
29
29
|
},
|
|
30
30
|
};
|
|
31
|
-
countQuery = applyFilter(this.knex, this.schema, countQuery, options.query.filter, relation.collection, aliasMap
|
|
31
|
+
countQuery = applyFilter(this.knex, this.schema, countQuery, options.query.filter, relation.collection, aliasMap).query;
|
|
32
32
|
}
|
|
33
33
|
return this.knex.raw('(' + countQuery.toQuery() + ')');
|
|
34
34
|
}
|