@directus/api 20.0.0-rc.0 → 20.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +9 -4
- package/dist/auth/drivers/ldap.js +4 -4
- package/dist/auth/drivers/local.js +4 -4
- package/dist/auth/drivers/oauth2.js +4 -4
- package/dist/auth/drivers/openid.js +4 -2
- package/dist/cache.js +0 -3
- package/dist/cli/commands/bootstrap/index.js +2 -8
- package/dist/cli/commands/init/index.js +10 -9
- package/dist/cli/utils/defaults.d.ts +11 -4
- package/dist/cli/utils/defaults.js +1 -7
- package/dist/constants.d.ts +9 -1
- package/dist/constants.js +10 -0
- package/dist/controllers/auth.js +16 -5
- package/dist/controllers/permissions.js +2 -14
- package/dist/controllers/roles.js +1 -22
- package/dist/controllers/{access.d.ts → tus.d.ts} +1 -0
- package/dist/controllers/tus.js +72 -0
- package/dist/controllers/users.js +55 -0
- package/dist/database/helpers/fn/types.d.ts +1 -2
- package/dist/database/helpers/fn/types.js +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.js +2 -4
- package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.js +3 -5
- package/dist/database/helpers/geometry/types.d.ts +1 -1
- package/dist/database/helpers/geometry/types.js +2 -4
- package/dist/database/index.js +1 -2
- package/dist/database/migrations/20240701A-add-tus-data.js +12 -0
- package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
- package/dist/database/run-ast.js +450 -0
- package/dist/flows.js +4 -3
- package/dist/middleware/authenticate.js +7 -2
- package/dist/middleware/cache.js +1 -1
- package/dist/middleware/check-ip.d.ts +2 -0
- package/dist/middleware/check-ip.js +37 -0
- package/dist/middleware/get-permissions.d.ts +3 -0
- package/dist/middleware/get-permissions.js +10 -0
- package/dist/middleware/respond.js +1 -1
- package/dist/services/activity.js +10 -22
- package/dist/services/assets.d.ts +3 -2
- package/dist/services/assets.js +5 -10
- package/dist/services/authentication.js +26 -32
- package/dist/services/authorization.d.ts +17 -0
- package/dist/services/authorization.js +456 -0
- package/dist/services/collections.js +17 -18
- package/dist/services/fields.d.ts +1 -0
- package/dist/services/fields.js +24 -53
- package/dist/services/files/lib/extract-metadata.d.ts +3 -0
- package/dist/services/files/lib/extract-metadata.js +32 -0
- package/dist/services/files/utils/get-metadata.d.ts +5 -0
- package/dist/services/files/utils/get-metadata.js +107 -0
- package/dist/services/files.d.ts +4 -6
- package/dist/services/files.js +24 -140
- package/dist/services/graphql/index.d.ts +3 -3
- package/dist/services/graphql/index.js +22 -126
- package/dist/services/graphql/subscription.js +4 -2
- package/dist/services/import-export.js +4 -18
- package/dist/services/index.d.ts +2 -3
- package/dist/services/index.js +2 -3
- package/dist/services/items.js +44 -115
- package/dist/services/meta.js +23 -60
- package/dist/services/payload.d.ts +10 -9
- package/dist/services/payload.js +3 -18
- package/dist/services/{permissions.d.ts → permissions/index.d.ts} +7 -5
- package/dist/services/{permissions.js → permissions/index.js} +54 -30
- package/dist/{permissions → services/permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
- package/dist/services/permissions/lib/with-app-minimal-permissions.js +13 -0
- package/dist/services/relations.d.ts +6 -0
- package/dist/services/relations.js +29 -26
- package/dist/services/roles.d.ts +12 -4
- package/dist/services/roles.js +424 -57
- package/dist/services/server.js +6 -0
- package/dist/services/shares.d.ts +2 -0
- package/dist/services/shares.js +8 -12
- package/dist/services/specifications.d.ts +2 -2
- package/dist/services/specifications.js +27 -39
- package/dist/services/tus/data-store.d.ts +36 -0
- package/dist/services/tus/data-store.js +214 -0
- package/dist/services/tus/index.d.ts +2 -0
- package/dist/services/tus/index.js +2 -0
- package/dist/services/tus/lockers.d.ts +36 -0
- package/dist/services/tus/lockers.js +83 -0
- package/dist/services/tus/server.d.ts +8 -0
- package/dist/services/tus/server.js +80 -0
- package/dist/services/tus/utils/wait-timeout.d.ts +1 -0
- package/dist/services/tus/utils/wait-timeout.js +13 -0
- package/dist/services/users.d.ts +5 -1
- package/dist/services/users.js +161 -78
- package/dist/services/utils.js +7 -11
- package/dist/services/versions.d.ts +2 -0
- package/dist/services/versions.js +10 -34
- package/dist/storage/register-locations.js +5 -1
- package/dist/telemetry/lib/get-report.js +2 -2
- package/dist/telemetry/utils/check-increased-user-limits.d.ts +7 -0
- package/dist/telemetry/utils/check-increased-user-limits.js +25 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +6 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.js +27 -0
- package/dist/telemetry/utils/get-role-counts-by-users.d.ts +11 -0
- package/dist/telemetry/utils/get-role-counts-by-users.js +34 -0
- package/dist/telemetry/utils/get-user-count.d.ts +8 -0
- package/dist/telemetry/utils/get-user-count.js +33 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +7 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.js +35 -0
- package/dist/types/ast.d.ts +1 -43
- package/dist/types/items.d.ts +0 -11
- package/dist/utils/apply-query.d.ts +3 -4
- package/dist/utils/apply-query.js +8 -37
- package/dist/utils/get-accountability-for-role.js +25 -16
- package/dist/utils/get-accountability-for-token.js +16 -17
- package/dist/utils/get-ast-from-query.d.ts +13 -0
- package/dist/utils/get-ast-from-query.js +297 -0
- package/dist/utils/get-cache-key.d.ts +1 -1
- package/dist/utils/get-cache-key.js +1 -12
- package/dist/utils/get-column.d.ts +1 -2
- package/dist/utils/get-column.js +0 -1
- package/dist/utils/get-permissions.d.ts +2 -0
- package/dist/utils/get-permissions.js +150 -0
- package/dist/utils/get-service.js +1 -5
- package/dist/utils/merge-permissions-for-share.d.ts +4 -0
- package/dist/utils/merge-permissions-for-share.js +109 -0
- package/dist/utils/merge-permissions.d.ts +3 -0
- package/dist/utils/merge-permissions.js +95 -0
- package/dist/utils/reduce-schema.d.ts +6 -4
- package/dist/utils/reduce-schema.js +34 -14
- package/dist/utils/verify-session-jwt.js +2 -1
- package/dist/websocket/authenticate.d.ts +2 -0
- package/dist/websocket/authenticate.js +12 -0
- package/dist/websocket/controllers/graphql.js +4 -1
- package/dist/websocket/controllers/hooks.js +0 -4
- package/dist/websocket/controllers/rest.js +2 -0
- package/dist/websocket/handlers/subscribe.js +2 -0
- package/dist/websocket/utils/items.d.ts +1 -1
- package/package.json +35 -33
- package/dist/controllers/access.js +0 -148
- package/dist/controllers/policies.d.ts +0 -2
- package/dist/controllers/policies.js +0 -169
- package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +0 -16
- package/dist/database/get-ast-from-query/get-ast-from-query.js +0 -82
- package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +0 -13
- package/dist/database/get-ast-from-query/lib/convert-wildcards.js +0 -69
- package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +0 -15
- package/dist/database/get-ast-from-query/lib/parse-fields.js +0 -190
- package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +0 -14
- package/dist/database/get-ast-from-query/utils/get-deep-query.js +0 -17
- package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-related-collection.js +0 -13
- package/dist/database/get-ast-from-query/utils/get-relation.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-relation.js +0 -7
- package/dist/database/migrations/20240619A-permissions-policies.js +0 -163
- package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
- package/dist/database/run-ast/lib/get-db-query.js +0 -194
- package/dist/database/run-ast/lib/parse-current-level.d.ts +0 -7
- package/dist/database/run-ast/lib/parse-current-level.js +0 -41
- package/dist/database/run-ast/run-ast.d.ts +0 -7
- package/dist/database/run-ast/run-ast.js +0 -107
- package/dist/database/run-ast/types.js +0 -1
- package/dist/database/run-ast/utils/apply-case-when.d.ts +0 -16
- package/dist/database/run-ast/utils/apply-case-when.js +0 -26
- package/dist/database/run-ast/utils/apply-parent-filters.d.ts +0 -3
- package/dist/database/run-ast/utils/apply-parent-filters.js +0 -55
- package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +0 -10
- package/dist/database/run-ast/utils/get-column-pre-processor.js +0 -57
- package/dist/database/run-ast/utils/get-field-alias.d.ts +0 -2
- package/dist/database/run-ast/utils/get-field-alias.js +0 -4
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +0 -5
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +0 -23
- package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +0 -3
- package/dist/database/run-ast/utils/merge-with-parent-items.js +0 -87
- package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +0 -3
- package/dist/database/run-ast/utils/remove-temporary-fields.js +0 -73
- package/dist/permissions/cache.d.ts +0 -2
- package/dist/permissions/cache.js +0 -23
- package/dist/permissions/lib/fetch-permissions.d.ts +0 -10
- package/dist/permissions/lib/fetch-permissions.js +0 -55
- package/dist/permissions/lib/fetch-policies.d.ts +0 -7
- package/dist/permissions/lib/fetch-policies.js +0 -28
- package/dist/permissions/lib/fetch-roles-tree.d.ts +0 -3
- package/dist/permissions/lib/fetch-roles-tree.js +0 -28
- package/dist/permissions/lib/with-app-minimal-permissions.js +0 -10
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +0 -7
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +0 -56
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +0 -3
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +0 -16
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +0 -8
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +0 -24
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +0 -9
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +0 -31
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +0 -16
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +0 -27
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +0 -10
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +0 -23
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
- package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/types.js +0 -1
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +0 -12
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +0 -32
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +0 -4
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +0 -29
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +0 -49
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +0 -3
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +0 -56
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +0 -8
- package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +0 -9
- package/dist/permissions/modules/process-ast/lib/inject-cases.js +0 -93
- package/dist/permissions/modules/process-ast/process-ast.d.ts +0 -9
- package/dist/permissions/modules/process-ast/process-ast.js +0 -39
- package/dist/permissions/modules/process-ast/types.d.ts +0 -24
- package/dist/permissions/modules/process-ast/types.js +0 -1
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +0 -7
- package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +0 -12
- package/dist/permissions/modules/process-ast/utils/dedupe-access.js +0 -30
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +0 -15
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +0 -50
- package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/find-related-collection.js +0 -9
- package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/flatten-filter.js +0 -24
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +0 -1
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +0 -3
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +0 -5
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +0 -7
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +0 -3
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +0 -16
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +0 -12
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +0 -28
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +0 -5
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +0 -12
- package/dist/permissions/modules/process-payload/process-payload.d.ts +0 -13
- package/dist/permissions/modules/process-payload/process-payload.js +0 -77
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +0 -12
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +0 -11
- package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +0 -9
- package/dist/permissions/modules/validate-access/lib/validate-item-access.js +0 -33
- package/dist/permissions/modules/validate-access/validate-access.d.ts +0 -14
- package/dist/permissions/modules/validate-access/validate-access.js +0 -28
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +0 -1
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +0 -8
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +0 -5
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +0 -10
- package/dist/permissions/types.d.ts +0 -6
- package/dist/permissions/types.js +0 -1
- package/dist/permissions/utils/create-default-accountability.d.ts +0 -2
- package/dist/permissions/utils/create-default-accountability.js +0 -11
- package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +0 -8
- package/dist/permissions/utils/extract-required-dynamic-variable-context.js +0 -27
- package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +0 -9
- package/dist/permissions/utils/fetch-dynamic-variable-context.js +0 -43
- package/dist/permissions/utils/filter-policies-by-ip.d.ts +0 -2
- package/dist/permissions/utils/filter-policies-by-ip.js +0 -15
- package/dist/permissions/utils/get-unaliased-field-key.d.ts +0 -5
- package/dist/permissions/utils/get-unaliased-field-key.js +0 -17
- package/dist/permissions/utils/process-permissions.d.ts +0 -7
- package/dist/permissions/utils/process-permissions.js +0 -9
- package/dist/permissions/utils/with-cache.d.ts +0 -10
- package/dist/permissions/utils/with-cache.js +0 -25
- package/dist/services/access.d.ts +0 -10
- package/dist/services/access.js +0 -43
- package/dist/services/policies.d.ts +0 -12
- package/dist/services/policies.js +0 -87
- package/dist/telemetry/utils/check-user-limits.d.ts +0 -5
- package/dist/telemetry/utils/check-user-limits.js +0 -19
- package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +0 -17
- package/dist/utils/fetch-user-count/fetch-access-lookup.js +0 -22
- package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +0 -16
- package/dist/utils/fetch-user-count/fetch-access-roles.js +0 -37
- package/dist/utils/fetch-user-count/fetch-active-users.d.ts +0 -6
- package/dist/utils/fetch-user-count/fetch-active-users.js +0 -3
- package/dist/utils/fetch-user-count/fetch-user-count.d.ts +0 -12
- package/dist/utils/fetch-user-count/fetch-user-count.js +0 -57
- package/dist/utils/fetch-user-count/get-user-count-query.d.ts +0 -20
- package/dist/utils/fetch-user-count/get-user-count-query.js +0 -17
- package/dist/utils/validate-user-count-integrity.d.ts +0 -13
- package/dist/utils/validate-user-count-integrity.js +0 -29
- /package/dist/database/migrations/{20240619A-permissions-policies.d.ts → 20240701A-add-tus-data.d.ts} +0 -0
- /package/dist/{utils → services/files/utils}/parse-image-metadata.d.ts +0 -0
- /package/dist/{utils → services/files/utils}/parse-image-metadata.js +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventEmitter, on } from 'events';
|
|
2
2
|
import { useBus } from '../../bus/index.js';
|
|
3
3
|
import { getSchema } from '../../utils/get-schema.js';
|
|
4
|
+
import { refreshAccountability } from '../../websocket/authenticate.js';
|
|
4
5
|
import { getPayload } from '../../websocket/utils/items.js';
|
|
5
6
|
const messages = createPubSub(new EventEmitter());
|
|
6
7
|
export function bindPubSub() {
|
|
@@ -18,6 +19,7 @@ export function createSubscriptionGenerator(self, event) {
|
|
|
18
19
|
if ('event' in args && eventData['action'] !== args['event']) {
|
|
19
20
|
continue; // skip filtered events
|
|
20
21
|
}
|
|
22
|
+
const accountability = await refreshAccountability(self.accountability);
|
|
21
23
|
const schema = await getSchema();
|
|
22
24
|
const subscription = {
|
|
23
25
|
collection: eventData['collection'],
|
|
@@ -33,7 +35,7 @@ export function createSubscriptionGenerator(self, event) {
|
|
|
33
35
|
if (eventData['action'] === 'create') {
|
|
34
36
|
try {
|
|
35
37
|
subscription.item = eventData['key'];
|
|
36
|
-
const result = await getPayload(subscription,
|
|
38
|
+
const result = await getPayload(subscription, accountability, schema, eventData);
|
|
37
39
|
yield {
|
|
38
40
|
[event]: {
|
|
39
41
|
key: eventData['key'],
|
|
@@ -50,7 +52,7 @@ export function createSubscriptionGenerator(self, event) {
|
|
|
50
52
|
for (const key of eventData['keys']) {
|
|
51
53
|
try {
|
|
52
54
|
subscription.item = key;
|
|
53
|
-
const result = await getPayload(subscription,
|
|
55
|
+
const result = await getPayload(subscription, accountability, schema, eventData);
|
|
54
56
|
yield {
|
|
55
57
|
[event]: {
|
|
56
58
|
key,
|
|
@@ -15,7 +15,6 @@ import StreamArray from 'stream-json/streamers/StreamArray.js';
|
|
|
15
15
|
import getDatabase from '../database/index.js';
|
|
16
16
|
import emitter from '../emitter.js';
|
|
17
17
|
import { useLogger } from '../logger.js';
|
|
18
|
-
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
19
18
|
import { getDateFormatted } from '../utils/get-date-formatted.js';
|
|
20
19
|
import { getService } from '../utils/get-service.js';
|
|
21
20
|
import { transaction } from '../utils/transaction.js';
|
|
@@ -38,23 +37,10 @@ export class ImportService {
|
|
|
38
37
|
async import(collection, mimetype, stream) {
|
|
39
38
|
if (this.accountability?.admin !== true && isSystemCollection(collection))
|
|
40
39
|
throw new ForbiddenError();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
collection,
|
|
46
|
-
}, {
|
|
47
|
-
schema: this.schema,
|
|
48
|
-
knex: this.knex,
|
|
49
|
-
});
|
|
50
|
-
await validateAccess({
|
|
51
|
-
accountability: this.accountability,
|
|
52
|
-
action: 'update',
|
|
53
|
-
collection,
|
|
54
|
-
}, {
|
|
55
|
-
schema: this.schema,
|
|
56
|
-
knex: this.knex,
|
|
57
|
-
});
|
|
40
|
+
const createPermissions = this.accountability?.permissions?.find((permission) => permission.collection === collection && permission.action === 'create');
|
|
41
|
+
const updatePermissions = this.accountability?.permissions?.find((permission) => permission.collection === collection && permission.action === 'update');
|
|
42
|
+
if (this.accountability?.admin !== true && (!createPermissions || !updatePermissions)) {
|
|
43
|
+
throw new ForbiddenError();
|
|
58
44
|
}
|
|
59
45
|
switch (mimetype) {
|
|
60
46
|
case 'application/json':
|
package/dist/services/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from './access.js';
|
|
2
1
|
export * from './activity.js';
|
|
3
2
|
export * from './assets.js';
|
|
4
3
|
export * from './authentication.js';
|
|
4
|
+
export * from './authorization.js';
|
|
5
5
|
export * from './collections.js';
|
|
6
6
|
export * from './dashboards.js';
|
|
7
7
|
export * from './extensions.js';
|
|
@@ -18,8 +18,7 @@ export * from './notifications.js';
|
|
|
18
18
|
export * from './operations.js';
|
|
19
19
|
export * from './panels.js';
|
|
20
20
|
export * from './payload.js';
|
|
21
|
-
export * from './permissions.js';
|
|
22
|
-
export * from './policies.js';
|
|
21
|
+
export * from './permissions/index.js';
|
|
23
22
|
export * from './presets.js';
|
|
24
23
|
export * from './relations.js';
|
|
25
24
|
export * from './revisions.js';
|
package/dist/services/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from './access.js';
|
|
2
1
|
export * from './activity.js';
|
|
3
2
|
export * from './assets.js';
|
|
4
3
|
export * from './authentication.js';
|
|
4
|
+
export * from './authorization.js';
|
|
5
5
|
export * from './collections.js';
|
|
6
6
|
export * from './dashboards.js';
|
|
7
7
|
export * from './extensions.js';
|
|
@@ -18,8 +18,7 @@ export * from './notifications.js';
|
|
|
18
18
|
export * from './operations.js';
|
|
19
19
|
export * from './panels.js';
|
|
20
20
|
export * from './payload.js';
|
|
21
|
-
export * from './permissions.js';
|
|
22
|
-
export * from './policies.js';
|
|
21
|
+
export * from './permissions/index.js';
|
|
23
22
|
export * from './presets.js';
|
|
24
23
|
export * from './relations.js';
|
|
25
24
|
export * from './revisions.js';
|
package/dist/services/items.js
CHANGED
|
@@ -5,18 +5,15 @@ import { isSystemCollection } from '@directus/system-data';
|
|
|
5
5
|
import { assign, clone, cloneDeep, omit, pick, without } from 'lodash-es';
|
|
6
6
|
import { getCache } from '../cache.js';
|
|
7
7
|
import { translateDatabaseError } from '../database/errors/translate.js';
|
|
8
|
-
import { getAstFromQuery } from '../database/get-ast-from-query/get-ast-from-query.js';
|
|
9
8
|
import { getHelpers } from '../database/helpers/index.js';
|
|
10
9
|
import getDatabase from '../database/index.js';
|
|
11
|
-
import
|
|
10
|
+
import runAST from '../database/run-ast.js';
|
|
12
11
|
import emitter from '../emitter.js';
|
|
13
|
-
import
|
|
14
|
-
import { processPayload } from '../permissions/modules/process-payload/process-payload.js';
|
|
15
|
-
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
12
|
+
import getASTFromQuery from '../utils/get-ast-from-query.js';
|
|
16
13
|
import { shouldClearCache } from '../utils/should-clear-cache.js';
|
|
17
14
|
import { transaction } from '../utils/transaction.js';
|
|
18
15
|
import { validateKeys } from '../utils/validate-keys.js';
|
|
19
|
-
import {
|
|
16
|
+
import { AuthorizationService } from './authorization.js';
|
|
20
17
|
import { PayloadService } from './payload.js';
|
|
21
18
|
const env = useEnv();
|
|
22
19
|
export class ItemsService {
|
|
@@ -101,13 +98,17 @@ export class ItemsService {
|
|
|
101
98
|
// that any errors thrown in any nested relational changes will bubble up and cancel the whole
|
|
102
99
|
// update tree
|
|
103
100
|
const primaryKey = await transaction(this.knex, async (trx) => {
|
|
104
|
-
|
|
101
|
+
// We're creating new services instances so they can use the transaction as their Knex interface
|
|
102
|
+
const payloadService = new PayloadService(this.collection, {
|
|
105
103
|
accountability: this.accountability,
|
|
106
104
|
knex: trx,
|
|
107
105
|
schema: this.schema,
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
|
|
106
|
+
});
|
|
107
|
+
const authorizationService = new AuthorizationService({
|
|
108
|
+
accountability: this.accountability,
|
|
109
|
+
knex: trx,
|
|
110
|
+
schema: this.schema,
|
|
111
|
+
});
|
|
111
112
|
// Run all hooks that are attached to this event so the end user has the chance to augment the
|
|
112
113
|
// item that is about to be saved
|
|
113
114
|
const payloadAfterHooks = opts.emitEvents !== false
|
|
@@ -122,21 +123,13 @@ export class ItemsService {
|
|
|
122
123
|
})
|
|
123
124
|
: payload;
|
|
124
125
|
const payloadWithPresets = this.accountability
|
|
125
|
-
?
|
|
126
|
-
accountability: this.accountability,
|
|
127
|
-
action: 'create',
|
|
128
|
-
collection: this.collection,
|
|
129
|
-
payload: payloadAfterHooks,
|
|
130
|
-
}, {
|
|
131
|
-
knex: trx,
|
|
132
|
-
schema: this.schema,
|
|
133
|
-
})
|
|
126
|
+
? authorizationService.validatePayload('create', this.collection, payloadAfterHooks)
|
|
134
127
|
: payloadAfterHooks;
|
|
135
128
|
if (opts.preMutationError) {
|
|
136
129
|
throw opts.preMutationError;
|
|
137
130
|
}
|
|
138
|
-
const { payload: payloadWithM2O, revisions: revisionsM2O, nestedActionEvents: nestedActionEventsM2O,
|
|
139
|
-
const { payload: payloadWithA2O, revisions: revisionsA2O, nestedActionEvents: nestedActionEventsA2O,
|
|
131
|
+
const { payload: payloadWithM2O, revisions: revisionsM2O, nestedActionEvents: nestedActionEventsM2O, } = await payloadService.processM2O(payloadWithPresets, opts);
|
|
132
|
+
const { payload: payloadWithA2O, revisions: revisionsA2O, nestedActionEvents: nestedActionEventsA2O, } = await payloadService.processA2O(payloadWithM2O, opts);
|
|
140
133
|
const payloadWithoutAliases = pick(payloadWithA2O, without(fields, ...aliases));
|
|
141
134
|
const payloadWithTypeCasting = await payloadService.processValues('create', payloadWithoutAliases);
|
|
142
135
|
// The primary key can already exist in the payload.
|
|
@@ -194,22 +187,10 @@ export class ItemsService {
|
|
|
194
187
|
}
|
|
195
188
|
// At this point, the primary key is guaranteed to be set.
|
|
196
189
|
primaryKey = primaryKey;
|
|
197
|
-
const { revisions: revisionsO2M, nestedActionEvents: nestedActionEventsO2M
|
|
190
|
+
const { revisions: revisionsO2M, nestedActionEvents: nestedActionEventsO2M } = await payloadService.processO2M(payloadWithPresets, primaryKey, opts);
|
|
198
191
|
nestedActionEvents.push(...nestedActionEventsM2O);
|
|
199
192
|
nestedActionEvents.push(...nestedActionEventsA2O);
|
|
200
193
|
nestedActionEvents.push(...nestedActionEventsO2M);
|
|
201
|
-
const userIntegrityCheckFlags = (opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None) |
|
|
202
|
-
userIntegrityCheckFlagsM2O |
|
|
203
|
-
userIntegrityCheckFlagsA2O |
|
|
204
|
-
userIntegrityCheckFlagsO2M;
|
|
205
|
-
if (userIntegrityCheckFlags) {
|
|
206
|
-
if (opts.onRequireUserIntegrityCheck) {
|
|
207
|
-
opts.onRequireUserIntegrityCheck(userIntegrityCheckFlags);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
await validateUserCountIntegrity({ flags: userIntegrityCheckFlags, knex: trx });
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
194
|
// If this is an authenticated action, and accountability tracking is enabled, save activity row
|
|
214
195
|
if (this.accountability && this.schema.collections[this.collection].accountability !== null) {
|
|
215
196
|
const activityService = new ActivityService({
|
|
@@ -300,7 +281,6 @@ export class ItemsService {
|
|
|
300
281
|
opts.mutationTracker = this.createMutationTracker();
|
|
301
282
|
const { primaryKeys, nestedActionEvents } = await transaction(this.knex, async (knex) => {
|
|
302
283
|
const service = this.fork({ knex });
|
|
303
|
-
let userIntegrityCheckFlags = opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None;
|
|
304
284
|
const primaryKeys = [];
|
|
305
285
|
const nestedActionEvents = [];
|
|
306
286
|
const pkField = this.schema.collections[this.collection].primary;
|
|
@@ -314,21 +294,12 @@ export class ItemsService {
|
|
|
314
294
|
const primaryKey = await service.createOne(payload, {
|
|
315
295
|
...(opts || {}),
|
|
316
296
|
autoPurgeCache: false,
|
|
317
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
318
297
|
bypassEmitAction: (params) => nestedActionEvents.push(params),
|
|
319
298
|
mutationTracker: opts.mutationTracker,
|
|
320
299
|
bypassAutoIncrementSequenceReset,
|
|
321
300
|
});
|
|
322
301
|
primaryKeys.push(primaryKey);
|
|
323
302
|
}
|
|
324
|
-
if (userIntegrityCheckFlags) {
|
|
325
|
-
if (opts.onRequireUserIntegrityCheck) {
|
|
326
|
-
opts.onRequireUserIntegrityCheck(userIntegrityCheckFlags);
|
|
327
|
-
}
|
|
328
|
-
else {
|
|
329
|
-
await validateUserCountIntegrity({ flags: userIntegrityCheckFlags, knex });
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
303
|
return { primaryKeys, nestedActionEvents };
|
|
333
304
|
});
|
|
334
305
|
if (opts.emitEvents !== false) {
|
|
@@ -361,21 +332,27 @@ export class ItemsService {
|
|
|
361
332
|
accountability: this.accountability,
|
|
362
333
|
})
|
|
363
334
|
: query;
|
|
364
|
-
let ast = await
|
|
365
|
-
collection: this.collection,
|
|
366
|
-
query: updatedQuery,
|
|
335
|
+
let ast = await getASTFromQuery(this.collection, updatedQuery, this.schema, {
|
|
367
336
|
accountability: this.accountability,
|
|
368
|
-
|
|
369
|
-
|
|
337
|
+
// By setting the permissions action, you can read items using the permissions for another
|
|
338
|
+
// operation's permissions. This is used to dynamically check if you have update/delete
|
|
339
|
+
// access to (a) certain item(s)
|
|
340
|
+
action: opts?.permissionsAction || 'read',
|
|
370
341
|
knex: this.knex,
|
|
371
342
|
});
|
|
372
|
-
|
|
373
|
-
|
|
343
|
+
if (this.accountability && this.accountability.admin !== true) {
|
|
344
|
+
const authorizationService = new AuthorizationService({
|
|
345
|
+
accountability: this.accountability,
|
|
346
|
+
knex: this.knex,
|
|
347
|
+
schema: this.schema,
|
|
348
|
+
});
|
|
349
|
+
ast = await authorizationService.processAST(ast, opts?.permissionsAction);
|
|
350
|
+
}
|
|
351
|
+
const records = await runAST(ast, this.schema, {
|
|
374
352
|
knex: this.knex,
|
|
375
353
|
// GraphQL requires relational keys to be returned regardless
|
|
376
354
|
stripNonRequested: opts?.stripNonRequested !== undefined ? opts.stripNonRequested : true,
|
|
377
355
|
});
|
|
378
|
-
// TODO when would this happen?
|
|
379
356
|
if (records === null) {
|
|
380
357
|
throw new ForbiddenError();
|
|
381
358
|
}
|
|
@@ -473,26 +450,13 @@ export class ItemsService {
|
|
|
473
450
|
try {
|
|
474
451
|
await transaction(this.knex, async (knex) => {
|
|
475
452
|
const service = this.fork({ knex });
|
|
476
|
-
let userIntegrityCheckFlags = opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None;
|
|
477
453
|
for (const item of data) {
|
|
478
454
|
const primaryKey = item[primaryKeyField];
|
|
479
455
|
if (!primaryKey)
|
|
480
456
|
throw new InvalidPayloadError({ reason: `Item in update misses primary key` });
|
|
481
|
-
const combinedOpts = {
|
|
482
|
-
autoPurgeCache: false,
|
|
483
|
-
...opts,
|
|
484
|
-
onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
|
|
485
|
-
};
|
|
457
|
+
const combinedOpts = Object.assign({ autoPurgeCache: false }, opts);
|
|
486
458
|
keys.push(await service.updateOne(primaryKey, omit(item, primaryKeyField), combinedOpts));
|
|
487
459
|
}
|
|
488
|
-
if (userIntegrityCheckFlags) {
|
|
489
|
-
if (opts.onRequireUserIntegrityCheck) {
|
|
490
|
-
opts.onRequireUserIntegrityCheck(userIntegrityCheckFlags);
|
|
491
|
-
}
|
|
492
|
-
else {
|
|
493
|
-
await validateUserCountIntegrity({ flags: userIntegrityCheckFlags, knex });
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
460
|
});
|
|
497
461
|
}
|
|
498
462
|
finally {
|
|
@@ -521,6 +485,11 @@ export class ItemsService {
|
|
|
521
485
|
.map((field) => field.field);
|
|
522
486
|
const payload = cloneDeep(data);
|
|
523
487
|
const nestedActionEvents = [];
|
|
488
|
+
const authorizationService = new AuthorizationService({
|
|
489
|
+
accountability: this.accountability,
|
|
490
|
+
knex: this.knex,
|
|
491
|
+
schema: this.schema,
|
|
492
|
+
});
|
|
524
493
|
// Run all hooks that are attached to this event so the end user has the chance to augment the
|
|
525
494
|
// item that is about to be saved
|
|
526
495
|
const payloadAfterHooks = opts.emitEvents !== false
|
|
@@ -538,26 +507,10 @@ export class ItemsService {
|
|
|
538
507
|
// Sort keys to ensure that the order is maintained
|
|
539
508
|
keys.sort();
|
|
540
509
|
if (this.accountability) {
|
|
541
|
-
await
|
|
542
|
-
accountability: this.accountability,
|
|
543
|
-
action: 'update',
|
|
544
|
-
collection: this.collection,
|
|
545
|
-
primaryKeys: keys,
|
|
546
|
-
}, {
|
|
547
|
-
schema: this.schema,
|
|
548
|
-
knex: this.knex,
|
|
549
|
-
});
|
|
510
|
+
await authorizationService.checkAccess('update', this.collection, keys);
|
|
550
511
|
}
|
|
551
512
|
const payloadWithPresets = this.accountability
|
|
552
|
-
?
|
|
553
|
-
accountability: this.accountability,
|
|
554
|
-
action: 'update',
|
|
555
|
-
collection: this.collection,
|
|
556
|
-
payload: payloadAfterHooks,
|
|
557
|
-
}, {
|
|
558
|
-
knex: this.knex,
|
|
559
|
-
schema: this.schema,
|
|
560
|
-
})
|
|
513
|
+
? authorizationService.validatePayload('update', this.collection, payloadAfterHooks)
|
|
561
514
|
: payloadAfterHooks;
|
|
562
515
|
if (opts.preMutationError) {
|
|
563
516
|
throw opts.preMutationError;
|
|
@@ -568,8 +521,8 @@ export class ItemsService {
|
|
|
568
521
|
knex: trx,
|
|
569
522
|
schema: this.schema,
|
|
570
523
|
});
|
|
571
|
-
const { payload: payloadWithM2O, revisions: revisionsM2O, nestedActionEvents: nestedActionEventsM2O,
|
|
572
|
-
const { payload: payloadWithA2O, revisions: revisionsA2O, nestedActionEvents: nestedActionEventsA2O,
|
|
524
|
+
const { payload: payloadWithM2O, revisions: revisionsM2O, nestedActionEvents: nestedActionEventsM2O, } = await payloadService.processM2O(payloadWithPresets, opts);
|
|
525
|
+
const { payload: payloadWithA2O, revisions: revisionsA2O, nestedActionEvents: nestedActionEventsA2O, } = await payloadService.processA2O(payloadWithM2O, opts);
|
|
573
526
|
const payloadWithoutAliasAndPK = pick(payloadWithA2O, without(fields, primaryKeyField, ...aliases));
|
|
574
527
|
const payloadWithTypeCasting = await payloadService.processValues('update', payloadWithoutAliasAndPK);
|
|
575
528
|
if (Object.keys(payloadWithTypeCasting).length > 0) {
|
|
@@ -581,25 +534,12 @@ export class ItemsService {
|
|
|
581
534
|
}
|
|
582
535
|
}
|
|
583
536
|
const childrenRevisions = [...revisionsM2O, ...revisionsA2O];
|
|
584
|
-
let userIntegrityCheckFlags = opts.userIntegrityCheckFlags ??
|
|
585
|
-
UserIntegrityCheckFlag.None | userIntegrityCheckFlagsM2O | userIntegrityCheckFlagsA2O;
|
|
586
537
|
nestedActionEvents.push(...nestedActionEventsM2O);
|
|
587
538
|
nestedActionEvents.push(...nestedActionEventsA2O);
|
|
588
539
|
for (const key of keys) {
|
|
589
|
-
const { revisions, nestedActionEvents: nestedActionEventsO2M
|
|
540
|
+
const { revisions, nestedActionEvents: nestedActionEventsO2M } = await payloadService.processO2M(payloadWithA2O, key, opts);
|
|
590
541
|
childrenRevisions.push(...revisions);
|
|
591
542
|
nestedActionEvents.push(...nestedActionEventsO2M);
|
|
592
|
-
userIntegrityCheckFlags |= userIntegrityCheckFlagsO2M;
|
|
593
|
-
}
|
|
594
|
-
if (userIntegrityCheckFlags) {
|
|
595
|
-
if (opts?.onRequireUserIntegrityCheck) {
|
|
596
|
-
opts.onRequireUserIntegrityCheck(userIntegrityCheckFlags);
|
|
597
|
-
}
|
|
598
|
-
else {
|
|
599
|
-
// Having no onRequireUserIntegrityCheck callback indicates that
|
|
600
|
-
// this is the top level invocation of the nested updates, so perform the user integrity check
|
|
601
|
-
await validateUserCountIntegrity({ flags: userIntegrityCheckFlags, knex: trx });
|
|
602
|
-
}
|
|
603
543
|
}
|
|
604
544
|
// If this is an authenticated action, and accountability tracking is enabled, save activity row
|
|
605
545
|
if (this.accountability && this.schema.collections[this.collection].accountability !== null) {
|
|
@@ -768,16 +708,13 @@ export class ItemsService {
|
|
|
768
708
|
const { ActivityService } = await import('./activity.js');
|
|
769
709
|
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
770
710
|
validateKeys(this.schema, this.collection, primaryKeyField, keys);
|
|
771
|
-
if (this.accountability) {
|
|
772
|
-
|
|
711
|
+
if (this.accountability && this.accountability.admin !== true) {
|
|
712
|
+
const authorizationService = new AuthorizationService({
|
|
773
713
|
accountability: this.accountability,
|
|
774
|
-
action: 'delete',
|
|
775
|
-
collection: this.collection,
|
|
776
|
-
primaryKeys: keys,
|
|
777
|
-
}, {
|
|
778
|
-
knex: this.knex,
|
|
779
714
|
schema: this.schema,
|
|
715
|
+
knex: this.knex,
|
|
780
716
|
});
|
|
717
|
+
await authorizationService.checkAccess('delete', this.collection, keys);
|
|
781
718
|
}
|
|
782
719
|
if (opts.preMutationError) {
|
|
783
720
|
throw opts.preMutationError;
|
|
@@ -793,14 +730,6 @@ export class ItemsService {
|
|
|
793
730
|
}
|
|
794
731
|
await transaction(this.knex, async (trx) => {
|
|
795
732
|
await trx(this.collection).whereIn(primaryKeyField, keys).delete();
|
|
796
|
-
if (opts.userIntegrityCheckFlags) {
|
|
797
|
-
if (opts.onRequireUserIntegrityCheck) {
|
|
798
|
-
opts.onRequireUserIntegrityCheck(opts.userIntegrityCheckFlags);
|
|
799
|
-
}
|
|
800
|
-
else {
|
|
801
|
-
await validateUserCountIntegrity({ flags: opts.userIntegrityCheckFlags, knex: trx });
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
733
|
if (this.accountability && this.schema.collections[this.collection].accountability !== null) {
|
|
805
734
|
const activityService = new ActivityService({
|
|
806
735
|
knex: trx,
|
package/dist/services/meta.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import getDatabase from '../database/index.js';
|
|
2
|
-
import {
|
|
3
|
-
import { fetchPolicies } from '../permissions/lib/fetch-policies.js';
|
|
4
|
-
import { dedupeAccess } from '../permissions/modules/process-ast/utils/dedupe-access.js';
|
|
5
|
-
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
2
|
+
import { ForbiddenError } from '@directus/errors';
|
|
6
3
|
import { applyFilter, applySearch } from '../utils/apply-query.js';
|
|
7
4
|
export class MetaService {
|
|
8
5
|
knex;
|
|
@@ -31,73 +28,39 @@ export class MetaService {
|
|
|
31
28
|
}, {});
|
|
32
29
|
}
|
|
33
30
|
async totalCount(collection) {
|
|
34
|
-
const dbQuery = this.knex(collection);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const policies = await fetchPolicies(this.accountability, context);
|
|
44
|
-
const permissions = await fetchPermissions({
|
|
45
|
-
action: 'read',
|
|
46
|
-
policies,
|
|
47
|
-
accountability: this.accountability,
|
|
48
|
-
...(collection ? { collections: [collection] } : {}),
|
|
49
|
-
}, context);
|
|
50
|
-
const rules = dedupeAccess(permissions);
|
|
51
|
-
const cases = rules.map(({ rule }) => rule);
|
|
52
|
-
const filter = {
|
|
53
|
-
_or: cases,
|
|
54
|
-
};
|
|
55
|
-
const result = applyFilter(this.knex, this.schema, dbQuery, filter, collection, {}, cases);
|
|
56
|
-
hasJoins = result.hasJoins;
|
|
57
|
-
}
|
|
58
|
-
if (hasJoins) {
|
|
59
|
-
const primaryKeyName = this.schema.collections[collection].primary;
|
|
60
|
-
dbQuery.countDistinct({ count: [`${collection}.${primaryKeyName}`] });
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
dbQuery.count('*', { as: 'count' });
|
|
31
|
+
const dbQuery = this.knex(collection).count('*', { as: 'count' }).first();
|
|
32
|
+
if (this.accountability?.admin !== true) {
|
|
33
|
+
const permissionsRecord = this.accountability?.permissions?.find((permission) => {
|
|
34
|
+
return permission.action === 'read' && permission.collection === collection;
|
|
35
|
+
});
|
|
36
|
+
if (!permissionsRecord)
|
|
37
|
+
throw new ForbiddenError();
|
|
38
|
+
const permissions = permissionsRecord.permissions ?? {};
|
|
39
|
+
applyFilter(this.knex, this.schema, dbQuery, permissions, collection, {});
|
|
64
40
|
}
|
|
65
|
-
const result = await dbQuery
|
|
41
|
+
const result = await dbQuery;
|
|
66
42
|
return Number(result?.count ?? 0);
|
|
67
43
|
}
|
|
68
44
|
async filterCount(collection, query) {
|
|
69
45
|
const dbQuery = this.knex(collection);
|
|
70
46
|
let filter = query.filter || {};
|
|
71
47
|
let hasJoins = false;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}, context);
|
|
80
|
-
const policies = await fetchPolicies(this.accountability, context);
|
|
81
|
-
const permissions = await fetchPermissions({
|
|
82
|
-
action: 'read',
|
|
83
|
-
policies,
|
|
84
|
-
accountability: this.accountability,
|
|
85
|
-
...(collection ? { collections: [collection] } : {}),
|
|
86
|
-
}, context);
|
|
87
|
-
const rules = dedupeAccess(permissions);
|
|
88
|
-
cases = rules.map(({ rule }) => rule);
|
|
89
|
-
const permissionsFilter = {
|
|
90
|
-
_or: cases,
|
|
91
|
-
};
|
|
48
|
+
if (this.accountability?.admin !== true) {
|
|
49
|
+
const permissionsRecord = this.accountability?.permissions?.find((permission) => {
|
|
50
|
+
return permission.action === 'read' && permission.collection === collection;
|
|
51
|
+
});
|
|
52
|
+
if (!permissionsRecord)
|
|
53
|
+
throw new ForbiddenError();
|
|
54
|
+
const permissions = permissionsRecord.permissions ?? {};
|
|
92
55
|
if (Object.keys(filter).length > 0) {
|
|
93
|
-
filter = { _and: [
|
|
56
|
+
filter = { _and: [permissions, filter] };
|
|
94
57
|
}
|
|
95
58
|
else {
|
|
96
|
-
filter =
|
|
59
|
+
filter = permissions;
|
|
97
60
|
}
|
|
98
61
|
}
|
|
99
62
|
if (Object.keys(filter).length > 0) {
|
|
100
|
-
({ hasJoins } = applyFilter(this.knex, this.schema, dbQuery, filter, collection, {}
|
|
63
|
+
({ hasJoins } = applyFilter(this.knex, this.schema, dbQuery, filter, collection, {}));
|
|
101
64
|
}
|
|
102
65
|
if (query.search) {
|
|
103
66
|
applySearch(this.knex, this.schema, dbQuery, query.search, collection);
|
|
@@ -109,7 +72,7 @@ export class MetaService {
|
|
|
109
72
|
else {
|
|
110
73
|
dbQuery.count('*', { as: 'count' });
|
|
111
74
|
}
|
|
112
|
-
const
|
|
113
|
-
return Number(
|
|
75
|
+
const records = await dbQuery;
|
|
76
|
+
return Number(records[0]['count']);
|
|
114
77
|
}
|
|
115
78
|
}
|
|
@@ -2,7 +2,6 @@ import type { Accountability, Item, PrimaryKey, SchemaOverview } from '@directus
|
|
|
2
2
|
import type { Knex } from 'knex';
|
|
3
3
|
import type { Helpers } from '../database/helpers/index.js';
|
|
4
4
|
import type { AbstractServiceOptions, ActionEventParams, MutationOptions } from '../types/index.js';
|
|
5
|
-
import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
|
|
6
5
|
type Action = 'create' | 'read' | 'update';
|
|
7
6
|
type Transformers = {
|
|
8
7
|
[type: string]: (context: {
|
|
@@ -14,11 +13,6 @@ type Transformers = {
|
|
|
14
13
|
helpers: Helpers;
|
|
15
14
|
}) => Promise<any>;
|
|
16
15
|
};
|
|
17
|
-
type PayloadServiceProcessRelationResult = {
|
|
18
|
-
revisions: PrimaryKey[];
|
|
19
|
-
nestedActionEvents: ActionEventParams[];
|
|
20
|
-
userIntegrityCheckFlags: UserIntegrityCheckFlag;
|
|
21
|
-
};
|
|
22
16
|
/**
|
|
23
17
|
* Process a given payload for a collection to ensure the special fields (hash, uuid, date etc) are
|
|
24
18
|
* handled correctly.
|
|
@@ -52,19 +46,26 @@ export declare class PayloadService {
|
|
|
52
46
|
/**
|
|
53
47
|
* Recursively save/update all nested related Any-to-One items
|
|
54
48
|
*/
|
|
55
|
-
processA2O(data: Partial<Item>, opts?: MutationOptions): Promise<
|
|
49
|
+
processA2O(data: Partial<Item>, opts?: MutationOptions): Promise<{
|
|
56
50
|
payload: Partial<Item>;
|
|
51
|
+
revisions: PrimaryKey[];
|
|
52
|
+
nestedActionEvents: ActionEventParams[];
|
|
57
53
|
}>;
|
|
58
54
|
/**
|
|
59
55
|
* Save/update all nested related m2o items inside the payload
|
|
60
56
|
*/
|
|
61
|
-
processM2O(data: Partial<Item>, opts?: MutationOptions): Promise<
|
|
57
|
+
processM2O(data: Partial<Item>, opts?: MutationOptions): Promise<{
|
|
62
58
|
payload: Partial<Item>;
|
|
59
|
+
revisions: PrimaryKey[];
|
|
60
|
+
nestedActionEvents: ActionEventParams[];
|
|
63
61
|
}>;
|
|
64
62
|
/**
|
|
65
63
|
* Recursively save/update all nested related o2m items
|
|
66
64
|
*/
|
|
67
|
-
processO2M(data: Partial<Item>, parent: PrimaryKey, opts?: MutationOptions): Promise<
|
|
65
|
+
processO2M(data: Partial<Item>, parent: PrimaryKey, opts?: MutationOptions): Promise<{
|
|
66
|
+
revisions: PrimaryKey[];
|
|
67
|
+
nestedActionEvents: ActionEventParams[];
|
|
68
|
+
}>;
|
|
68
69
|
/**
|
|
69
70
|
* Transforms the input partial payload to match the output structure, to have consistency
|
|
70
71
|
* between delta and data
|