@directus/api 21.0.0-rc.0 → 21.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 +5 -5
- 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.d.ts +0 -1
- package/dist/cache.js +7 -25
- 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 +1 -1
- package/dist/controllers/auth.js +16 -5
- package/dist/controllers/permissions.js +2 -14
- package/dist/controllers/roles.js +1 -22
- package/dist/controllers/tus.js +27 -13
- 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 +11 -8
- package/dist/database/migrations/20240305A-change-useragent-type.js +1 -1
- package/dist/database/migrations/20240716A-update-files-date-fields.js +33 -0
- package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
- package/dist/database/run-ast.js +458 -0
- package/dist/flows.js +4 -3
- package/dist/logger/index.js +1 -1
- 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/error-handler.d.ts +2 -2
- package/dist/middleware/error-handler.js +54 -51
- 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 +7 -15
- package/dist/services/authentication.js +18 -18
- 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 +4 -0
- package/dist/services/fields.js +53 -58
- package/dist/services/files/lib/get-sharp-instance.d.ts +2 -0
- package/dist/services/files/lib/get-sharp-instance.js +10 -0
- package/dist/services/files/utils/get-metadata.js +7 -6
- package/dist/services/files.js +8 -10
- 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/mail/index.d.ts +1 -1
- package/dist/services/mail/index.js +9 -1
- package/dist/services/meta.js +23 -60
- package/dist/services/notifications.js +6 -14
- 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 +9 -1
- package/dist/services/relations.js +56 -31
- package/dist/services/roles.d.ts +12 -4
- package/dist/services/roles.js +424 -57
- 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.js +4 -5
- package/dist/services/tus/server.d.ts +1 -1
- package/dist/services/tus/server.js +9 -2
- 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/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 +16 -39
- 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-schema.js +3 -3
- 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 +32 -16
- 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 +36 -37
- package/dist/controllers/access.d.ts +0 -2
- 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/20240710A-permissions-policies.js +0 -169
- package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
- package/dist/database/run-ast/lib/get-db-query.js +0 -208
- 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 -34
- 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/{20240710A-permissions-policies.d.ts → 20240716A-update-files-date-fields.d.ts} +0 -0
package/dist/services/payload.js
CHANGED
|
@@ -9,7 +9,6 @@ import { parse as wktToGeoJSON } from 'wellknown';
|
|
|
9
9
|
import { getHelpers } from '../database/helpers/index.js';
|
|
10
10
|
import getDatabase from '../database/index.js';
|
|
11
11
|
import { generateHash } from '../utils/generate-hash.js';
|
|
12
|
-
import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
|
|
13
12
|
/**
|
|
14
13
|
* Process a given payload for a collection to ensure the special fields (hash, uuid, date etc) are
|
|
15
14
|
* handled correctly.
|
|
@@ -318,7 +317,6 @@ export class PayloadService {
|
|
|
318
317
|
return relation.collection === this.collection;
|
|
319
318
|
});
|
|
320
319
|
const revisions = [];
|
|
321
|
-
let userIntegrityCheckFlags = UserIntegrityCheckFlag.None;
|
|
322
320
|
const nestedActionEvents = [];
|
|
323
321
|
const payload = cloneDeep(data);
|
|
324
322
|
// Only process related records that are actually in the payload
|
|
@@ -364,7 +362,6 @@ export class PayloadService {
|
|
|
364
362
|
if (Object.keys(fieldsToUpdate).length > 0) {
|
|
365
363
|
await service.updateOne(relatedPrimaryKey, relatedRecord, {
|
|
366
364
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
367
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
368
365
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
369
366
|
emitEvents: opts?.emitEvents,
|
|
370
367
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -374,7 +371,6 @@ export class PayloadService {
|
|
|
374
371
|
else {
|
|
375
372
|
relatedPrimaryKey = await service.createOne(relatedRecord, {
|
|
376
373
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
377
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
378
374
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
379
375
|
emitEvents: opts?.emitEvents,
|
|
380
376
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -383,7 +379,7 @@ export class PayloadService {
|
|
|
383
379
|
// Overwrite the nested object with just the primary key, so the parent level can be saved correctly
|
|
384
380
|
payload[relation.field] = relatedPrimaryKey;
|
|
385
381
|
}
|
|
386
|
-
return { payload, revisions, nestedActionEvents
|
|
382
|
+
return { payload, revisions, nestedActionEvents };
|
|
387
383
|
}
|
|
388
384
|
/**
|
|
389
385
|
* Save/update all nested related m2o items inside the payload
|
|
@@ -392,7 +388,6 @@ export class PayloadService {
|
|
|
392
388
|
const payload = cloneDeep(data);
|
|
393
389
|
// All the revisions saved on this level
|
|
394
390
|
const revisions = [];
|
|
395
|
-
let userIntegrityCheckFlags = UserIntegrityCheckFlag.None;
|
|
396
391
|
const nestedActionEvents = [];
|
|
397
392
|
// Many to one relations that exist on the current collection
|
|
398
393
|
const relations = this.schema.relations.filter((relation) => {
|
|
@@ -429,7 +424,6 @@ export class PayloadService {
|
|
|
429
424
|
if (Object.keys(fieldsToUpdate).length > 0) {
|
|
430
425
|
await service.updateOne(relatedPrimaryKey, relatedRecord, {
|
|
431
426
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
432
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
433
427
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
434
428
|
emitEvents: opts?.emitEvents,
|
|
435
429
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -439,7 +433,6 @@ export class PayloadService {
|
|
|
439
433
|
else {
|
|
440
434
|
relatedPrimaryKey = await service.createOne(relatedRecord, {
|
|
441
435
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
442
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
443
436
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
444
437
|
emitEvents: opts?.emitEvents,
|
|
445
438
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -448,14 +441,13 @@ export class PayloadService {
|
|
|
448
441
|
// Overwrite the nested object with just the primary key, so the parent level can be saved correctly
|
|
449
442
|
payload[relation.field] = relatedPrimaryKey;
|
|
450
443
|
}
|
|
451
|
-
return { payload, revisions, nestedActionEvents
|
|
444
|
+
return { payload, revisions, nestedActionEvents };
|
|
452
445
|
}
|
|
453
446
|
/**
|
|
454
447
|
* Recursively save/update all nested related o2m items
|
|
455
448
|
*/
|
|
456
449
|
async processO2M(data, parent, opts) {
|
|
457
450
|
const revisions = [];
|
|
458
|
-
let userIntegrityCheckFlags = UserIntegrityCheckFlag.None;
|
|
459
451
|
const nestedActionEvents = [];
|
|
460
452
|
const relations = this.schema.relations.filter((relation) => {
|
|
461
453
|
return relation.related_collection === this.collection;
|
|
@@ -524,7 +516,6 @@ export class PayloadService {
|
|
|
524
516
|
}
|
|
525
517
|
savedPrimaryKeys.push(...(await service.upsertMany(recordsToUpsert, {
|
|
526
518
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
527
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
528
519
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
529
520
|
emitEvents: opts?.emitEvents,
|
|
530
521
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -549,7 +540,6 @@ export class PayloadService {
|
|
|
549
540
|
if (relation.meta.one_deselect_action === 'delete') {
|
|
550
541
|
// There's no revision for a deletion
|
|
551
542
|
await service.deleteByQuery(query, {
|
|
552
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
553
543
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
554
544
|
emitEvents: opts?.emitEvents,
|
|
555
545
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -558,7 +548,6 @@ export class PayloadService {
|
|
|
558
548
|
else {
|
|
559
549
|
await service.updateByQuery(query, { [relation.field]: null }, {
|
|
560
550
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
561
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
562
551
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
563
552
|
emitEvents: opts?.emitEvents,
|
|
564
553
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -601,7 +590,6 @@ export class PayloadService {
|
|
|
601
590
|
}
|
|
602
591
|
await service.createMany(createPayload, {
|
|
603
592
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
604
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
605
593
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
606
594
|
emitEvents: opts?.emitEvents,
|
|
607
595
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -615,7 +603,6 @@ export class PayloadService {
|
|
|
615
603
|
[relation.field]: parent || payload[currentPrimaryKeyField],
|
|
616
604
|
}, {
|
|
617
605
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
618
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
619
606
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
620
607
|
emitEvents: opts?.emitEvents,
|
|
621
608
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -641,7 +628,6 @@ export class PayloadService {
|
|
|
641
628
|
};
|
|
642
629
|
if (relation.meta.one_deselect_action === 'delete') {
|
|
643
630
|
await service.deleteByQuery(query, {
|
|
644
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
645
631
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
646
632
|
emitEvents: opts?.emitEvents,
|
|
647
633
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -650,7 +636,6 @@ export class PayloadService {
|
|
|
650
636
|
else {
|
|
651
637
|
await service.updateByQuery(query, { [relation.field]: null }, {
|
|
652
638
|
onRevisionCreate: (pk) => revisions.push(pk),
|
|
653
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
654
639
|
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
655
640
|
emitEvents: opts?.emitEvents,
|
|
656
641
|
mutationTracker: opts?.mutationTracker,
|
|
@@ -659,7 +644,7 @@ export class PayloadService {
|
|
|
659
644
|
}
|
|
660
645
|
}
|
|
661
646
|
}
|
|
662
|
-
return { revisions, nestedActionEvents
|
|
647
|
+
return { revisions, nestedActionEvents };
|
|
663
648
|
}
|
|
664
649
|
/**
|
|
665
650
|
* Transforms the input partial payload to match the output structure, to have consistency
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type { Item, ItemPermissions, PrimaryKey, Query } from '@directus/types';
|
|
2
|
-
import type
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
1
|
+
import type { Item, ItemPermissions, PermissionsAction, PrimaryKey, Query } from '@directus/types';
|
|
2
|
+
import type Keyv from 'keyv';
|
|
3
|
+
import type { AbstractServiceOptions, MutationOptions } from '../../types/index.js';
|
|
4
|
+
import type { QueryOptions } from '../items.js';
|
|
5
|
+
import { ItemsService } from '../items.js';
|
|
5
6
|
export declare class PermissionsService extends ItemsService {
|
|
7
|
+
systemCache: Keyv<any>;
|
|
6
8
|
constructor(options: AbstractServiceOptions);
|
|
7
|
-
|
|
9
|
+
getAllowedFields(action: PermissionsAction, collection?: string): Record<string, string[]>;
|
|
8
10
|
readByQuery(query: Query, opts?: QueryOptions): Promise<Partial<Item>[]>;
|
|
9
11
|
createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
10
12
|
createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import { ForbiddenError } from '@directus/errors';
|
|
2
|
-
import { clearSystemCache } from '
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { clearSystemCache, getCache } from '../../cache.js';
|
|
3
|
+
import { AuthorizationService } from '../authorization.js';
|
|
4
|
+
import { ItemsService } from '../items.js';
|
|
5
|
+
import { withAppMinimalPermissions } from './lib/with-app-minimal-permissions.js';
|
|
6
6
|
export class PermissionsService extends ItemsService {
|
|
7
|
+
systemCache;
|
|
7
8
|
constructor(options) {
|
|
8
9
|
super('directus_permissions', options);
|
|
10
|
+
const { systemCache } = getCache();
|
|
11
|
+
this.systemCache = systemCache;
|
|
9
12
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
getAllowedFields(action, collection) {
|
|
14
|
+
const results = this.accountability?.permissions?.filter((permission) => {
|
|
15
|
+
let matchesCollection = true;
|
|
16
|
+
if (collection) {
|
|
17
|
+
matchesCollection = permission.collection === collection;
|
|
18
|
+
}
|
|
19
|
+
const matchesAction = permission.action === action;
|
|
20
|
+
return collection ? matchesCollection && matchesAction : matchesAction;
|
|
21
|
+
}) ?? [];
|
|
22
|
+
const fieldsPerCollection = {};
|
|
23
|
+
for (const result of results) {
|
|
24
|
+
const { collection, fields } = result;
|
|
25
|
+
if (!fieldsPerCollection[collection])
|
|
26
|
+
fieldsPerCollection[collection] = [];
|
|
27
|
+
fieldsPerCollection[collection].push(...(fields ?? []));
|
|
14
28
|
}
|
|
29
|
+
return fieldsPerCollection;
|
|
15
30
|
}
|
|
16
31
|
async readByQuery(query, opts) {
|
|
17
32
|
const result = (await super.readByQuery(query, opts));
|
|
@@ -19,32 +34,50 @@ export class PermissionsService extends ItemsService {
|
|
|
19
34
|
}
|
|
20
35
|
async createOne(data, opts) {
|
|
21
36
|
const res = await super.createOne(data, opts);
|
|
22
|
-
await
|
|
37
|
+
await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
|
|
38
|
+
if (this.cache && opts?.autoPurgeCache !== false) {
|
|
39
|
+
await this.cache.clear();
|
|
40
|
+
}
|
|
23
41
|
return res;
|
|
24
42
|
}
|
|
25
43
|
async createMany(data, opts) {
|
|
26
44
|
const res = await super.createMany(data, opts);
|
|
27
|
-
await
|
|
45
|
+
await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
|
|
46
|
+
if (this.cache && opts?.autoPurgeCache !== false) {
|
|
47
|
+
await this.cache.clear();
|
|
48
|
+
}
|
|
28
49
|
return res;
|
|
29
50
|
}
|
|
30
51
|
async updateBatch(data, opts) {
|
|
31
52
|
const res = await super.updateBatch(data, opts);
|
|
32
|
-
await
|
|
53
|
+
await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
|
|
54
|
+
if (this.cache && opts?.autoPurgeCache !== false) {
|
|
55
|
+
await this.cache.clear();
|
|
56
|
+
}
|
|
33
57
|
return res;
|
|
34
58
|
}
|
|
35
59
|
async updateMany(keys, data, opts) {
|
|
36
60
|
const res = await super.updateMany(keys, data, opts);
|
|
37
|
-
await
|
|
61
|
+
await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
|
|
62
|
+
if (this.cache && opts?.autoPurgeCache !== false) {
|
|
63
|
+
await this.cache.clear();
|
|
64
|
+
}
|
|
38
65
|
return res;
|
|
39
66
|
}
|
|
40
67
|
async upsertMany(payloads, opts) {
|
|
41
68
|
const res = await super.upsertMany(payloads, opts);
|
|
42
|
-
await
|
|
69
|
+
await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
|
|
70
|
+
if (this.cache && opts?.autoPurgeCache !== false) {
|
|
71
|
+
await this.cache.clear();
|
|
72
|
+
}
|
|
43
73
|
return res;
|
|
44
74
|
}
|
|
45
75
|
async deleteMany(keys, opts) {
|
|
46
76
|
const res = await super.deleteMany(keys, opts);
|
|
47
|
-
await
|
|
77
|
+
await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
|
|
78
|
+
if (this.cache && opts?.autoPurgeCache !== false) {
|
|
79
|
+
await this.cache.clear();
|
|
80
|
+
}
|
|
48
81
|
return res;
|
|
49
82
|
}
|
|
50
83
|
async getItemPermissions(collection, primaryKey) {
|
|
@@ -82,25 +115,16 @@ export class PermissionsService extends ItemsService {
|
|
|
82
115
|
updateAction = 'create';
|
|
83
116
|
}
|
|
84
117
|
}
|
|
118
|
+
const authorizationService = new AuthorizationService({
|
|
119
|
+
knex: this.knex,
|
|
120
|
+
accountability: this.accountability,
|
|
121
|
+
schema: this.schema,
|
|
122
|
+
});
|
|
85
123
|
await Promise.all(Object.keys(itemPermissions).map((key) => {
|
|
86
124
|
const action = key;
|
|
87
125
|
const checkAction = action === 'update' ? updateAction : action;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return Promise.resolve();
|
|
91
|
-
}
|
|
92
|
-
const opts = {
|
|
93
|
-
accountability: this.accountability,
|
|
94
|
-
action: checkAction,
|
|
95
|
-
collection,
|
|
96
|
-
};
|
|
97
|
-
if (primaryKey) {
|
|
98
|
-
opts.primaryKeys = [primaryKey];
|
|
99
|
-
}
|
|
100
|
-
return validateAccess(opts, {
|
|
101
|
-
schema: this.schema,
|
|
102
|
-
knex: this.knex,
|
|
103
|
-
})
|
|
126
|
+
return authorizationService
|
|
127
|
+
.checkAccess(checkAction, collection, primaryKey)
|
|
104
128
|
.then(() => (itemPermissions[action].access = true))
|
|
105
129
|
.catch(() => { });
|
|
106
130
|
}));
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Accountability, Permission, Query } from '@directus/types';
|
|
2
|
-
export declare function withAppMinimalPermissions(accountability:
|
|
2
|
+
export declare function withAppMinimalPermissions(accountability: Accountability | null, permissions: Permission[], filter: Query['filter']): Permission[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { appAccessMinimalPermissions } from '@directus/system-data';
|
|
2
|
+
import { filterItems } from '../../../utils/filter-items.js';
|
|
3
|
+
import { mergePermissions } from '../../../utils/merge-permissions.js';
|
|
4
|
+
export function withAppMinimalPermissions(accountability, permissions, filter) {
|
|
5
|
+
if (accountability?.app === true) {
|
|
6
|
+
const filteredAppMinimalPermissions = filterItems(appAccessMinimalPermissions.map((permission) => ({
|
|
7
|
+
...permission,
|
|
8
|
+
role: accountability.role,
|
|
9
|
+
})), filter);
|
|
10
|
+
return mergePermissions('or', permissions, filteredAppMinimalPermissions);
|
|
11
|
+
}
|
|
12
|
+
return permissions;
|
|
13
|
+
}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import type { SchemaInspector } from '@directus/schema';
|
|
1
|
+
import type { ForeignKey, SchemaInspector } from '@directus/schema';
|
|
2
2
|
import type { Accountability, Relation, RelationMeta, SchemaOverview } from '@directus/types';
|
|
3
3
|
import type Keyv from 'keyv';
|
|
4
4
|
import type { Knex } from 'knex';
|
|
5
5
|
import type { Helpers } from '../database/helpers/index.js';
|
|
6
6
|
import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
|
|
7
7
|
import { ItemsService, type QueryOptions } from './items.js';
|
|
8
|
+
import { PermissionsService } from './permissions/index.js';
|
|
8
9
|
export declare class RelationsService {
|
|
9
10
|
knex: Knex;
|
|
11
|
+
permissionsService: PermissionsService;
|
|
10
12
|
schemaInspector: SchemaInspector;
|
|
11
13
|
accountability: Accountability | null;
|
|
12
14
|
schema: SchemaOverview;
|
|
13
15
|
relationsItemService: ItemsService<RelationMeta>;
|
|
14
16
|
systemCache: Keyv<any>;
|
|
17
|
+
schemaCache: Keyv<any>;
|
|
15
18
|
helpers: Helpers;
|
|
16
19
|
constructor(options: AbstractServiceOptions);
|
|
20
|
+
foreignKeys(collection?: string): Promise<ForeignKey[]>;
|
|
17
21
|
readAll(collection?: string, opts?: QueryOptions): Promise<Relation[]>;
|
|
18
22
|
readOne(collection: string, field: string): Promise<Relation>;
|
|
19
23
|
/**
|
|
@@ -30,6 +34,10 @@ export declare class RelationsService {
|
|
|
30
34
|
* Delete an existing relationship
|
|
31
35
|
*/
|
|
32
36
|
deleteOne(collection: string, field: string, opts?: MutationOptions): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Whether or not the current user has read access to relations
|
|
39
|
+
*/
|
|
40
|
+
private get hasReadAccess();
|
|
33
41
|
/**
|
|
34
42
|
* Combine raw schema foreign key information with Directus relations meta rows to form final
|
|
35
43
|
* Relation objects
|
|
@@ -2,27 +2,30 @@ import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
|
|
|
2
2
|
import { createInspector } from '@directus/schema';
|
|
3
3
|
import { systemRelationRows } from '@directus/system-data';
|
|
4
4
|
import { toArray } from '@directus/utils';
|
|
5
|
-
import { clearSystemCache, getCache } from '../cache.js';
|
|
5
|
+
import { clearSystemCache, getCache, getCacheValue, setCacheValue } from '../cache.js';
|
|
6
6
|
import { getHelpers } from '../database/helpers/index.js';
|
|
7
7
|
import getDatabase, { getSchemaInspector } from '../database/index.js';
|
|
8
8
|
import emitter from '../emitter.js';
|
|
9
|
-
import { fetchAllowedFieldMap } from '../permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js';
|
|
10
|
-
import { fetchAllowedFields } from '../permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js';
|
|
11
|
-
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
12
9
|
import { getDefaultIndexName } from '../utils/get-default-index-name.js';
|
|
13
10
|
import { getSchema } from '../utils/get-schema.js';
|
|
14
11
|
import { transaction } from '../utils/transaction.js';
|
|
15
12
|
import { ItemsService } from './items.js';
|
|
13
|
+
import { PermissionsService } from './permissions/index.js';
|
|
14
|
+
import { useEnv } from '@directus/env';
|
|
15
|
+
const env = useEnv();
|
|
16
16
|
export class RelationsService {
|
|
17
17
|
knex;
|
|
18
|
+
permissionsService;
|
|
18
19
|
schemaInspector;
|
|
19
20
|
accountability;
|
|
20
21
|
schema;
|
|
21
22
|
relationsItemService;
|
|
22
23
|
systemCache;
|
|
24
|
+
schemaCache;
|
|
23
25
|
helpers;
|
|
24
26
|
constructor(options) {
|
|
25
27
|
this.knex = options.knex || getDatabase();
|
|
28
|
+
this.permissionsService = new PermissionsService(options);
|
|
26
29
|
this.schemaInspector = options.knex ? createInspector(options.knex) : getSchemaInspector();
|
|
27
30
|
this.schema = options.schema;
|
|
28
31
|
this.accountability = options.accountability || null;
|
|
@@ -33,19 +36,31 @@ export class RelationsService {
|
|
|
33
36
|
// allowed to extract the relations regardless of permissions to directus_relations. This
|
|
34
37
|
// happens in `filterForbidden` down below
|
|
35
38
|
});
|
|
36
|
-
|
|
39
|
+
const cache = getCache();
|
|
40
|
+
this.systemCache = cache.systemCache;
|
|
41
|
+
this.schemaCache = cache.localSchemaCache;
|
|
37
42
|
this.helpers = getHelpers(this.knex);
|
|
38
43
|
}
|
|
44
|
+
async foreignKeys(collection) {
|
|
45
|
+
const schemaCacheIsEnabled = Boolean(env['CACHE_SCHEMA']);
|
|
46
|
+
let foreignKeys = null;
|
|
47
|
+
if (schemaCacheIsEnabled) {
|
|
48
|
+
foreignKeys = await getCacheValue(this.schemaCache, 'foreignKeys');
|
|
49
|
+
}
|
|
50
|
+
if (!foreignKeys) {
|
|
51
|
+
foreignKeys = await this.schemaInspector.foreignKeys();
|
|
52
|
+
if (schemaCacheIsEnabled) {
|
|
53
|
+
setCacheValue(this.schemaCache, 'foreignKeys', foreignKeys);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (collection) {
|
|
57
|
+
return foreignKeys.filter((row) => row.table === collection);
|
|
58
|
+
}
|
|
59
|
+
return foreignKeys;
|
|
60
|
+
}
|
|
39
61
|
async readAll(collection, opts) {
|
|
40
|
-
if (this.accountability) {
|
|
41
|
-
|
|
42
|
-
accountability: this.accountability,
|
|
43
|
-
action: 'read',
|
|
44
|
-
collection: 'directus_relations',
|
|
45
|
-
}, {
|
|
46
|
-
knex: this.knex,
|
|
47
|
-
schema: this.schema,
|
|
48
|
-
});
|
|
62
|
+
if (this.accountability && this.accountability.admin !== true && this.hasReadAccess === false) {
|
|
63
|
+
throw new ForbiddenError();
|
|
49
64
|
}
|
|
50
65
|
const metaReadQuery = {
|
|
51
66
|
limit: -1,
|
|
@@ -65,23 +80,24 @@ export class RelationsService {
|
|
|
65
80
|
return true;
|
|
66
81
|
return metaRow.many_collection === collection;
|
|
67
82
|
});
|
|
68
|
-
const schemaRows = await this.
|
|
83
|
+
const schemaRows = await this.foreignKeys(collection);
|
|
69
84
|
const results = this.stitchRelations(metaRows, schemaRows);
|
|
70
85
|
return await this.filterForbidden(results);
|
|
71
86
|
}
|
|
72
87
|
async readOne(collection, field) {
|
|
73
88
|
if (this.accountability && this.accountability.admin !== true) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
schema: this.schema,
|
|
80
|
-
knex: this.knex,
|
|
89
|
+
if (this.hasReadAccess === false) {
|
|
90
|
+
throw new ForbiddenError();
|
|
91
|
+
}
|
|
92
|
+
const permissions = this.accountability.permissions?.find((permission) => {
|
|
93
|
+
return permission.action === 'read' && permission.collection === collection;
|
|
81
94
|
});
|
|
82
|
-
|
|
83
|
-
if (allowedFields.includes('*') === false && allowedFields.includes(field) === false) {
|
|
95
|
+
if (!permissions || !permissions.fields)
|
|
84
96
|
throw new ForbiddenError();
|
|
97
|
+
if (permissions.fields.includes('*') === false) {
|
|
98
|
+
const allowedFields = permissions.fields;
|
|
99
|
+
if (allowedFields.includes(field) === false)
|
|
100
|
+
throw new ForbiddenError();
|
|
85
101
|
}
|
|
86
102
|
}
|
|
87
103
|
const metaRow = await this.relationsItemService.readByQuery({
|
|
@@ -101,7 +117,7 @@ export class RelationsService {
|
|
|
101
117
|
],
|
|
102
118
|
},
|
|
103
119
|
});
|
|
104
|
-
const schemaRow = (await this.
|
|
120
|
+
const schemaRow = (await this.foreignKeys(collection)).find((foreignKey) => foreignKey.column === field);
|
|
105
121
|
const stitched = this.stitchRelations(metaRow, schemaRow ? [schemaRow] : []);
|
|
106
122
|
const results = await this.filterForbidden(stitched);
|
|
107
123
|
if (results.length === 0) {
|
|
@@ -316,7 +332,7 @@ export class RelationsService {
|
|
|
316
332
|
const nestedActionEvents = [];
|
|
317
333
|
try {
|
|
318
334
|
await transaction(this.knex, async (trx) => {
|
|
319
|
-
const existingConstraints = await this.
|
|
335
|
+
const existingConstraints = await this.foreignKeys();
|
|
320
336
|
const constraintNames = existingConstraints.map((key) => key.constraint_name);
|
|
321
337
|
if (existingRelation.schema?.constraint_name &&
|
|
322
338
|
constraintNames.includes(existingRelation.schema.constraint_name)) {
|
|
@@ -363,6 +379,14 @@ export class RelationsService {
|
|
|
363
379
|
}
|
|
364
380
|
}
|
|
365
381
|
}
|
|
382
|
+
/**
|
|
383
|
+
* Whether or not the current user has read access to relations
|
|
384
|
+
*/
|
|
385
|
+
get hasReadAccess() {
|
|
386
|
+
return !!this.accountability?.permissions?.find((permission) => {
|
|
387
|
+
return permission.collection === 'directus_relations' && permission.action === 'read';
|
|
388
|
+
});
|
|
389
|
+
}
|
|
366
390
|
/**
|
|
367
391
|
* Combine raw schema foreign key information with Directus relations meta rows to form final
|
|
368
392
|
* Relation objects
|
|
@@ -411,11 +435,12 @@ export class RelationsService {
|
|
|
411
435
|
async filterForbidden(relations) {
|
|
412
436
|
if (this.accountability === null || this.accountability?.admin === true)
|
|
413
437
|
return relations;
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
action
|
|
417
|
-
}
|
|
418
|
-
|
|
438
|
+
const allowedCollections = this.accountability.permissions
|
|
439
|
+
?.filter((permission) => {
|
|
440
|
+
return permission.action === 'read';
|
|
441
|
+
})
|
|
442
|
+
.map(({ collection }) => collection) ?? [];
|
|
443
|
+
const allowedFields = this.permissionsService.getAllowedFields('read');
|
|
419
444
|
relations = toArray(relations);
|
|
420
445
|
return relations.filter((relation) => {
|
|
421
446
|
let collectionsAllowed = true;
|
package/dist/services/roles.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import type { Item, PrimaryKey } from '@directus/types';
|
|
1
|
+
import type { Item, PrimaryKey, Query } from '@directus/types';
|
|
2
2
|
import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
|
|
3
3
|
import { ItemsService } from './items.js';
|
|
4
4
|
export declare class RolesService extends ItemsService {
|
|
5
5
|
constructor(options: AbstractServiceOptions);
|
|
6
|
+
private checkForOtherAdminRoles;
|
|
7
|
+
private checkForOtherAdminUsers;
|
|
8
|
+
private isIpAccessValid;
|
|
9
|
+
private assertValidIpAccess;
|
|
10
|
+
private getRoleAccessType;
|
|
11
|
+
createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
12
|
+
createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
13
|
+
updateOne(key: PrimaryKey, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
14
|
+
updateBatch(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
6
15
|
updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
private clearCaches;
|
|
16
|
+
updateByQuery(query: Query, data: Partial<Item>, opts?: MutationOptions | undefined): Promise<PrimaryKey[]>;
|
|
17
|
+
deleteMany(keys: PrimaryKey[]): Promise<PrimaryKey[]>;
|
|
10
18
|
}
|