@directus/api 21.0.0 → 22.1.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 +4 -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 +2 -4
- package/dist/cache.js +3 -0
- package/dist/cli/commands/bootstrap/index.js +8 -2
- package/dist/cli/commands/init/index.js +9 -10
- package/dist/cli/commands/init/questions.d.ts +7 -6
- package/dist/cli/commands/init/questions.js +2 -2
- package/dist/cli/utils/create-env/index.d.ts +2 -2
- package/dist/cli/utils/create-env/index.js +3 -1
- package/dist/cli/utils/defaults.d.ts +4 -11
- package/dist/cli/utils/defaults.js +7 -1
- package/dist/cli/utils/drivers.js +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/controllers/access.d.ts +2 -0
- package/dist/controllers/access.js +148 -0
- package/dist/controllers/auth.js +5 -16
- package/dist/controllers/permissions.js +14 -2
- package/dist/controllers/policies.d.ts +2 -0
- package/dist/controllers/policies.js +169 -0
- package/dist/controllers/roles.js +22 -1
- package/dist/controllers/tus.js +14 -26
- package/dist/controllers/users.js +0 -55
- package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +16 -0
- package/dist/database/get-ast-from-query/get-ast-from-query.js +82 -0
- package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +13 -0
- package/dist/database/get-ast-from-query/lib/convert-wildcards.js +69 -0
- package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +15 -0
- package/dist/database/get-ast-from-query/lib/parse-fields.js +200 -0
- package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +14 -0
- package/dist/database/get-ast-from-query/utils/get-deep-query.js +17 -0
- package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +2 -0
- package/dist/database/get-ast-from-query/utils/get-related-collection.js +13 -0
- package/dist/database/get-ast-from-query/utils/get-relation.d.ts +2 -0
- package/dist/database/get-ast-from-query/utils/get-relation.js +7 -0
- package/dist/database/helpers/fn/types.d.ts +2 -1
- 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 +4 -2
- 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 +5 -3
- package/dist/database/helpers/geometry/types.d.ts +1 -1
- package/dist/database/helpers/geometry/types.js +4 -2
- package/dist/database/helpers/index.d.ts +3 -3
- package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/cockroachdb.js +4 -0
- package/dist/database/helpers/schema/dialects/mssql.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/mssql.js +4 -0
- package/dist/database/helpers/schema/dialects/oracle.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/oracle.js +4 -0
- package/dist/database/helpers/schema/dialects/postgres.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/postgres.js +4 -0
- package/dist/database/helpers/schema/types.d.ts +5 -0
- package/dist/database/helpers/schema/types.js +3 -0
- package/dist/database/helpers/schema/utils/preprocess-bindings.d.ts +8 -0
- package/dist/database/helpers/schema/utils/preprocess-bindings.js +30 -0
- package/dist/database/index.js +6 -1
- package/dist/database/migrations/20210519A-add-system-fk-triggers.js +3 -2
- package/dist/database/migrations/20230721A-require-shares-fields.js +3 -5
- package/dist/database/migrations/20240716A-update-files-date-fields.js +3 -7
- package/dist/{utils/merge-permissions.d.ts → database/migrations/20240806A-permissions-policies.d.ts} +4 -1
- package/dist/database/migrations/20240806A-permissions-policies.js +352 -0
- package/dist/database/run-ast/lib/get-db-query.d.ts +4 -0
- package/dist/database/run-ast/lib/get-db-query.js +218 -0
- package/dist/database/run-ast/lib/parse-current-level.d.ts +7 -0
- package/dist/database/run-ast/lib/parse-current-level.js +41 -0
- package/dist/database/run-ast/run-ast.d.ts +7 -0
- package/dist/database/run-ast/run-ast.js +107 -0
- package/dist/database/{run-ast.d.ts → run-ast/types.d.ts} +3 -9
- package/dist/database/run-ast/types.js +1 -0
- package/dist/database/run-ast/utils/apply-case-when.d.ts +16 -0
- package/dist/database/run-ast/utils/apply-case-when.js +27 -0
- package/dist/database/run-ast/utils/apply-parent-filters.d.ts +3 -0
- package/dist/database/run-ast/utils/apply-parent-filters.js +55 -0
- package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +10 -0
- package/dist/database/run-ast/utils/get-column-pre-processor.js +57 -0
- package/dist/database/run-ast/utils/get-field-alias.d.ts +2 -0
- package/dist/database/run-ast/utils/get-field-alias.js +4 -0
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +5 -0
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +23 -0
- package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +3 -0
- package/dist/database/run-ast/utils/merge-with-parent-items.js +87 -0
- package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +3 -0
- package/dist/database/run-ast/utils/remove-temporary-fields.js +73 -0
- package/dist/database/run-ast/utils/with-preprocess-bindings.d.ts +2 -0
- package/dist/database/run-ast/utils/with-preprocess-bindings.js +14 -0
- package/dist/flows.js +3 -4
- package/dist/middleware/authenticate.js +2 -7
- package/dist/middleware/cache.js +1 -1
- package/dist/middleware/respond.js +1 -1
- package/dist/permissions/cache.d.ts +2 -0
- package/dist/permissions/cache.js +23 -0
- package/dist/permissions/lib/fetch-permissions.d.ts +11 -0
- package/dist/permissions/lib/fetch-permissions.js +56 -0
- package/dist/permissions/lib/fetch-policies.d.ts +14 -0
- package/dist/permissions/lib/fetch-policies.js +43 -0
- package/dist/permissions/lib/fetch-roles-tree.d.ts +3 -0
- package/dist/permissions/lib/fetch-roles-tree.js +28 -0
- package/dist/{services/permissions → permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
- package/dist/permissions/lib/with-app-minimal-permissions.js +10 -0
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +7 -0
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +56 -0
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +3 -0
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +16 -0
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +8 -0
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +24 -0
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +9 -0
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +31 -0
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +16 -0
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +27 -0
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +10 -0
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +23 -0
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +5 -0
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +7 -0
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +5 -0
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +10 -0
- package/dist/permissions/modules/fetch-global-access/types.d.ts +4 -0
- package/dist/permissions/modules/fetch-global-access/types.js +1 -0
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +4 -0
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +27 -0
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +12 -0
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +32 -0
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +4 -0
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +29 -0
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +4 -0
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +49 -0
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +3 -0
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +56 -0
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +4 -0
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +8 -0
- package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +9 -0
- package/dist/permissions/modules/process-ast/lib/inject-cases.js +93 -0
- package/dist/permissions/modules/process-ast/process-ast.d.ts +9 -0
- package/dist/permissions/modules/process-ast/process-ast.js +39 -0
- package/dist/permissions/modules/process-ast/types.d.ts +18 -0
- package/dist/permissions/modules/process-ast/types.js +1 -0
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +2 -0
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +7 -0
- package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +12 -0
- package/dist/permissions/modules/process-ast/utils/dedupe-access.js +30 -0
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +15 -0
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +60 -0
- package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +3 -0
- package/dist/permissions/modules/process-ast/utils/find-related-collection.js +9 -0
- package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +3 -0
- package/dist/permissions/modules/process-ast/utils/flatten-filter.js +34 -0
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +1 -0
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +3 -0
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +5 -0
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +7 -0
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +2 -0
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +3 -0
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +2 -0
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +3 -0
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +3 -0
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +16 -0
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +2 -0
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +12 -0
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +2 -0
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +28 -0
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +5 -0
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +12 -0
- package/dist/permissions/modules/process-payload/process-payload.d.ts +13 -0
- package/dist/permissions/modules/process-payload/process-payload.js +77 -0
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +12 -0
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +11 -0
- package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +9 -0
- package/dist/permissions/modules/validate-access/lib/validate-item-access.js +33 -0
- package/dist/permissions/modules/validate-access/validate-access.d.ts +14 -0
- package/dist/permissions/modules/validate-access/validate-access.js +28 -0
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +1 -0
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +8 -0
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +5 -0
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +10 -0
- package/dist/permissions/types.d.ts +6 -0
- package/dist/permissions/types.js +1 -0
- package/dist/permissions/utils/create-default-accountability.d.ts +2 -0
- package/dist/permissions/utils/create-default-accountability.js +11 -0
- package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +8 -0
- package/dist/permissions/utils/extract-required-dynamic-variable-context.js +27 -0
- package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +9 -0
- package/dist/permissions/utils/fetch-dynamic-variable-context.js +43 -0
- package/dist/permissions/utils/filter-policies-by-ip.d.ts +2 -0
- package/dist/permissions/utils/filter-policies-by-ip.js +15 -0
- package/dist/permissions/utils/get-unaliased-field-key.d.ts +5 -0
- package/dist/permissions/utils/get-unaliased-field-key.js +17 -0
- package/dist/permissions/utils/process-permissions.d.ts +7 -0
- package/dist/permissions/utils/process-permissions.js +9 -0
- package/dist/permissions/utils/with-cache.d.ts +10 -0
- package/dist/permissions/utils/with-cache.js +25 -0
- package/dist/server.js +17 -4
- package/dist/services/access.d.ts +10 -0
- package/dist/services/access.js +43 -0
- package/dist/services/activity.js +22 -10
- package/dist/services/assets.d.ts +2 -3
- package/dist/services/assets.js +10 -5
- package/dist/services/authentication.js +18 -18
- package/dist/services/collections.js +18 -17
- package/dist/services/fields.d.ts +0 -1
- package/dist/services/fields.js +54 -25
- package/dist/services/files.js +10 -3
- package/dist/services/graphql/index.d.ts +3 -3
- package/dist/services/graphql/index.js +126 -22
- package/dist/services/graphql/subscription.js +2 -4
- package/dist/services/import-export.d.ts +3 -1
- package/dist/services/import-export.js +67 -9
- package/dist/services/index.d.ts +3 -2
- package/dist/services/index.js +3 -2
- package/dist/services/items.js +115 -44
- package/dist/services/meta.js +60 -23
- package/dist/services/notifications.js +14 -6
- package/dist/services/payload.d.ts +9 -10
- package/dist/services/payload.js +18 -3
- package/dist/services/{permissions/index.d.ts → permissions.d.ts} +5 -7
- package/dist/services/{permissions/index.js → permissions.js} +30 -54
- package/dist/services/policies.d.ts +12 -0
- package/dist/services/policies.js +87 -0
- package/dist/services/relations.d.ts +0 -6
- package/dist/services/relations.js +27 -30
- package/dist/services/roles.d.ts +4 -12
- package/dist/services/roles.js +57 -424
- package/dist/services/shares.d.ts +0 -2
- package/dist/services/shares.js +12 -8
- package/dist/services/specifications.d.ts +2 -2
- package/dist/services/specifications.js +39 -27
- package/dist/services/users.d.ts +1 -5
- package/dist/services/users.js +78 -161
- package/dist/services/utils.js +11 -7
- package/dist/services/versions.d.ts +0 -2
- package/dist/services/versions.js +34 -10
- package/dist/telemetry/lib/get-report.js +2 -2
- package/dist/telemetry/utils/check-user-limits.d.ts +5 -0
- package/dist/telemetry/utils/check-user-limits.js +19 -0
- package/dist/types/ast.d.ts +43 -1
- package/dist/types/database.d.ts +1 -1
- package/dist/types/items.d.ts +11 -0
- package/dist/utils/apply-query.d.ts +11 -7
- package/dist/utils/apply-query.js +69 -11
- package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +19 -0
- package/dist/utils/fetch-user-count/fetch-access-lookup.js +23 -0
- package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +16 -0
- package/dist/utils/fetch-user-count/fetch-access-roles.js +37 -0
- package/dist/utils/fetch-user-count/fetch-active-users.d.ts +6 -0
- package/dist/utils/fetch-user-count/fetch-active-users.js +3 -0
- package/dist/utils/fetch-user-count/fetch-user-count.d.ts +12 -0
- package/dist/utils/fetch-user-count/fetch-user-count.js +64 -0
- package/dist/utils/fetch-user-count/get-user-count-query.d.ts +20 -0
- package/dist/utils/fetch-user-count/get-user-count-query.js +17 -0
- package/dist/utils/get-accountability-for-role.js +16 -25
- package/dist/utils/get-accountability-for-token.js +17 -16
- package/dist/utils/get-address.d.ts +5 -0
- package/dist/utils/get-address.js +13 -0
- package/dist/utils/get-cache-key.d.ts +1 -1
- package/dist/utils/get-cache-key.js +12 -1
- package/dist/utils/get-column.d.ts +2 -1
- package/dist/utils/get-column.js +1 -0
- package/dist/utils/get-service.js +5 -1
- package/dist/utils/reduce-schema.d.ts +4 -6
- package/dist/utils/reduce-schema.js +16 -32
- package/dist/utils/sanitize-schema.d.ts +1 -1
- package/dist/utils/transaction.js +28 -11
- package/dist/utils/validate-user-count-integrity.d.ts +13 -0
- package/dist/utils/validate-user-count-integrity.js +29 -0
- package/dist/websocket/authenticate.d.ts +0 -2
- package/dist/websocket/authenticate.js +0 -12
- package/dist/websocket/controllers/graphql.js +3 -7
- package/dist/websocket/controllers/hooks.js +4 -0
- package/dist/websocket/controllers/rest.js +2 -5
- package/dist/websocket/handlers/subscribe.js +0 -2
- package/dist/websocket/utils/items.d.ts +1 -1
- package/package.json +31 -30
- package/dist/database/run-ast.js +0 -458
- package/dist/middleware/check-ip.d.ts +0 -2
- package/dist/middleware/check-ip.js +0 -37
- package/dist/middleware/get-permissions.d.ts +0 -3
- package/dist/middleware/get-permissions.js +0 -10
- package/dist/services/authorization.d.ts +0 -17
- package/dist/services/authorization.js +0 -456
- package/dist/services/permissions/lib/with-app-minimal-permissions.js +0 -13
- package/dist/telemetry/utils/check-increased-user-limits.d.ts +0 -7
- package/dist/telemetry/utils/check-increased-user-limits.js +0 -25
- package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +0 -6
- package/dist/telemetry/utils/get-role-counts-by-roles.js +0 -27
- package/dist/telemetry/utils/get-role-counts-by-users.d.ts +0 -11
- package/dist/telemetry/utils/get-role-counts-by-users.js +0 -34
- package/dist/telemetry/utils/get-user-count.d.ts +0 -8
- package/dist/telemetry/utils/get-user-count.js +0 -33
- package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +0 -7
- package/dist/telemetry/utils/get-user-counts-by-roles.js +0 -35
- package/dist/utils/get-ast-from-query.d.ts +0 -13
- package/dist/utils/get-ast-from-query.js +0 -297
- package/dist/utils/get-permissions.d.ts +0 -2
- package/dist/utils/get-permissions.js +0 -150
- package/dist/utils/merge-permissions-for-share.d.ts +0 -4
- package/dist/utils/merge-permissions-for-share.js +0 -109
- package/dist/utils/merge-permissions.js +0 -95
|
@@ -3,11 +3,13 @@ import { useEnv } from '@directus/env';
|
|
|
3
3
|
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
4
4
|
import { uniq } from 'lodash-es';
|
|
5
5
|
import { useLogger } from '../logger/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { fetchRolesTree } from '../permissions/lib/fetch-roles-tree.js';
|
|
7
|
+
import { fetchGlobalAccess } from '../permissions/modules/fetch-global-access/fetch-global-access.js';
|
|
8
|
+
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
9
|
+
import { createDefaultAccountability } from '../permissions/utils/create-default-accountability.js';
|
|
7
10
|
import { isValidUuid } from '../utils/is-valid-uuid.js';
|
|
8
11
|
import { Url } from '../utils/url.js';
|
|
9
12
|
import { userName } from '../utils/user-name.js';
|
|
10
|
-
import { AuthorizationService } from './authorization.js';
|
|
11
13
|
import { ItemsService } from './items.js';
|
|
12
14
|
import { NotificationsService } from './notifications.js';
|
|
13
15
|
import { UsersService } from './users.js';
|
|
@@ -31,19 +33,29 @@ export class ActivityService extends ItemsService {
|
|
|
31
33
|
for (const mention of mentions) {
|
|
32
34
|
const userID = mention.substring(1);
|
|
33
35
|
const user = await this.usersService.readOne(userID, {
|
|
34
|
-
fields: ['id', 'first_name', 'last_name', 'email', 'role
|
|
36
|
+
fields: ['id', 'first_name', 'last_name', 'email', 'role'],
|
|
35
37
|
});
|
|
36
|
-
const
|
|
38
|
+
const roles = await fetchRolesTree(user['role'], this.knex);
|
|
39
|
+
const globalAccess = await fetchGlobalAccess({ user: user['id'], roles, ip: null }, this.knex);
|
|
40
|
+
const accountability = createDefaultAccountability({
|
|
37
41
|
user: userID,
|
|
38
42
|
role: user['role']?.id ?? null,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
};
|
|
42
|
-
accountability.permissions = await getPermissions(accountability, this.schema);
|
|
43
|
-
const authorizationService = new AuthorizationService({ schema: this.schema, accountability });
|
|
43
|
+
roles,
|
|
44
|
+
...globalAccess,
|
|
45
|
+
});
|
|
44
46
|
const usersService = new UsersService({ schema: this.schema, accountability });
|
|
45
47
|
try {
|
|
46
|
-
|
|
48
|
+
if (this.accountability) {
|
|
49
|
+
await validateAccess({
|
|
50
|
+
accountability: this.accountability,
|
|
51
|
+
action: 'read',
|
|
52
|
+
collection: data['collection'],
|
|
53
|
+
primaryKeys: [data['item']],
|
|
54
|
+
}, {
|
|
55
|
+
knex: this.knex,
|
|
56
|
+
schema: this.schema,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
47
59
|
const templateData = await usersService.readByQuery({
|
|
48
60
|
fields: ['id', 'first_name', 'last_name', 'email'],
|
|
49
61
|
filter: { id: { _in: mentions.map((mention) => mention.substring(1)) } },
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import type { Range, Stat } from '@directus/storage';
|
|
3
|
-
import type { Accountability } from '@directus/types';
|
|
3
|
+
import type { Accountability, SchemaOverview } from '@directus/types';
|
|
4
4
|
import type { Knex } from 'knex';
|
|
5
5
|
import type { Readable } from 'node:stream';
|
|
6
6
|
import type { AbstractServiceOptions, TransformationSet } from '../types/index.js';
|
|
7
|
-
import { AuthorizationService } from './authorization.js';
|
|
8
7
|
import { FilesService } from './files.js';
|
|
9
8
|
export declare class AssetsService {
|
|
10
9
|
knex: Knex;
|
|
11
10
|
accountability: Accountability | null;
|
|
12
|
-
|
|
11
|
+
schema: SchemaOverview;
|
|
13
12
|
filesService: FilesService;
|
|
14
13
|
constructor(options: AbstractServiceOptions);
|
|
15
14
|
getAsset(id: string, transformation?: TransformationSet, range?: Range): Promise<{
|
package/dist/services/assets.js
CHANGED
|
@@ -8,11 +8,11 @@ import sharp from 'sharp';
|
|
|
8
8
|
import { SUPPORTED_IMAGE_TRANSFORM_FORMATS } from '../constants.js';
|
|
9
9
|
import getDatabase from '../database/index.js';
|
|
10
10
|
import { useLogger } from '../logger/index.js';
|
|
11
|
+
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
11
12
|
import { getStorage } from '../storage/index.js';
|
|
12
13
|
import { getMilliseconds } from '../utils/get-milliseconds.js';
|
|
13
14
|
import { isValidUuid } from '../utils/is-valid-uuid.js';
|
|
14
15
|
import * as TransformationUtils from '../utils/transformations.js';
|
|
15
|
-
import { AuthorizationService } from './authorization.js';
|
|
16
16
|
import { FilesService } from './files.js';
|
|
17
17
|
import { getSharpInstance } from './files/lib/get-sharp-instance.js';
|
|
18
18
|
const env = useEnv();
|
|
@@ -20,13 +20,13 @@ const logger = useLogger();
|
|
|
20
20
|
export class AssetsService {
|
|
21
21
|
knex;
|
|
22
22
|
accountability;
|
|
23
|
-
|
|
23
|
+
schema;
|
|
24
24
|
filesService;
|
|
25
25
|
constructor(options) {
|
|
26
26
|
this.knex = options.knex || getDatabase();
|
|
27
27
|
this.accountability = options.accountability || null;
|
|
28
|
+
this.schema = options.schema;
|
|
28
29
|
this.filesService = new FilesService({ ...options, accountability: null });
|
|
29
|
-
this.authorizationService = new AuthorizationService(options);
|
|
30
30
|
}
|
|
31
31
|
async getAsset(id, transformation, range) {
|
|
32
32
|
const storage = await getStorage();
|
|
@@ -42,8 +42,13 @@ export class AssetsService {
|
|
|
42
42
|
*/
|
|
43
43
|
if (!isValidUuid(id))
|
|
44
44
|
throw new ForbiddenError();
|
|
45
|
-
if (systemPublicKeys.includes(id) === false && this.accountability
|
|
46
|
-
await
|
|
45
|
+
if (systemPublicKeys.includes(id) === false && this.accountability) {
|
|
46
|
+
await validateAccess({
|
|
47
|
+
accountability: this.accountability,
|
|
48
|
+
action: 'read',
|
|
49
|
+
collection: 'directus_files',
|
|
50
|
+
primaryKeys: [id],
|
|
51
|
+
}, { knex: this.knex, schema: this.schema });
|
|
47
52
|
}
|
|
48
53
|
const file = (await this.filesService.readOne(id, { limit: 1 }));
|
|
49
54
|
const exists = await storage.location(file.storage).exists(file.filename_disk);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { fetchRolesTree } from '../permissions/lib/fetch-roles-tree.js';
|
|
2
|
+
import { fetchGlobalAccess } from '../permissions/modules/fetch-global-access/fetch-global-access.js';
|
|
1
3
|
import { Action } from '@directus/constants';
|
|
2
4
|
import { useEnv } from '@directus/env';
|
|
3
5
|
import { InvalidCredentialsError, InvalidOtpError, ServiceUnavailableError, UserSuspendedError, } from '@directus/errors';
|
|
@@ -48,10 +50,9 @@ export class AuthenticationService {
|
|
|
48
50
|
throw err;
|
|
49
51
|
}
|
|
50
52
|
const user = await this.knex
|
|
51
|
-
.select('
|
|
52
|
-
.from('directus_users
|
|
53
|
-
.
|
|
54
|
-
.where('u.id', userId)
|
|
53
|
+
.select('id', 'first_name', 'last_name', 'email', 'password', 'status', 'role', 'tfa_secret', 'provider', 'external_identifier', 'auth_data')
|
|
54
|
+
.from('directus_users')
|
|
55
|
+
.where('id', userId)
|
|
55
56
|
.first();
|
|
56
57
|
const updatedPayload = await emitter.emitFilter('auth.login', payload, {
|
|
57
58
|
status: 'pending',
|
|
@@ -128,11 +129,13 @@ export class AuthenticationService {
|
|
|
128
129
|
throw new InvalidOtpError();
|
|
129
130
|
}
|
|
130
131
|
}
|
|
132
|
+
const roles = await fetchRolesTree(user.role, this.knex);
|
|
133
|
+
const globalAccess = await fetchGlobalAccess({ roles, user: user.id, ip: this.accountability?.ip ?? null }, this.knex);
|
|
131
134
|
const tokenPayload = {
|
|
132
135
|
id: user.id,
|
|
133
136
|
role: user.role,
|
|
134
|
-
app_access:
|
|
135
|
-
admin_access:
|
|
137
|
+
app_access: globalAccess.app,
|
|
138
|
+
admin_access: globalAccess.admin,
|
|
136
139
|
};
|
|
137
140
|
const refreshToken = nanoid(64);
|
|
138
141
|
const refreshTokenExpiration = new Date(Date.now() + getMilliseconds(env['REFRESH_TOKEN_TTL'], 0));
|
|
@@ -207,9 +210,7 @@ export class AuthenticationService {
|
|
|
207
210
|
user_provider: 'u.provider',
|
|
208
211
|
user_external_identifier: 'u.external_identifier',
|
|
209
212
|
user_auth_data: 'u.auth_data',
|
|
210
|
-
|
|
211
|
-
role_admin_access: 'r.admin_access',
|
|
212
|
-
role_app_access: 'r.app_access',
|
|
213
|
+
user_role: 'u.role',
|
|
213
214
|
share_id: 'd.id',
|
|
214
215
|
share_item: 'd.item',
|
|
215
216
|
share_role: 'd.role',
|
|
@@ -222,9 +223,6 @@ export class AuthenticationService {
|
|
|
222
223
|
.from('directus_sessions AS s')
|
|
223
224
|
.leftJoin('directus_users AS u', 's.user', 'u.id')
|
|
224
225
|
.leftJoin('directus_shares AS d', 's.share', 'd.id')
|
|
225
|
-
.leftJoin('directus_roles AS r', (join) => {
|
|
226
|
-
join.onIn('r.id', [this.knex.ref('u.role'), this.knex.ref('d.role')]);
|
|
227
|
-
})
|
|
228
226
|
.where('s.token', refreshToken)
|
|
229
227
|
.andWhere('s.expires', '>=', new Date())
|
|
230
228
|
.andWhere((subQuery) => {
|
|
@@ -248,6 +246,8 @@ export class AuthenticationService {
|
|
|
248
246
|
throw new InvalidCredentialsError();
|
|
249
247
|
}
|
|
250
248
|
}
|
|
249
|
+
const roles = await fetchRolesTree(record.user_role, this.knex);
|
|
250
|
+
const globalAccess = await fetchGlobalAccess({ user: record.user_id, roles, ip: this.accountability?.ip ?? null }, this.knex);
|
|
251
251
|
if (record.user_id) {
|
|
252
252
|
const provider = getAuthProvider(record.user_provider);
|
|
253
253
|
await provider.refresh({
|
|
@@ -260,9 +260,9 @@ export class AuthenticationService {
|
|
|
260
260
|
provider: record.user_provider,
|
|
261
261
|
external_identifier: record.user_external_identifier,
|
|
262
262
|
auth_data: record.user_auth_data,
|
|
263
|
-
role: record.
|
|
264
|
-
app_access:
|
|
265
|
-
admin_access:
|
|
263
|
+
role: record.user_role,
|
|
264
|
+
app_access: globalAccess.app,
|
|
265
|
+
admin_access: globalAccess.admin,
|
|
266
266
|
});
|
|
267
267
|
}
|
|
268
268
|
let newRefreshToken = record.session_next_token ?? nanoid(64);
|
|
@@ -270,9 +270,9 @@ export class AuthenticationService {
|
|
|
270
270
|
const refreshTokenExpiration = new Date(Date.now() + getMilliseconds(sessionDuration, 0));
|
|
271
271
|
const tokenPayload = {
|
|
272
272
|
id: record.user_id,
|
|
273
|
-
role: record.
|
|
274
|
-
app_access:
|
|
275
|
-
admin_access:
|
|
273
|
+
role: record.user_role,
|
|
274
|
+
app_access: globalAccess.app,
|
|
275
|
+
admin_access: globalAccess.admin,
|
|
276
276
|
};
|
|
277
277
|
if (options?.session) {
|
|
278
278
|
newRefreshToken = await this.updateStatefulSession(record, refreshToken, newRefreshToken, refreshTokenExpiration);
|
|
@@ -9,6 +9,8 @@ import { ALIAS_TYPES } from '../constants.js';
|
|
|
9
9
|
import { getHelpers } from '../database/helpers/index.js';
|
|
10
10
|
import getDatabase, { getSchemaInspector } from '../database/index.js';
|
|
11
11
|
import emitter from '../emitter.js';
|
|
12
|
+
import { fetchAllowedCollections } from '../permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js';
|
|
13
|
+
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
12
14
|
import { getSchema } from '../utils/get-schema.js';
|
|
13
15
|
import { shouldClearCache } from '../utils/should-clear-cache.js';
|
|
14
16
|
import { transaction } from '../utils/transaction.js';
|
|
@@ -223,11 +225,13 @@ export class CollectionsService {
|
|
|
223
225
|
...meta,
|
|
224
226
|
[item.collection]: item.group,
|
|
225
227
|
}), {});
|
|
226
|
-
let collectionsYouHavePermissionToRead =
|
|
227
|
-
.
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
.
|
|
228
|
+
let collectionsYouHavePermissionToRead = await fetchAllowedCollections({
|
|
229
|
+
accountability: this.accountability,
|
|
230
|
+
action: 'read',
|
|
231
|
+
}, {
|
|
232
|
+
knex: this.knex,
|
|
233
|
+
schema: this.schema,
|
|
234
|
+
});
|
|
231
235
|
for (const collection of collectionsYouHavePermissionToRead) {
|
|
232
236
|
const group = collectionsGroups[collection];
|
|
233
237
|
if (group)
|
|
@@ -279,18 +283,15 @@ export class CollectionsService {
|
|
|
279
283
|
* Read many collections by name
|
|
280
284
|
*/
|
|
281
285
|
async readMany(collectionKeys) {
|
|
282
|
-
if (this.accountability
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
286
|
+
if (this.accountability) {
|
|
287
|
+
await Promise.all(collectionKeys.map((collection) => validateAccess({
|
|
288
|
+
accountability: this.accountability,
|
|
289
|
+
action: 'read',
|
|
290
|
+
collection,
|
|
291
|
+
}, {
|
|
292
|
+
schema: this.schema,
|
|
293
|
+
knex: this.knex,
|
|
294
|
+
})));
|
|
294
295
|
}
|
|
295
296
|
const collections = await this.readByQuery();
|
|
296
297
|
return collections.filter(({ collection }) => collectionKeys.includes(collection));
|
|
@@ -18,7 +18,6 @@ export declare class FieldsService {
|
|
|
18
18
|
systemCache: Keyv<any>;
|
|
19
19
|
schemaCache: Keyv<any>;
|
|
20
20
|
constructor(options: AbstractServiceOptions);
|
|
21
|
-
private get hasReadAccess();
|
|
22
21
|
columnInfo(collection?: string): Promise<Column[]>;
|
|
23
22
|
columnInfo(collection: string, field: string): Promise<Column>;
|
|
24
23
|
readAll(collection?: string): Promise<Field[]>;
|
package/dist/services/fields.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DEFAULT_NUMERIC_PRECISION, DEFAULT_NUMERIC_SCALE, KNEX_TYPES, REGEX_BETWEEN_PARENS, } from '@directus/constants';
|
|
2
|
+
import { useEnv } from '@directus/env';
|
|
2
3
|
import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
|
|
3
4
|
import { createInspector } from '@directus/schema';
|
|
4
5
|
import { addFieldFlag, toArray } from '@directus/utils';
|
|
@@ -9,6 +10,9 @@ import { translateDatabaseError } from '../database/errors/translate.js';
|
|
|
9
10
|
import { getHelpers } from '../database/helpers/index.js';
|
|
10
11
|
import getDatabase, { getSchemaInspector } from '../database/index.js';
|
|
11
12
|
import emitter from '../emitter.js';
|
|
13
|
+
import { fetchPermissions } from '../permissions/lib/fetch-permissions.js';
|
|
14
|
+
import { fetchPolicies } from '../permissions/lib/fetch-policies.js';
|
|
15
|
+
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
12
16
|
import getDefaultValue from '../utils/get-default-value.js';
|
|
13
17
|
import { getSystemFieldRowsWithAuthProviders } from '../utils/get-field-system-rows.js';
|
|
14
18
|
import getLocalType from '../utils/get-local-type.js';
|
|
@@ -19,7 +23,6 @@ import { transaction } from '../utils/transaction.js';
|
|
|
19
23
|
import { ItemsService } from './items.js';
|
|
20
24
|
import { PayloadService } from './payload.js';
|
|
21
25
|
import { RelationsService } from './relations.js';
|
|
22
|
-
import { useEnv } from '@directus/env';
|
|
23
26
|
const systemFieldRows = getSystemFieldRowsWithAuthProviders();
|
|
24
27
|
const env = useEnv();
|
|
25
28
|
export class FieldsService {
|
|
@@ -46,11 +49,6 @@ export class FieldsService {
|
|
|
46
49
|
this.systemCache = systemCache;
|
|
47
50
|
this.schemaCache = localSchemaCache;
|
|
48
51
|
}
|
|
49
|
-
get hasReadAccess() {
|
|
50
|
-
return !!this.accountability?.permissions?.find((permission) => {
|
|
51
|
-
return permission.collection === 'directus_fields' && permission.action === 'read';
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
52
|
async columnInfo(collection, field) {
|
|
55
53
|
const schemaCacheIsEnabled = Boolean(env['CACHE_SCHEMA']);
|
|
56
54
|
let columnInfo = null;
|
|
@@ -73,8 +71,15 @@ export class FieldsService {
|
|
|
73
71
|
}
|
|
74
72
|
async readAll(collection) {
|
|
75
73
|
let fields;
|
|
76
|
-
if (this.accountability
|
|
77
|
-
|
|
74
|
+
if (this.accountability) {
|
|
75
|
+
await validateAccess({
|
|
76
|
+
accountability: this.accountability,
|
|
77
|
+
action: 'read',
|
|
78
|
+
collection: 'directus_fields',
|
|
79
|
+
}, {
|
|
80
|
+
schema: this.schema,
|
|
81
|
+
knex: this.knex,
|
|
82
|
+
});
|
|
78
83
|
}
|
|
79
84
|
const nonAuthorizedItemsService = new ItemsService('directus_fields', {
|
|
80
85
|
knex: this.knex,
|
|
@@ -143,12 +148,27 @@ export class FieldsService {
|
|
|
143
148
|
const result = [...columnsWithSystem, ...aliasFieldsAsField].filter((field) => knownCollections.includes(field.collection));
|
|
144
149
|
// Filter the result so we only return the fields you have read access to
|
|
145
150
|
if (this.accountability && this.accountability.admin !== true) {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
151
|
+
const policies = await fetchPolicies(this.accountability, { knex: this.knex, schema: this.schema });
|
|
152
|
+
const permissions = await fetchPermissions(collection
|
|
153
|
+
? {
|
|
154
|
+
action: 'read',
|
|
155
|
+
policies,
|
|
156
|
+
collections: [collection],
|
|
157
|
+
accountability: this.accountability,
|
|
158
|
+
}
|
|
159
|
+
: {
|
|
160
|
+
action: 'read',
|
|
161
|
+
policies,
|
|
162
|
+
accountability: this.accountability,
|
|
163
|
+
}, { knex: this.knex, schema: this.schema });
|
|
149
164
|
const allowedFieldsInCollection = {};
|
|
150
165
|
permissions.forEach((permission) => {
|
|
151
|
-
allowedFieldsInCollection[permission.collection]
|
|
166
|
+
if (!allowedFieldsInCollection[permission.collection]) {
|
|
167
|
+
allowedFieldsInCollection[permission.collection] = new Set();
|
|
168
|
+
}
|
|
169
|
+
for (const field of permission.fields ?? []) {
|
|
170
|
+
allowedFieldsInCollection[permission.collection].add(field);
|
|
171
|
+
}
|
|
152
172
|
});
|
|
153
173
|
if (collection && collection in allowedFieldsInCollection === false) {
|
|
154
174
|
throw new ForbiddenError();
|
|
@@ -157,9 +177,9 @@ export class FieldsService {
|
|
|
157
177
|
if (field.collection in allowedFieldsInCollection === false)
|
|
158
178
|
return false;
|
|
159
179
|
const allowedFields = allowedFieldsInCollection[field.collection];
|
|
160
|
-
if (allowedFields
|
|
180
|
+
if (allowedFields.has('*'))
|
|
161
181
|
return true;
|
|
162
|
-
return allowedFields.
|
|
182
|
+
return allowedFields.has(field.field);
|
|
163
183
|
});
|
|
164
184
|
}
|
|
165
185
|
// Update specific database type overrides
|
|
@@ -176,18 +196,27 @@ export class FieldsService {
|
|
|
176
196
|
}
|
|
177
197
|
async readOne(collection, field) {
|
|
178
198
|
if (this.accountability && this.accountability.admin !== true) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
199
|
+
await validateAccess({
|
|
200
|
+
accountability: this.accountability,
|
|
201
|
+
action: 'read',
|
|
202
|
+
collection,
|
|
203
|
+
}, {
|
|
204
|
+
schema: this.schema,
|
|
205
|
+
knex: this.knex,
|
|
184
206
|
});
|
|
185
|
-
|
|
207
|
+
const policies = await fetchPolicies(this.accountability, { knex: this.knex, schema: this.schema });
|
|
208
|
+
const permissions = await fetchPermissions({ action: 'read', policies, collections: [collection], accountability: this.accountability }, { knex: this.knex, schema: this.schema });
|
|
209
|
+
let hasAccess = false;
|
|
210
|
+
for (const permission of permissions) {
|
|
211
|
+
if (permission.fields) {
|
|
212
|
+
if (permission.fields.includes('*') || permission.fields.includes(field)) {
|
|
213
|
+
hasAccess = true;
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (!hasAccess) {
|
|
186
219
|
throw new ForbiddenError();
|
|
187
|
-
if (permissions.fields.includes('*') === false) {
|
|
188
|
-
const allowedFields = permissions.fields;
|
|
189
|
-
if (allowedFields.includes(field) === false)
|
|
190
|
-
throw new ForbiddenError();
|
|
191
220
|
}
|
|
192
221
|
}
|
|
193
222
|
let column = undefined;
|
package/dist/services/files.js
CHANGED
|
@@ -12,6 +12,7 @@ import url from 'url';
|
|
|
12
12
|
import { RESUMABLE_UPLOADS } from '../constants.js';
|
|
13
13
|
import emitter from '../emitter.js';
|
|
14
14
|
import { useLogger } from '../logger/index.js';
|
|
15
|
+
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
15
16
|
import { getAxios } from '../request/index.js';
|
|
16
17
|
import { getStorage } from '../storage/index.js';
|
|
17
18
|
import { extractMetadata } from './files/lib/extract-metadata.js';
|
|
@@ -157,9 +158,15 @@ export class FilesService extends ItemsService {
|
|
|
157
158
|
* Import a single file from an external URL
|
|
158
159
|
*/
|
|
159
160
|
async importOne(importURL, body) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
if (this.accountability) {
|
|
162
|
+
await validateAccess({
|
|
163
|
+
accountability: this.accountability,
|
|
164
|
+
action: 'create',
|
|
165
|
+
collection: 'directus_files',
|
|
166
|
+
}, {
|
|
167
|
+
knex: this.knex,
|
|
168
|
+
schema: this.schema,
|
|
169
|
+
});
|
|
163
170
|
}
|
|
164
171
|
let fileResponse;
|
|
165
172
|
try {
|
|
@@ -20,9 +20,9 @@ export declare class GraphQLService {
|
|
|
20
20
|
/**
|
|
21
21
|
* Generate the GraphQL schema. Pulls from the schema information generated by the get-schema util.
|
|
22
22
|
*/
|
|
23
|
-
getSchema(): GraphQLSchema
|
|
24
|
-
getSchema(type: 'schema'): GraphQLSchema
|
|
25
|
-
getSchema(type: 'sdl'): GraphQLSchema | string
|
|
23
|
+
getSchema(): Promise<GraphQLSchema>;
|
|
24
|
+
getSchema(type: 'schema'): Promise<GraphQLSchema>;
|
|
25
|
+
getSchema(type: 'sdl'): Promise<GraphQLSchema | string>;
|
|
26
26
|
/**
|
|
27
27
|
* Generic resolver that's used for every "regular" items/system query. Converts the incoming GraphQL AST / fragments into
|
|
28
28
|
* Directus' query structure which is then executed by the services.
|