@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,169 +0,0 @@
|
|
|
1
|
-
import { ErrorCode, ForbiddenError, isDirectusError } from '@directus/errors';
|
|
2
|
-
import express from 'express';
|
|
3
|
-
import getDatabase from '../database/index.js';
|
|
4
|
-
import { respond } from '../middleware/respond.js';
|
|
5
|
-
import useCollection from '../middleware/use-collection.js';
|
|
6
|
-
import { validateBatch } from '../middleware/validate-batch.js';
|
|
7
|
-
import { fetchAccountabilityPolicyGlobals } from '../permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js';
|
|
8
|
-
import { MetaService } from '../services/meta.js';
|
|
9
|
-
import { PoliciesService } from '../services/policies.js';
|
|
10
|
-
import asyncHandler from '../utils/async-handler.js';
|
|
11
|
-
import { sanitizeQuery } from '../utils/sanitize-query.js';
|
|
12
|
-
const router = express.Router();
|
|
13
|
-
router.use(useCollection('directus_policies'));
|
|
14
|
-
router.post('/', asyncHandler(async (req, res, next) => {
|
|
15
|
-
const service = new PoliciesService({
|
|
16
|
-
accountability: req.accountability,
|
|
17
|
-
schema: req.schema,
|
|
18
|
-
});
|
|
19
|
-
const savedKeys = [];
|
|
20
|
-
if (Array.isArray(req.body)) {
|
|
21
|
-
const keys = await service.createMany(req.body);
|
|
22
|
-
savedKeys.push(...keys);
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
const key = await service.createOne(req.body);
|
|
26
|
-
savedKeys.push(key);
|
|
27
|
-
}
|
|
28
|
-
try {
|
|
29
|
-
if (Array.isArray(req.body)) {
|
|
30
|
-
const items = await service.readMany(savedKeys, req.sanitizedQuery);
|
|
31
|
-
res.locals['payload'] = { data: items };
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
const item = await service.readOne(savedKeys[0], req.sanitizedQuery);
|
|
35
|
-
res.locals['payload'] = { data: item };
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
40
|
-
return next();
|
|
41
|
-
}
|
|
42
|
-
throw error;
|
|
43
|
-
}
|
|
44
|
-
return next();
|
|
45
|
-
}), respond);
|
|
46
|
-
const readHandler = asyncHandler(async (req, res, next) => {
|
|
47
|
-
const service = new PoliciesService({
|
|
48
|
-
accountability: req.accountability,
|
|
49
|
-
schema: req.schema,
|
|
50
|
-
});
|
|
51
|
-
const metaService = new MetaService({
|
|
52
|
-
accountability: req.accountability,
|
|
53
|
-
schema: req.schema,
|
|
54
|
-
});
|
|
55
|
-
let result;
|
|
56
|
-
if (req.body.keys) {
|
|
57
|
-
result = await service.readMany(req.body.keys, req.sanitizedQuery);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
result = await service.readByQuery(req.sanitizedQuery);
|
|
61
|
-
}
|
|
62
|
-
const meta = await metaService.getMetaForQuery('directus_policies', req.sanitizedQuery);
|
|
63
|
-
res.locals['payload'] = { data: result, meta };
|
|
64
|
-
return next();
|
|
65
|
-
});
|
|
66
|
-
router.get('/', validateBatch('read'), readHandler, respond);
|
|
67
|
-
router.search('/', validateBatch('read'), readHandler, respond);
|
|
68
|
-
router.get('/me/globals', asyncHandler(async (req, res, next) => {
|
|
69
|
-
try {
|
|
70
|
-
if (!req.accountability?.user && !req.accountability?.role)
|
|
71
|
-
throw new ForbiddenError();
|
|
72
|
-
const result = await fetchAccountabilityPolicyGlobals(req.accountability, {
|
|
73
|
-
schema: req.schema,
|
|
74
|
-
knex: getDatabase(),
|
|
75
|
-
});
|
|
76
|
-
res.locals['payload'] = { data: result };
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
80
|
-
res.locals['payload'] = { data: { app_access: false } };
|
|
81
|
-
return next();
|
|
82
|
-
}
|
|
83
|
-
throw error;
|
|
84
|
-
}
|
|
85
|
-
return next();
|
|
86
|
-
}), respond);
|
|
87
|
-
router.get('/:pk', asyncHandler(async (req, res, next) => {
|
|
88
|
-
if (req.path.endsWith('me'))
|
|
89
|
-
return next();
|
|
90
|
-
const service = new PoliciesService({
|
|
91
|
-
accountability: req.accountability,
|
|
92
|
-
schema: req.schema,
|
|
93
|
-
});
|
|
94
|
-
const record = await service.readOne(req.params['pk'], req.sanitizedQuery);
|
|
95
|
-
res.locals['payload'] = { data: record };
|
|
96
|
-
return next();
|
|
97
|
-
}), respond);
|
|
98
|
-
router.patch('/', validateBatch('update'), asyncHandler(async (req, res, next) => {
|
|
99
|
-
const service = new PoliciesService({
|
|
100
|
-
accountability: req.accountability,
|
|
101
|
-
schema: req.schema,
|
|
102
|
-
});
|
|
103
|
-
let keys = [];
|
|
104
|
-
if (Array.isArray(req.body)) {
|
|
105
|
-
keys = await service.updateBatch(req.body);
|
|
106
|
-
}
|
|
107
|
-
else if (req.body.keys) {
|
|
108
|
-
keys = await service.updateMany(req.body.keys, req.body.data);
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
const sanitizedQuery = sanitizeQuery(req.body.query, req.accountability);
|
|
112
|
-
keys = await service.updateByQuery(sanitizedQuery, req.body.data);
|
|
113
|
-
}
|
|
114
|
-
try {
|
|
115
|
-
const result = await service.readMany(keys, req.sanitizedQuery);
|
|
116
|
-
res.locals['payload'] = { data: result };
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
120
|
-
return next();
|
|
121
|
-
}
|
|
122
|
-
throw error;
|
|
123
|
-
}
|
|
124
|
-
return next();
|
|
125
|
-
}), respond);
|
|
126
|
-
router.patch('/:pk', asyncHandler(async (req, res, next) => {
|
|
127
|
-
const service = new PoliciesService({
|
|
128
|
-
accountability: req.accountability,
|
|
129
|
-
schema: req.schema,
|
|
130
|
-
});
|
|
131
|
-
const primaryKey = await service.updateOne(req.params['pk'], req.body);
|
|
132
|
-
try {
|
|
133
|
-
const item = await service.readOne(primaryKey, req.sanitizedQuery);
|
|
134
|
-
res.locals['payload'] = { data: item || null };
|
|
135
|
-
}
|
|
136
|
-
catch (error) {
|
|
137
|
-
if (isDirectusError(error, ErrorCode.Forbidden)) {
|
|
138
|
-
return next();
|
|
139
|
-
}
|
|
140
|
-
throw error;
|
|
141
|
-
}
|
|
142
|
-
return next();
|
|
143
|
-
}), respond);
|
|
144
|
-
router.delete('/', validateBatch('delete'), asyncHandler(async (req, _res, next) => {
|
|
145
|
-
const service = new PoliciesService({
|
|
146
|
-
accountability: req.accountability,
|
|
147
|
-
schema: req.schema,
|
|
148
|
-
});
|
|
149
|
-
if (Array.isArray(req.body)) {
|
|
150
|
-
await service.deleteMany(req.body);
|
|
151
|
-
}
|
|
152
|
-
else if (req.body.keys) {
|
|
153
|
-
await service.deleteMany(req.body.keys);
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
const sanitizedQuery = sanitizeQuery(req.body.query, req.accountability);
|
|
157
|
-
await service.deleteByQuery(sanitizedQuery);
|
|
158
|
-
}
|
|
159
|
-
return next();
|
|
160
|
-
}), respond);
|
|
161
|
-
router.delete('/:pk', asyncHandler(async (req, _res, next) => {
|
|
162
|
-
const service = new PoliciesService({
|
|
163
|
-
accountability: req.accountability,
|
|
164
|
-
schema: req.schema,
|
|
165
|
-
});
|
|
166
|
-
await service.deleteOne(req.params['pk']);
|
|
167
|
-
return next();
|
|
168
|
-
}), respond);
|
|
169
|
-
export default router;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate an AST based on a given collection and query
|
|
3
|
-
*/
|
|
4
|
-
import type { Accountability, Query, SchemaOverview } from '@directus/types';
|
|
5
|
-
import type { Knex } from 'knex';
|
|
6
|
-
import type { AST } from '../../types/index.js';
|
|
7
|
-
export interface GetAstFromQueryOptions {
|
|
8
|
-
collection: string;
|
|
9
|
-
query: Query;
|
|
10
|
-
accountability: Accountability | null;
|
|
11
|
-
}
|
|
12
|
-
export interface GetAstFromQueryContext {
|
|
13
|
-
knex: Knex;
|
|
14
|
-
schema: SchemaOverview;
|
|
15
|
-
}
|
|
16
|
-
export declare function getAstFromQuery(options: GetAstFromQueryOptions, context: GetAstFromQueryContext): Promise<AST>;
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate an AST based on a given collection and query
|
|
3
|
-
*/
|
|
4
|
-
import { cloneDeep, uniq } from 'lodash-es';
|
|
5
|
-
import { fetchAllowedFields } from '../../permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js';
|
|
6
|
-
import { parseFields } from './lib/parse-fields.js';
|
|
7
|
-
export async function getAstFromQuery(options, context) {
|
|
8
|
-
options.query = cloneDeep(options.query);
|
|
9
|
-
const ast = {
|
|
10
|
-
type: 'root',
|
|
11
|
-
name: options.collection,
|
|
12
|
-
query: options.query,
|
|
13
|
-
children: [],
|
|
14
|
-
cases: [],
|
|
15
|
-
};
|
|
16
|
-
let fields = ['*'];
|
|
17
|
-
if (options.query.fields) {
|
|
18
|
-
fields = options.query.fields;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* When using aggregate functions, you can't have any other regular fields
|
|
22
|
-
* selected. This makes sure you never end up in a non-aggregate fields selection error
|
|
23
|
-
*/
|
|
24
|
-
if (Object.keys(options.query.aggregate || {}).length > 0) {
|
|
25
|
-
fields = [];
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Similarly, when grouping on a specific field, you can't have other non-aggregated fields.
|
|
29
|
-
* The group query will override the fields query
|
|
30
|
-
*/
|
|
31
|
-
if (options.query.group) {
|
|
32
|
-
fields = options.query.group;
|
|
33
|
-
}
|
|
34
|
-
fields = uniq(fields);
|
|
35
|
-
const deep = options.query.deep || {};
|
|
36
|
-
// Prevent fields/deep from showing up in the query object in further use
|
|
37
|
-
delete options.query.fields;
|
|
38
|
-
delete options.query.deep;
|
|
39
|
-
if (!options.query.sort) {
|
|
40
|
-
// We'll default to the primary key for the standard sort output
|
|
41
|
-
let sortField = context.schema.collections[options.collection].primary;
|
|
42
|
-
// If a custom manual sort field is configured, use that
|
|
43
|
-
if (context.schema.collections[options.collection]?.sortField) {
|
|
44
|
-
sortField = context.schema.collections[options.collection].sortField;
|
|
45
|
-
}
|
|
46
|
-
if (options.accountability && options.accountability.admin === false) {
|
|
47
|
-
// Verify that the user has access to the sort field
|
|
48
|
-
const allowedFields = await fetchAllowedFields({
|
|
49
|
-
collection: options.collection,
|
|
50
|
-
action: 'read',
|
|
51
|
-
accountability: options.accountability,
|
|
52
|
-
}, context);
|
|
53
|
-
if (allowedFields.length === 0) {
|
|
54
|
-
sortField = null;
|
|
55
|
-
}
|
|
56
|
-
else if (allowedFields.includes('*') === false && allowedFields.includes(sortField) === false) {
|
|
57
|
-
// If the sort field is not allowed, default to the first allowed field
|
|
58
|
-
sortField = allowedFields[0];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// When group by is used, default to the first column provided in the group by clause
|
|
62
|
-
if (options.query.group?.[0]) {
|
|
63
|
-
sortField = options.query.group[0];
|
|
64
|
-
}
|
|
65
|
-
if (sortField) {
|
|
66
|
-
options.query.sort = [sortField];
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
// When no group by is supplied, but an aggregate function is used, only a single row will be
|
|
70
|
-
// returned. In those cases, we'll ignore the sort field altogether
|
|
71
|
-
if (options.query.aggregate && Object.keys(options.query.aggregate).length && !options.query.group?.[0]) {
|
|
72
|
-
delete options.query.sort;
|
|
73
|
-
}
|
|
74
|
-
ast.children = await parseFields({
|
|
75
|
-
parentCollection: options.collection,
|
|
76
|
-
fields,
|
|
77
|
-
query: options.query,
|
|
78
|
-
deep,
|
|
79
|
-
accountability: options.accountability,
|
|
80
|
-
}, context);
|
|
81
|
-
return ast;
|
|
82
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Accountability, Query, SchemaOverview } from '@directus/types';
|
|
2
|
-
import type { Knex } from 'knex';
|
|
3
|
-
export interface ConvertWildcardsOptions {
|
|
4
|
-
parentCollection: string;
|
|
5
|
-
fields: string[];
|
|
6
|
-
query: Query;
|
|
7
|
-
accountability: Accountability | null;
|
|
8
|
-
}
|
|
9
|
-
export interface ConvertWildCardsContext {
|
|
10
|
-
schema: SchemaOverview;
|
|
11
|
-
knex: Knex;
|
|
12
|
-
}
|
|
13
|
-
export declare function convertWildcards(options: ConvertWildcardsOptions, context: ConvertWildCardsContext): Promise<string[]>;
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { cloneDeep } from 'lodash-es';
|
|
2
|
-
import { fetchAllowedFields } from '../../../permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js';
|
|
3
|
-
import { getRelation } from '../utils/get-relation.js';
|
|
4
|
-
export async function convertWildcards(options, context) {
|
|
5
|
-
const fields = cloneDeep(options.fields);
|
|
6
|
-
const fieldsInCollection = Object.entries(context.schema.collections[options.parentCollection].fields).map(([name]) => name);
|
|
7
|
-
let allowedFields = fieldsInCollection;
|
|
8
|
-
if (options.accountability && options.accountability.admin === false) {
|
|
9
|
-
allowedFields = await fetchAllowedFields({
|
|
10
|
-
collection: options.parentCollection,
|
|
11
|
-
action: 'read',
|
|
12
|
-
accountability: options.accountability,
|
|
13
|
-
}, context);
|
|
14
|
-
}
|
|
15
|
-
if (!allowedFields || allowedFields.length === 0)
|
|
16
|
-
return [];
|
|
17
|
-
// In case of full read permissions
|
|
18
|
-
if (allowedFields[0] === '*')
|
|
19
|
-
allowedFields = fieldsInCollection;
|
|
20
|
-
for (let index = 0; index < fields.length; index++) {
|
|
21
|
-
const fieldKey = fields[index];
|
|
22
|
-
if (fieldKey.includes('*') === false)
|
|
23
|
-
continue;
|
|
24
|
-
if (fieldKey === '*') {
|
|
25
|
-
const aliases = Object.keys(options.query.alias ?? {});
|
|
26
|
-
// Set to all fields in collection
|
|
27
|
-
if (allowedFields.includes('*')) {
|
|
28
|
-
fields.splice(index, 1, ...fieldsInCollection, ...aliases);
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
// Set to all allowed fields
|
|
32
|
-
const allowedAliases = aliases.filter((fieldKey) => {
|
|
33
|
-
const name = options.query.alias[fieldKey];
|
|
34
|
-
return allowedFields.includes(name);
|
|
35
|
-
});
|
|
36
|
-
fields.splice(index, 1, ...allowedFields, ...allowedAliases);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
// Swap *.* case for *,<relational-field>.*,<another-relational>.*
|
|
40
|
-
if (fieldKey.includes('.') && fieldKey.split('.')[0] === '*') {
|
|
41
|
-
const parts = fieldKey.split('.');
|
|
42
|
-
const relationalFields = allowedFields.includes('*')
|
|
43
|
-
? context.schema.relations
|
|
44
|
-
.filter((relation) => relation.collection === options.parentCollection ||
|
|
45
|
-
relation.related_collection === options.parentCollection)
|
|
46
|
-
.map((relation) => {
|
|
47
|
-
const isMany = relation.collection === options.parentCollection;
|
|
48
|
-
return isMany ? relation.field : relation.meta?.one_field;
|
|
49
|
-
})
|
|
50
|
-
: allowedFields.filter((fieldKey) => !!getRelation(context.schema, options.parentCollection, fieldKey));
|
|
51
|
-
const nonRelationalFields = allowedFields.filter((fieldKey) => relationalFields.includes(fieldKey) === false);
|
|
52
|
-
const aliasFields = Object.keys(options.query.alias ?? {}).map((fieldKey) => {
|
|
53
|
-
const name = options.query.alias[fieldKey];
|
|
54
|
-
if (relationalFields.includes(name)) {
|
|
55
|
-
return `${fieldKey}.${parts.slice(1).join('.')}`;
|
|
56
|
-
}
|
|
57
|
-
return fieldKey;
|
|
58
|
-
});
|
|
59
|
-
fields.splice(index, 1, ...[
|
|
60
|
-
...relationalFields.map((relationalField) => {
|
|
61
|
-
return `${relationalField}.${parts.slice(1).join('.')}`;
|
|
62
|
-
}),
|
|
63
|
-
...nonRelationalFields,
|
|
64
|
-
...aliasFields,
|
|
65
|
-
]);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return fields;
|
|
69
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { Accountability, Query, SchemaOverview } from '@directus/types';
|
|
2
|
-
import type { Knex } from 'knex';
|
|
3
|
-
import type { FieldNode, FunctionFieldNode, NestedCollectionNode } from '../../../types/index.js';
|
|
4
|
-
export interface ParseFieldsOptions {
|
|
5
|
-
accountability: Accountability | null;
|
|
6
|
-
parentCollection: string;
|
|
7
|
-
fields: string[] | null;
|
|
8
|
-
query: Query;
|
|
9
|
-
deep?: Record<string, any>;
|
|
10
|
-
}
|
|
11
|
-
export interface ParseFieldsContext {
|
|
12
|
-
schema: SchemaOverview;
|
|
13
|
-
knex: Knex;
|
|
14
|
-
}
|
|
15
|
-
export declare function parseFields(options: ParseFieldsOptions, context: ParseFieldsContext): Promise<(NestedCollectionNode | FieldNode | FunctionFieldNode)[]>;
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { REGEX_BETWEEN_PARENS } from '@directus/constants';
|
|
2
|
-
import { isEmpty } from 'lodash-es';
|
|
3
|
-
import { fetchPermissions } from '../../../permissions/lib/fetch-permissions.js';
|
|
4
|
-
import { fetchPolicies } from '../../../permissions/lib/fetch-policies.js';
|
|
5
|
-
import { getRelationType } from '../../../utils/get-relation-type.js';
|
|
6
|
-
import { getDeepQuery } from '../utils/get-deep-query.js';
|
|
7
|
-
import { getRelatedCollection } from '../utils/get-related-collection.js';
|
|
8
|
-
import { getRelation } from '../utils/get-relation.js';
|
|
9
|
-
import { convertWildcards } from './convert-wildcards.js';
|
|
10
|
-
export async function parseFields(options, context) {
|
|
11
|
-
let { fields } = options;
|
|
12
|
-
if (!fields)
|
|
13
|
-
return [];
|
|
14
|
-
fields = await convertWildcards({
|
|
15
|
-
fields,
|
|
16
|
-
parentCollection: options.parentCollection,
|
|
17
|
-
query: options.query,
|
|
18
|
-
accountability: options.accountability,
|
|
19
|
-
}, context);
|
|
20
|
-
if (!fields || !Array.isArray(fields))
|
|
21
|
-
return [];
|
|
22
|
-
const children = [];
|
|
23
|
-
const policies = options.accountability && options.accountability.admin === false
|
|
24
|
-
? await fetchPolicies(options.accountability, context)
|
|
25
|
-
: null;
|
|
26
|
-
const relationalStructure = Object.create(null);
|
|
27
|
-
for (const fieldKey of fields) {
|
|
28
|
-
let name = fieldKey;
|
|
29
|
-
if (options.query.alias) {
|
|
30
|
-
// check for field alias (is one of the key)
|
|
31
|
-
if (name in options.query.alias) {
|
|
32
|
-
name = options.query.alias[fieldKey];
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const isRelational = name.includes('.') ||
|
|
36
|
-
// We'll always treat top level o2m fields as a related item. This is an alias field, otherwise it won't return
|
|
37
|
-
// anything
|
|
38
|
-
!!context.schema.relations.find((relation) => relation.related_collection === options.parentCollection && relation.meta?.one_field === name);
|
|
39
|
-
if (isRelational) {
|
|
40
|
-
// field is relational
|
|
41
|
-
const parts = fieldKey.split('.');
|
|
42
|
-
let rootField = parts[0];
|
|
43
|
-
let collectionScope = null;
|
|
44
|
-
// a2o related collection scoped field selector `fields=sections.section_id:headings.title`
|
|
45
|
-
if (rootField.includes(':')) {
|
|
46
|
-
const [key, scope] = rootField.split(':');
|
|
47
|
-
rootField = key;
|
|
48
|
-
collectionScope = scope;
|
|
49
|
-
}
|
|
50
|
-
if (rootField in relationalStructure === false) {
|
|
51
|
-
if (collectionScope) {
|
|
52
|
-
relationalStructure[rootField] = { [collectionScope]: [] };
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
relationalStructure[rootField] = [];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
if (parts.length > 1) {
|
|
59
|
-
const childKey = parts.slice(1).join('.');
|
|
60
|
-
if (collectionScope) {
|
|
61
|
-
if (collectionScope in relationalStructure[rootField] === false) {
|
|
62
|
-
relationalStructure[rootField][collectionScope] = [];
|
|
63
|
-
}
|
|
64
|
-
relationalStructure[rootField][collectionScope].push(childKey);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
relationalStructure[rootField].push(childKey);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
if (name.includes('(') && name.includes(')')) {
|
|
73
|
-
const columnName = name.match(REGEX_BETWEEN_PARENS)[1];
|
|
74
|
-
const foundField = context.schema.collections[options.parentCollection].fields[columnName];
|
|
75
|
-
if (foundField && foundField.type === 'alias') {
|
|
76
|
-
const foundRelation = context.schema.relations.find((relation) => relation.related_collection === options.parentCollection && relation.meta?.one_field === columnName);
|
|
77
|
-
if (foundRelation) {
|
|
78
|
-
children.push({
|
|
79
|
-
type: 'functionField',
|
|
80
|
-
name,
|
|
81
|
-
fieldKey,
|
|
82
|
-
query: {},
|
|
83
|
-
relatedCollection: foundRelation.collection,
|
|
84
|
-
whenCase: [],
|
|
85
|
-
cases: [],
|
|
86
|
-
});
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
children.push({ type: 'field', name, fieldKey, whenCase: [] });
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
for (const [fieldKey, nestedFields] of Object.entries(relationalStructure)) {
|
|
95
|
-
let fieldName = fieldKey;
|
|
96
|
-
if (options.query.alias && fieldKey in options.query.alias) {
|
|
97
|
-
fieldName = options.query.alias[fieldKey];
|
|
98
|
-
}
|
|
99
|
-
const relatedCollection = getRelatedCollection(context.schema, options.parentCollection, fieldName);
|
|
100
|
-
const relation = getRelation(context.schema, options.parentCollection, fieldName);
|
|
101
|
-
if (!relation)
|
|
102
|
-
continue;
|
|
103
|
-
const relationType = getRelationType({
|
|
104
|
-
relation,
|
|
105
|
-
collection: options.parentCollection,
|
|
106
|
-
field: fieldName,
|
|
107
|
-
});
|
|
108
|
-
if (!relationType)
|
|
109
|
-
continue;
|
|
110
|
-
let child = null;
|
|
111
|
-
if (relationType === 'a2o') {
|
|
112
|
-
const allowedCollections = relation.meta.one_allowed_collections;
|
|
113
|
-
child = {
|
|
114
|
-
type: 'a2o',
|
|
115
|
-
names: allowedCollections,
|
|
116
|
-
children: {},
|
|
117
|
-
query: {},
|
|
118
|
-
relatedKey: {},
|
|
119
|
-
parentKey: context.schema.collections[options.parentCollection].primary,
|
|
120
|
-
fieldKey: fieldKey,
|
|
121
|
-
relation: relation,
|
|
122
|
-
cases: {},
|
|
123
|
-
whenCase: [],
|
|
124
|
-
};
|
|
125
|
-
for (const relatedCollection of allowedCollections) {
|
|
126
|
-
child.children[relatedCollection] = await parseFields({
|
|
127
|
-
parentCollection: relatedCollection,
|
|
128
|
-
fields: Array.isArray(nestedFields)
|
|
129
|
-
? nestedFields
|
|
130
|
-
: nestedFields[relatedCollection] || [],
|
|
131
|
-
query: options.query,
|
|
132
|
-
deep: options.deep?.[`${fieldKey}:${relatedCollection}`],
|
|
133
|
-
accountability: options.accountability,
|
|
134
|
-
}, context);
|
|
135
|
-
child.query[relatedCollection] = getDeepQuery(options.deep?.[`${fieldKey}:${relatedCollection}`] || {});
|
|
136
|
-
child.relatedKey[relatedCollection] = context.schema.collections[relatedCollection].primary;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
else if (relatedCollection) {
|
|
140
|
-
if (options.accountability && options.accountability.admin === false && policies) {
|
|
141
|
-
const permissions = await fetchPermissions({
|
|
142
|
-
action: 'read',
|
|
143
|
-
collections: [relatedCollection],
|
|
144
|
-
policies: policies,
|
|
145
|
-
accountability: options.accountability,
|
|
146
|
-
}, context);
|
|
147
|
-
// Skip related collection if no permissions
|
|
148
|
-
if (permissions.length === 0) {
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// update query alias for children parseFields
|
|
153
|
-
const deepAlias = getDeepQuery(options.deep?.[fieldKey] || {})?.['alias'];
|
|
154
|
-
if (!isEmpty(deepAlias))
|
|
155
|
-
options.query.alias = deepAlias;
|
|
156
|
-
child = {
|
|
157
|
-
type: relationType,
|
|
158
|
-
name: relatedCollection,
|
|
159
|
-
fieldKey: fieldKey,
|
|
160
|
-
parentKey: context.schema.collections[options.parentCollection].primary,
|
|
161
|
-
relatedKey: context.schema.collections[relatedCollection].primary,
|
|
162
|
-
relation: relation,
|
|
163
|
-
query: getDeepQuery(options.deep?.[fieldKey] || {}),
|
|
164
|
-
children: await parseFields({
|
|
165
|
-
parentCollection: relatedCollection,
|
|
166
|
-
fields: nestedFields,
|
|
167
|
-
query: options.query,
|
|
168
|
-
deep: options.deep?.[fieldKey] || {},
|
|
169
|
-
accountability: options.accountability,
|
|
170
|
-
}, context),
|
|
171
|
-
cases: [],
|
|
172
|
-
whenCase: [],
|
|
173
|
-
};
|
|
174
|
-
if (relationType === 'o2m' && !child.query.sort) {
|
|
175
|
-
child.query.sort = [relation.meta?.sort_field || context.schema.collections[relation.collection].primary];
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (child) {
|
|
179
|
-
children.push(child);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
// Deduplicate any children fields that are included both as a regular field, and as a nested m2o field
|
|
183
|
-
const nestedCollectionNodes = children.filter((childNode) => childNode.type !== 'field');
|
|
184
|
-
return children.filter((childNode) => {
|
|
185
|
-
const existsAsNestedRelational = !!nestedCollectionNodes.find((nestedCollectionNode) => childNode.fieldKey === nestedCollectionNode.fieldKey);
|
|
186
|
-
if (childNode.type === 'field' && existsAsNestedRelational)
|
|
187
|
-
return false;
|
|
188
|
-
return true;
|
|
189
|
-
});
|
|
190
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Convert Deep query object to regular query object by ignoring all nested fields and returning the
|
|
3
|
-
* `_` prefixed fields as top level query fields
|
|
4
|
-
*
|
|
5
|
-
* @example
|
|
6
|
-
*
|
|
7
|
-
* ```js
|
|
8
|
-
* getDeepQuery({
|
|
9
|
-
* _sort: ['a']
|
|
10
|
-
* });
|
|
11
|
-
* // => { sort: ['a'] }
|
|
12
|
-
* ```
|
|
13
|
-
*/
|
|
14
|
-
export declare function getDeepQuery(query: Record<string, any>): Record<string, any>;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { mapKeys, omitBy } from 'lodash-es';
|
|
2
|
-
/**
|
|
3
|
-
* Convert Deep query object to regular query object by ignoring all nested fields and returning the
|
|
4
|
-
* `_` prefixed fields as top level query fields
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
*
|
|
8
|
-
* ```js
|
|
9
|
-
* getDeepQuery({
|
|
10
|
-
* _sort: ['a']
|
|
11
|
-
* });
|
|
12
|
-
* // => { sort: ['a'] }
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
export function getDeepQuery(query) {
|
|
16
|
-
return mapKeys(omitBy(query, (_value, key) => key.startsWith('_') === false), (_value, key) => key.substring(1));
|
|
17
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { getRelation } from './get-relation.js';
|
|
2
|
-
export function getRelatedCollection(schema, collection, field) {
|
|
3
|
-
const relation = getRelation(schema, collection, field);
|
|
4
|
-
if (!relation)
|
|
5
|
-
return null;
|
|
6
|
-
if (relation.collection === collection && relation.field === field) {
|
|
7
|
-
return relation.related_collection || null;
|
|
8
|
-
}
|
|
9
|
-
if (relation.related_collection === collection && relation.meta?.one_field === field) {
|
|
10
|
-
return relation.collection || null;
|
|
11
|
-
}
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export function getRelation(schema, collection, field) {
|
|
2
|
-
const relation = schema.relations.find((relation) => {
|
|
3
|
-
return ((relation.collection === collection && relation.field === field) ||
|
|
4
|
-
(relation.related_collection === collection && relation.meta?.one_field === field));
|
|
5
|
-
});
|
|
6
|
-
return relation;
|
|
7
|
-
}
|