@directus/api 20.0.0 → 21.0.0-rc.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 +5 -5
- package/dist/auth/drivers/ldap.js +5 -5
- package/dist/auth/drivers/local.js +4 -4
- package/dist/auth/drivers/oauth2.js +5 -5
- package/dist/auth/drivers/openid.js +3 -5
- package/dist/auth/drivers/saml.js +1 -1
- package/dist/auth.js +1 -1
- package/dist/cache.js +4 -1
- package/dist/cli/commands/bootstrap/index.js +10 -3
- package/dist/cli/commands/count/index.js +1 -1
- package/dist/cli/commands/database/install.js +1 -1
- package/dist/cli/commands/database/migrate.js +1 -1
- package/dist/cli/commands/init/index.js +9 -10
- package/dist/cli/commands/roles/create.js +1 -1
- package/dist/cli/commands/schema/apply.js +1 -1
- package/dist/cli/commands/schema/snapshot.js +1 -1
- package/dist/cli/commands/users/create.js +1 -1
- package/dist/cli/commands/users/passwd.js +1 -1
- package/dist/cli/load-extensions.js +1 -1
- package/dist/cli/utils/defaults.d.ts +4 -11
- package/dist/cli/utils/defaults.js +7 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +2 -2
- package/dist/controllers/access.d.ts +2 -0
- package/dist/controllers/access.js +148 -0
- package/dist/controllers/assets.js +1 -1
- package/dist/controllers/auth.js +6 -17
- package/dist/controllers/files.js +1 -1
- 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/schema.js +1 -1
- package/dist/controllers/tus.js +11 -23
- 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 +190 -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/index.js +3 -2
- package/dist/database/migrations/20210518A-add-foreign-key-constraints.js +1 -1
- package/dist/database/migrations/20210519A-add-system-fk-triggers.js +1 -1
- package/dist/database/migrations/20210802A-replace-groups.js +1 -1
- package/dist/database/migrations/20230721A-require-shares-fields.js +1 -1
- package/dist/database/migrations/20240710A-permissions-policies.d.ts +3 -0
- package/dist/database/migrations/20240710A-permissions-policies.js +169 -0
- package/dist/database/migrations/run.js +1 -1
- package/dist/database/run-ast/lib/get-db-query.d.ts +4 -0
- package/dist/database/run-ast/lib/get-db-query.js +208 -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 +26 -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/emitter.js +1 -1
- package/dist/extensions/lib/get-shared-deps-mapping.js +1 -1
- package/dist/extensions/lib/installation/manager.js +1 -1
- package/dist/extensions/lib/sandbox/register/call-reference.js +1 -1
- package/dist/extensions/lib/sandbox/sdk/generators/log.js +1 -1
- package/dist/extensions/lib/sync-extensions.js +1 -1
- package/dist/extensions/manager.js +1 -1
- package/dist/flows.js +4 -5
- package/dist/{logger.js → logger/index.js} +2 -8
- package/dist/logger/redact-query.d.ts +1 -0
- package/dist/logger/redact-query.js +13 -0
- package/dist/mailer.js +1 -1
- package/dist/middleware/authenticate.js +2 -7
- package/dist/middleware/cache.js +2 -2
- package/dist/middleware/error-handler.js +1 -1
- package/dist/middleware/rate-limiter-global.js +1 -1
- package/dist/middleware/respond.js +2 -2
- package/dist/operations/log/index.js +1 -1
- package/dist/operations/mail/index.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 +10 -0
- package/dist/permissions/lib/fetch-permissions.js +55 -0
- package/dist/permissions/lib/fetch-policies.d.ts +7 -0
- package/dist/permissions/lib/fetch-policies.js +28 -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 +24 -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 +50 -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/request/is-denied-ip.js +1 -1
- package/dist/server.js +1 -1
- package/dist/services/access.d.ts +10 -0
- package/dist/services/access.js +43 -0
- package/dist/services/activity.js +23 -11
- package/dist/services/assets.d.ts +2 -3
- package/dist/services/assets.js +11 -6
- 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 +53 -24
- package/dist/services/files/utils/get-metadata.js +1 -1
- package/dist/services/files.js +25 -15
- 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/graphql/utils/process-error.js +1 -1
- package/dist/services/graphql/utils/sanitize-gql-schema.js +1 -1
- package/dist/services/import-export.js +19 -5
- package/dist/services/index.d.ts +3 -2
- package/dist/services/index.js +3 -2
- package/dist/services/items.d.ts +3 -3
- package/dist/services/items.js +115 -44
- package/dist/services/mail/index.js +1 -1
- package/dist/services/meta.js +60 -23
- package/dist/services/notifications.js +15 -7
- 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 +26 -29
- package/dist/services/roles.d.ts +4 -12
- package/dist/services/roles.js +57 -424
- package/dist/services/server.js +1 -1
- package/dist/services/shares.d.ts +0 -2
- package/dist/services/shares.js +13 -9
- package/dist/services/specifications.d.ts +2 -2
- package/dist/services/specifications.js +39 -27
- package/dist/services/tus/data-store.js +3 -1
- package/dist/services/users.d.ts +1 -5
- package/dist/services/users.js +79 -162
- package/dist/services/utils.js +11 -7
- package/dist/services/versions.d.ts +0 -2
- package/dist/services/versions.js +34 -10
- package/dist/services/webhooks.js +1 -1
- package/dist/telemetry/lib/get-report.js +2 -2
- package/dist/telemetry/lib/track.js +1 -1
- 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/items.d.ts +11 -0
- package/dist/utils/apply-diff.js +1 -1
- package/dist/utils/apply-query.d.ts +4 -3
- package/dist/utils/apply-query.js +37 -8
- package/dist/utils/delete-from-require-cache.js +1 -1
- package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +17 -0
- package/dist/utils/fetch-user-count/fetch-access-lookup.js +22 -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 +57 -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-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-default-value.js +1 -1
- package/dist/utils/get-ip-from-req.js +1 -1
- package/dist/utils/get-schema.js +1 -1
- package/dist/utils/get-service.js +5 -1
- package/dist/utils/is-url-allowed.js +1 -1
- package/dist/utils/reduce-schema.d.ts +4 -6
- package/dist/utils/reduce-schema.js +16 -32
- package/dist/utils/sanitize-query.js +1 -1
- package/dist/utils/transaction.js +1 -1
- package/dist/utils/validate-env.js +1 -1
- package/dist/utils/validate-storage.js +1 -1
- 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/base.d.ts +1 -1
- package/dist/websocket/controllers/base.js +21 -17
- package/dist/websocket/controllers/graphql.js +2 -5
- package/dist/websocket/controllers/hooks.js +4 -0
- package/dist/websocket/controllers/rest.js +1 -3
- package/dist/websocket/errors.js +1 -1
- package/dist/websocket/handlers/subscribe.js +0 -2
- package/dist/websocket/utils/items.d.ts +1 -1
- package/package.json +28 -27
- package/dist/database/run-ast.js +0 -450
- 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.d.ts +0 -3
- package/dist/utils/merge-permissions.js +0 -95
- /package/dist/{logger.d.ts → logger/index.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Permission } from '@directus/types';
|
|
2
|
+
export interface RequiredPermissionContext {
|
|
3
|
+
$CURRENT_USER: Set<string>;
|
|
4
|
+
$CURRENT_ROLE: Set<string>;
|
|
5
|
+
$CURRENT_ROLES: Set<string>;
|
|
6
|
+
$CURRENT_POLICIES: Set<string>;
|
|
7
|
+
}
|
|
8
|
+
export declare function extractRequiredDynamicVariableContext(permissions: Permission[]): RequiredPermissionContext;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { deepMap } from '@directus/utils';
|
|
2
|
+
export function extractRequiredDynamicVariableContext(permissions) {
|
|
3
|
+
const permissionContext = {
|
|
4
|
+
$CURRENT_USER: new Set(),
|
|
5
|
+
$CURRENT_ROLE: new Set(),
|
|
6
|
+
$CURRENT_ROLES: new Set(),
|
|
7
|
+
$CURRENT_POLICIES: new Set(),
|
|
8
|
+
};
|
|
9
|
+
for (const permission of permissions) {
|
|
10
|
+
deepMap(permission.permissions, extractPermissionData);
|
|
11
|
+
deepMap(permission.validation, extractPermissionData);
|
|
12
|
+
deepMap(permission.presets, extractPermissionData);
|
|
13
|
+
}
|
|
14
|
+
return permissionContext;
|
|
15
|
+
function extractPermissionData(val) {
|
|
16
|
+
for (const placeholder of [
|
|
17
|
+
'$CURRENT_USER',
|
|
18
|
+
'$CURRENT_ROLE',
|
|
19
|
+
'$CURRENT_ROLES',
|
|
20
|
+
'$CURRENT_POLICIES',
|
|
21
|
+
]) {
|
|
22
|
+
if (typeof val === 'string' && val.startsWith(`${placeholder}.`)) {
|
|
23
|
+
permissionContext[placeholder].add(val.replace(`${placeholder}.`, ''));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Accountability, Permission } from '@directus/types';
|
|
2
|
+
import type { Context } from '../types.js';
|
|
3
|
+
export declare const fetchDynamicVariableContext: typeof _fetchDynamicVariableContext;
|
|
4
|
+
export interface FetchDynamicVariableContext {
|
|
5
|
+
accountability: Pick<Accountability, 'user' | 'role' | 'roles'>;
|
|
6
|
+
policies: string[];
|
|
7
|
+
permissions: Permission[];
|
|
8
|
+
}
|
|
9
|
+
export declare function _fetchDynamicVariableContext(options: FetchDynamicVariableContext, context: Context): Promise<Record<string, any>>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { extractRequiredDynamicVariableContext } from './extract-required-dynamic-variable-context.js';
|
|
2
|
+
import { withCache } from './with-cache.js';
|
|
3
|
+
export const fetchDynamicVariableContext = withCache('permission-dynamic-variables', _fetchDynamicVariableContext, ({ policies, permissions, accountability: { user, role, roles } }) => ({
|
|
4
|
+
policies,
|
|
5
|
+
permissions,
|
|
6
|
+
accountability: {
|
|
7
|
+
user,
|
|
8
|
+
role,
|
|
9
|
+
roles,
|
|
10
|
+
},
|
|
11
|
+
}));
|
|
12
|
+
export async function _fetchDynamicVariableContext(options, context) {
|
|
13
|
+
const { UsersService } = await import('../../services/users.js');
|
|
14
|
+
const { RolesService } = await import('../../services/roles.js');
|
|
15
|
+
const { PoliciesService } = await import('../../services/policies.js');
|
|
16
|
+
const contextData = {};
|
|
17
|
+
const permissionContext = extractRequiredDynamicVariableContext(options.permissions);
|
|
18
|
+
if (options.accountability.user && (permissionContext.$CURRENT_USER?.size ?? 0) > 0) {
|
|
19
|
+
const usersService = new UsersService(context);
|
|
20
|
+
contextData['$CURRENT_USER'] = await usersService.readOne(options.accountability.user, {
|
|
21
|
+
fields: Array.from(permissionContext.$CURRENT_USER),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (options.accountability.role && (permissionContext.$CURRENT_ROLE?.size ?? 0) > 0) {
|
|
25
|
+
const rolesService = new RolesService(context);
|
|
26
|
+
contextData['$CURRENT_ROLE'] = await rolesService.readOne(options.accountability.role, {
|
|
27
|
+
fields: Array.from(permissionContext.$CURRENT_ROLE),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (options.accountability.roles.length > 0 && (permissionContext.$CURRENT_ROLES?.size ?? 0) > 0) {
|
|
31
|
+
const rolesService = new RolesService(context);
|
|
32
|
+
contextData['$CURRENT_ROLES'] = await rolesService.readMany(options.accountability.roles, {
|
|
33
|
+
fields: Array.from(permissionContext.$CURRENT_ROLES),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (options.policies.length > 0 && (permissionContext.$CURRENT_POLICIES?.size ?? 0) > 0) {
|
|
37
|
+
const policiesService = new PoliciesService(context);
|
|
38
|
+
contextData['$CURRENT_POLICIES'] = await policiesService.readMany(options.policies, {
|
|
39
|
+
fields: Array.from(permissionContext.$CURRENT_POLICIES),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return contextData;
|
|
43
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ipInNetworks } from '../../utils/ip-in-networks.js';
|
|
2
|
+
export function filterPoliciesByIp(policies, ip) {
|
|
3
|
+
return policies.filter(({ policy }) => {
|
|
4
|
+
// Keep policies that don't have an ip address allow list configured
|
|
5
|
+
if (!policy.ip_access || policy.ip_access.length === 0) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
// If the client's IP address is unknown, we can't validate it against the allow list and will
|
|
9
|
+
// have to default to the more secure option of preventing access
|
|
10
|
+
if (!ip) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return ipInNetworks(ip, policy.ip_access);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FieldNode, FunctionFieldNode, NestedCollectionNode } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Derive the unaliased field key from the given AST node.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getUnaliasedFieldKey(node: NestedCollectionNode | FieldNode | FunctionFieldNode): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { parseFilterKey } from '../../utils/parse-filter-key.js';
|
|
2
|
+
/**
|
|
3
|
+
* Derive the unaliased field key from the given AST node.
|
|
4
|
+
*/
|
|
5
|
+
export function getUnaliasedFieldKey(node) {
|
|
6
|
+
switch (node.type) {
|
|
7
|
+
case 'o2m':
|
|
8
|
+
return node.relation.meta.one_field;
|
|
9
|
+
case 'a2o':
|
|
10
|
+
case 'm2o':
|
|
11
|
+
return node.relation.field;
|
|
12
|
+
case 'field':
|
|
13
|
+
case 'functionField':
|
|
14
|
+
// The field name might still include a function, so process that here as well
|
|
15
|
+
return parseFilterKey(node.name).fieldName;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Accountability, Permission } from '@directus/types';
|
|
2
|
+
export interface ProcessPermissionsOptions {
|
|
3
|
+
permissions: Permission[];
|
|
4
|
+
accountability: Pick<Accountability, 'user' | 'role' | 'roles'>;
|
|
5
|
+
permissionsContext: Record<string, any>;
|
|
6
|
+
}
|
|
7
|
+
export declare function processPermissions({ permissions, accountability, permissionsContext }: ProcessPermissionsOptions): Permission[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { parseFilter, parsePreset } from '@directus/utils';
|
|
2
|
+
export function processPermissions({ permissions, accountability, permissionsContext }) {
|
|
3
|
+
return permissions.map((permission) => {
|
|
4
|
+
permission.permissions = parseFilter(permission.permissions, accountability, permissionsContext);
|
|
5
|
+
permission.validation = parseFilter(permission.validation, accountability, permissionsContext);
|
|
6
|
+
permission.presets = parsePreset(permission.presets, accountability, permissionsContext);
|
|
7
|
+
return permission;
|
|
8
|
+
});
|
|
9
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `pick` parameter can be used to stabilize cache keys, by only using a subset of the available parameters and
|
|
3
|
+
* ensuring key order.
|
|
4
|
+
*
|
|
5
|
+
* If the `pick` function is provided, we pass the picked result to the handler, in order for TypeScript to ensure that
|
|
6
|
+
* the function only relies on the parameters that are used for generating the cache key.
|
|
7
|
+
*
|
|
8
|
+
* @NOTE only uses the first parameter for memoization
|
|
9
|
+
*/
|
|
10
|
+
export declare function withCache<F extends (arg0: Arg0, ...args: any[]) => R, R, Arg0 = Parameters<F>[0]>(namespace: string, handler: F, prepareArg?: (arg0: Arg0) => Arg0): F;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getSimpleHash } from '@directus/utils';
|
|
2
|
+
import { useCache } from '../cache.js';
|
|
3
|
+
/**
|
|
4
|
+
* The `pick` parameter can be used to stabilize cache keys, by only using a subset of the available parameters and
|
|
5
|
+
* ensuring key order.
|
|
6
|
+
*
|
|
7
|
+
* If the `pick` function is provided, we pass the picked result to the handler, in order for TypeScript to ensure that
|
|
8
|
+
* the function only relies on the parameters that are used for generating the cache key.
|
|
9
|
+
*
|
|
10
|
+
* @NOTE only uses the first parameter for memoization
|
|
11
|
+
*/
|
|
12
|
+
export function withCache(namespace, handler, prepareArg) {
|
|
13
|
+
const cache = useCache();
|
|
14
|
+
return (async (arg0, ...args) => {
|
|
15
|
+
arg0 = prepareArg ? prepareArg(arg0) : arg0;
|
|
16
|
+
const key = namespace + '-' + getSimpleHash(JSON.stringify(arg0));
|
|
17
|
+
const cached = await cache.get(key);
|
|
18
|
+
if (cached !== undefined) {
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
const res = await handler(arg0, ...args);
|
|
22
|
+
cache.set(key, res);
|
|
23
|
+
return res;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEnv } from '@directus/env';
|
|
2
2
|
import os from 'node:os';
|
|
3
|
-
import { useLogger } from '../logger.js';
|
|
3
|
+
import { useLogger } from '../logger/index.js';
|
|
4
4
|
import { ipInNetworks } from '../utils/ip-in-networks.js';
|
|
5
5
|
export function isDeniedIp(ip) {
|
|
6
6
|
const env = useEnv();
|
package/dist/server.js
CHANGED
|
@@ -10,7 +10,7 @@ import url from 'url';
|
|
|
10
10
|
import createApp from './app.js';
|
|
11
11
|
import getDatabase from './database/index.js';
|
|
12
12
|
import emitter from './emitter.js';
|
|
13
|
-
import { useLogger } from './logger.js';
|
|
13
|
+
import { useLogger } from './logger/index.js';
|
|
14
14
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
15
15
|
import { getIPFromReq } from './utils/get-ip-from-req.js';
|
|
16
16
|
import { createSubscriptionController, createWebSocketController, getSubscriptionController, getWebSocketController, } from './websocket/controllers/index.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Item, PrimaryKey } from '@directus/types';
|
|
2
|
+
import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
|
|
3
|
+
import { ItemsService } from './items.js';
|
|
4
|
+
export declare class AccessService extends ItemsService {
|
|
5
|
+
constructor(options: AbstractServiceOptions);
|
|
6
|
+
private clearCaches;
|
|
7
|
+
createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
8
|
+
updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
9
|
+
deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { clearSystemCache } from '../cache.js';
|
|
2
|
+
import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
|
|
3
|
+
import { ItemsService } from './items.js';
|
|
4
|
+
export class AccessService extends ItemsService {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super('directus_access', options);
|
|
7
|
+
}
|
|
8
|
+
async clearCaches(opts) {
|
|
9
|
+
await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
|
|
10
|
+
if (this.cache && opts?.autoPurgeCache !== false) {
|
|
11
|
+
await this.cache.clear();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async createOne(data, opts = {}) {
|
|
15
|
+
// Creating a new policy attachments affects the number of admin/app/api users.
|
|
16
|
+
// But it can only add app or admin users, so no need to check the remaining admin users.
|
|
17
|
+
opts.userIntegrityCheckFlags =
|
|
18
|
+
(opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None) | UserIntegrityCheckFlag.UserLimits;
|
|
19
|
+
opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
|
|
20
|
+
const result = await super.createOne(data, opts);
|
|
21
|
+
// A new policy has been attached to a user or a role, clear the caches
|
|
22
|
+
await this.clearCaches();
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
async updateMany(keys, data, opts = {}) {
|
|
26
|
+
// Updating policy attachments might affect the number of admin/app/api users
|
|
27
|
+
opts.userIntegrityCheckFlags = UserIntegrityCheckFlag.All;
|
|
28
|
+
opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
|
|
29
|
+
const result = await super.updateMany(keys, data, { ...opts, userIntegrityCheckFlags: UserIntegrityCheckFlag.All });
|
|
30
|
+
// Some policy attachments have been updated, clear the caches
|
|
31
|
+
await this.clearCaches();
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
async deleteMany(keys, opts = {}) {
|
|
35
|
+
// Changes here can affect the number of admin/app/api users
|
|
36
|
+
opts.userIntegrityCheckFlags = UserIntegrityCheckFlag.All;
|
|
37
|
+
opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
|
|
38
|
+
const result = await super.deleteMany(keys, opts);
|
|
39
|
+
// Some policy attachments have been deleted, clear the caches
|
|
40
|
+
await this.clearCaches();
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -2,12 +2,14 @@ import { Action } from '@directus/constants';
|
|
|
2
2
|
import { useEnv } from '@directus/env';
|
|
3
3
|
import { ErrorCode, isDirectusError } from '@directus/errors';
|
|
4
4
|
import { uniq } from 'lodash-es';
|
|
5
|
-
import { useLogger } from '../logger.js';
|
|
6
|
-
import {
|
|
5
|
+
import { useLogger } from '../logger/index.js';
|
|
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
|
@@ -7,25 +7,25 @@ import path from 'path';
|
|
|
7
7
|
import sharp from 'sharp';
|
|
8
8
|
import { SUPPORTED_IMAGE_TRANSFORM_FORMATS } from '../constants.js';
|
|
9
9
|
import getDatabase from '../database/index.js';
|
|
10
|
-
import { useLogger } from '../logger.js';
|
|
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
|
const env = useEnv();
|
|
18
18
|
const logger = useLogger();
|
|
19
19
|
export class AssetsService {
|
|
20
20
|
knex;
|
|
21
21
|
accountability;
|
|
22
|
-
|
|
22
|
+
schema;
|
|
23
23
|
filesService;
|
|
24
24
|
constructor(options) {
|
|
25
25
|
this.knex = options.knex || getDatabase();
|
|
26
26
|
this.accountability = options.accountability || null;
|
|
27
|
+
this.schema = options.schema;
|
|
27
28
|
this.filesService = new FilesService({ ...options, accountability: null });
|
|
28
|
-
this.authorizationService = new AuthorizationService(options);
|
|
29
29
|
}
|
|
30
30
|
async getAsset(id, transformation, range) {
|
|
31
31
|
const storage = await getStorage();
|
|
@@ -41,8 +41,13 @@ export class AssetsService {
|
|
|
41
41
|
*/
|
|
42
42
|
if (!isValidUuid(id))
|
|
43
43
|
throw new ForbiddenError();
|
|
44
|
-
if (systemPublicKeys.includes(id) === false && this.accountability
|
|
45
|
-
await
|
|
44
|
+
if (systemPublicKeys.includes(id) === false && this.accountability) {
|
|
45
|
+
await validateAccess({
|
|
46
|
+
accountability: this.accountability,
|
|
47
|
+
action: 'read',
|
|
48
|
+
collection: 'directus_files',
|
|
49
|
+
primaryKeys: [id],
|
|
50
|
+
}, { knex: this.knex, schema: this.schema });
|
|
46
51
|
}
|
|
47
52
|
const file = (await this.filesService.readOne(id, { limit: 1 }));
|
|
48
53
|
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));
|
|
@@ -17,7 +17,6 @@ export declare class FieldsService {
|
|
|
17
17
|
cache: Keyv<any> | null;
|
|
18
18
|
systemCache: Keyv<any>;
|
|
19
19
|
constructor(options: AbstractServiceOptions);
|
|
20
|
-
private get hasReadAccess();
|
|
21
20
|
readAll(collection?: string): Promise<Field[]>;
|
|
22
21
|
readOne(collection: string, field: string): Promise<Record<string, any>>;
|
|
23
22
|
createField(collection: string, field: Partial<Field> & {
|