@directus/api 21.0.0-rc.0 → 21.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +5 -5
- package/dist/auth/drivers/ldap.js +4 -4
- package/dist/auth/drivers/local.js +4 -4
- package/dist/auth/drivers/oauth2.js +4 -4
- package/dist/auth/drivers/openid.js +4 -2
- package/dist/cache.d.ts +0 -1
- package/dist/cache.js +7 -25
- package/dist/cli/commands/bootstrap/index.js +2 -8
- package/dist/cli/commands/init/index.js +10 -9
- package/dist/cli/utils/defaults.d.ts +11 -4
- package/dist/cli/utils/defaults.js +1 -7
- package/dist/constants.d.ts +1 -1
- package/dist/controllers/auth.js +16 -5
- package/dist/controllers/permissions.js +2 -14
- package/dist/controllers/roles.js +1 -22
- package/dist/controllers/tus.js +27 -13
- package/dist/controllers/users.js +55 -0
- package/dist/database/helpers/fn/types.d.ts +1 -2
- package/dist/database/helpers/fn/types.js +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.js +2 -4
- package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.js +3 -5
- package/dist/database/helpers/geometry/types.d.ts +1 -1
- package/dist/database/helpers/geometry/types.js +2 -4
- package/dist/database/index.js +11 -8
- package/dist/database/migrations/20240305A-change-useragent-type.js +1 -1
- package/dist/database/migrations/20240716A-update-files-date-fields.js +33 -0
- package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
- package/dist/database/run-ast.js +458 -0
- package/dist/flows.js +4 -3
- package/dist/logger/index.js +1 -1
- package/dist/middleware/authenticate.js +7 -2
- package/dist/middleware/cache.js +1 -1
- package/dist/middleware/check-ip.d.ts +2 -0
- package/dist/middleware/check-ip.js +37 -0
- package/dist/middleware/error-handler.d.ts +2 -2
- package/dist/middleware/error-handler.js +54 -51
- package/dist/middleware/get-permissions.d.ts +3 -0
- package/dist/middleware/get-permissions.js +10 -0
- package/dist/middleware/respond.js +1 -1
- package/dist/services/activity.js +10 -22
- package/dist/services/assets.d.ts +3 -2
- package/dist/services/assets.js +7 -15
- package/dist/services/authentication.js +18 -18
- package/dist/services/authorization.d.ts +17 -0
- package/dist/services/authorization.js +456 -0
- package/dist/services/collections.js +17 -18
- package/dist/services/fields.d.ts +4 -0
- package/dist/services/fields.js +53 -58
- package/dist/services/files/lib/get-sharp-instance.d.ts +2 -0
- package/dist/services/files/lib/get-sharp-instance.js +10 -0
- package/dist/services/files/utils/get-metadata.js +7 -6
- package/dist/services/files.js +8 -10
- package/dist/services/graphql/index.d.ts +3 -3
- package/dist/services/graphql/index.js +22 -126
- package/dist/services/graphql/subscription.js +4 -2
- package/dist/services/import-export.js +4 -18
- package/dist/services/index.d.ts +2 -3
- package/dist/services/index.js +2 -3
- package/dist/services/items.js +44 -115
- package/dist/services/mail/index.d.ts +1 -1
- package/dist/services/mail/index.js +9 -1
- package/dist/services/meta.js +23 -60
- package/dist/services/notifications.js +6 -14
- package/dist/services/payload.d.ts +10 -9
- package/dist/services/payload.js +3 -18
- package/dist/services/{permissions.d.ts → permissions/index.d.ts} +7 -5
- package/dist/services/{permissions.js → permissions/index.js} +54 -30
- package/dist/{permissions → services/permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
- package/dist/services/permissions/lib/with-app-minimal-permissions.js +13 -0
- package/dist/services/relations.d.ts +9 -1
- package/dist/services/relations.js +56 -31
- package/dist/services/roles.d.ts +12 -4
- package/dist/services/roles.js +424 -57
- package/dist/services/shares.d.ts +2 -0
- package/dist/services/shares.js +8 -12
- package/dist/services/specifications.d.ts +2 -2
- package/dist/services/specifications.js +27 -39
- package/dist/services/tus/data-store.js +4 -5
- package/dist/services/tus/server.d.ts +1 -1
- package/dist/services/tus/server.js +9 -2
- package/dist/services/users.d.ts +5 -1
- package/dist/services/users.js +161 -78
- package/dist/services/utils.js +7 -11
- package/dist/services/versions.d.ts +2 -0
- package/dist/services/versions.js +10 -34
- package/dist/telemetry/lib/get-report.js +2 -2
- package/dist/telemetry/utils/check-increased-user-limits.d.ts +7 -0
- package/dist/telemetry/utils/check-increased-user-limits.js +25 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +6 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.js +27 -0
- package/dist/telemetry/utils/get-role-counts-by-users.d.ts +11 -0
- package/dist/telemetry/utils/get-role-counts-by-users.js +34 -0
- package/dist/telemetry/utils/get-user-count.d.ts +8 -0
- package/dist/telemetry/utils/get-user-count.js +33 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +7 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.js +35 -0
- package/dist/types/ast.d.ts +1 -43
- package/dist/types/items.d.ts +0 -11
- package/dist/utils/apply-query.d.ts +3 -4
- package/dist/utils/apply-query.js +16 -39
- package/dist/utils/get-accountability-for-role.js +25 -16
- package/dist/utils/get-accountability-for-token.js +16 -17
- package/dist/utils/get-ast-from-query.d.ts +13 -0
- package/dist/utils/get-ast-from-query.js +297 -0
- package/dist/utils/get-cache-key.d.ts +1 -1
- package/dist/utils/get-cache-key.js +1 -12
- package/dist/utils/get-column.d.ts +1 -2
- package/dist/utils/get-column.js +0 -1
- package/dist/utils/get-permissions.d.ts +2 -0
- package/dist/utils/get-permissions.js +150 -0
- package/dist/utils/get-schema.js +3 -3
- package/dist/utils/get-service.js +1 -5
- package/dist/utils/merge-permissions-for-share.d.ts +4 -0
- package/dist/utils/merge-permissions-for-share.js +109 -0
- package/dist/utils/merge-permissions.d.ts +3 -0
- package/dist/utils/merge-permissions.js +95 -0
- package/dist/utils/reduce-schema.d.ts +6 -4
- package/dist/utils/reduce-schema.js +32 -16
- package/dist/websocket/authenticate.d.ts +2 -0
- package/dist/websocket/authenticate.js +12 -0
- package/dist/websocket/controllers/graphql.js +4 -1
- package/dist/websocket/controllers/hooks.js +0 -4
- package/dist/websocket/controllers/rest.js +2 -0
- package/dist/websocket/handlers/subscribe.js +2 -0
- package/dist/websocket/utils/items.d.ts +1 -1
- package/package.json +36 -37
- package/dist/controllers/access.d.ts +0 -2
- package/dist/controllers/access.js +0 -148
- package/dist/controllers/policies.d.ts +0 -2
- package/dist/controllers/policies.js +0 -169
- package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +0 -16
- package/dist/database/get-ast-from-query/get-ast-from-query.js +0 -82
- package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +0 -13
- package/dist/database/get-ast-from-query/lib/convert-wildcards.js +0 -69
- package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +0 -15
- package/dist/database/get-ast-from-query/lib/parse-fields.js +0 -190
- package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +0 -14
- package/dist/database/get-ast-from-query/utils/get-deep-query.js +0 -17
- package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-related-collection.js +0 -13
- package/dist/database/get-ast-from-query/utils/get-relation.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-relation.js +0 -7
- package/dist/database/migrations/20240710A-permissions-policies.js +0 -169
- package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
- package/dist/database/run-ast/lib/get-db-query.js +0 -208
- package/dist/database/run-ast/lib/parse-current-level.d.ts +0 -7
- package/dist/database/run-ast/lib/parse-current-level.js +0 -41
- package/dist/database/run-ast/run-ast.d.ts +0 -7
- package/dist/database/run-ast/run-ast.js +0 -107
- package/dist/database/run-ast/types.js +0 -1
- package/dist/database/run-ast/utils/apply-case-when.d.ts +0 -16
- package/dist/database/run-ast/utils/apply-case-when.js +0 -26
- package/dist/database/run-ast/utils/apply-parent-filters.d.ts +0 -3
- package/dist/database/run-ast/utils/apply-parent-filters.js +0 -55
- package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +0 -10
- package/dist/database/run-ast/utils/get-column-pre-processor.js +0 -57
- package/dist/database/run-ast/utils/get-field-alias.d.ts +0 -2
- package/dist/database/run-ast/utils/get-field-alias.js +0 -4
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +0 -5
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +0 -23
- package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +0 -3
- package/dist/database/run-ast/utils/merge-with-parent-items.js +0 -87
- package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +0 -3
- package/dist/database/run-ast/utils/remove-temporary-fields.js +0 -73
- package/dist/permissions/cache.d.ts +0 -2
- package/dist/permissions/cache.js +0 -23
- package/dist/permissions/lib/fetch-permissions.d.ts +0 -10
- package/dist/permissions/lib/fetch-permissions.js +0 -55
- package/dist/permissions/lib/fetch-policies.d.ts +0 -7
- package/dist/permissions/lib/fetch-policies.js +0 -28
- package/dist/permissions/lib/fetch-roles-tree.d.ts +0 -3
- package/dist/permissions/lib/fetch-roles-tree.js +0 -28
- package/dist/permissions/lib/with-app-minimal-permissions.js +0 -10
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +0 -7
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +0 -56
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +0 -3
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +0 -16
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +0 -8
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +0 -24
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +0 -9
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +0 -31
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +0 -16
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +0 -27
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +0 -10
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +0 -23
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
- package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/types.js +0 -1
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +0 -12
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +0 -32
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +0 -4
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +0 -29
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +0 -49
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +0 -3
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +0 -56
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +0 -8
- package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +0 -9
- package/dist/permissions/modules/process-ast/lib/inject-cases.js +0 -93
- package/dist/permissions/modules/process-ast/process-ast.d.ts +0 -9
- package/dist/permissions/modules/process-ast/process-ast.js +0 -39
- package/dist/permissions/modules/process-ast/types.d.ts +0 -24
- package/dist/permissions/modules/process-ast/types.js +0 -1
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +0 -7
- package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +0 -12
- package/dist/permissions/modules/process-ast/utils/dedupe-access.js +0 -30
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +0 -15
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +0 -50
- package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/find-related-collection.js +0 -9
- package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/flatten-filter.js +0 -34
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +0 -1
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +0 -3
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +0 -5
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +0 -7
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +0 -3
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +0 -16
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +0 -12
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +0 -28
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +0 -5
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +0 -12
- package/dist/permissions/modules/process-payload/process-payload.d.ts +0 -13
- package/dist/permissions/modules/process-payload/process-payload.js +0 -77
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +0 -12
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +0 -11
- package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +0 -9
- package/dist/permissions/modules/validate-access/lib/validate-item-access.js +0 -33
- package/dist/permissions/modules/validate-access/validate-access.d.ts +0 -14
- package/dist/permissions/modules/validate-access/validate-access.js +0 -28
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +0 -1
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +0 -8
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +0 -5
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +0 -10
- package/dist/permissions/types.d.ts +0 -6
- package/dist/permissions/types.js +0 -1
- package/dist/permissions/utils/create-default-accountability.d.ts +0 -2
- package/dist/permissions/utils/create-default-accountability.js +0 -11
- package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +0 -8
- package/dist/permissions/utils/extract-required-dynamic-variable-context.js +0 -27
- package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +0 -9
- package/dist/permissions/utils/fetch-dynamic-variable-context.js +0 -43
- package/dist/permissions/utils/filter-policies-by-ip.d.ts +0 -2
- package/dist/permissions/utils/filter-policies-by-ip.js +0 -15
- package/dist/permissions/utils/get-unaliased-field-key.d.ts +0 -5
- package/dist/permissions/utils/get-unaliased-field-key.js +0 -17
- package/dist/permissions/utils/process-permissions.d.ts +0 -7
- package/dist/permissions/utils/process-permissions.js +0 -9
- package/dist/permissions/utils/with-cache.d.ts +0 -10
- package/dist/permissions/utils/with-cache.js +0 -25
- package/dist/services/access.d.ts +0 -10
- package/dist/services/access.js +0 -43
- package/dist/services/policies.d.ts +0 -12
- package/dist/services/policies.js +0 -87
- package/dist/telemetry/utils/check-user-limits.d.ts +0 -5
- package/dist/telemetry/utils/check-user-limits.js +0 -19
- package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +0 -17
- package/dist/utils/fetch-user-count/fetch-access-lookup.js +0 -22
- package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +0 -16
- package/dist/utils/fetch-user-count/fetch-access-roles.js +0 -37
- package/dist/utils/fetch-user-count/fetch-active-users.d.ts +0 -6
- package/dist/utils/fetch-user-count/fetch-active-users.js +0 -3
- package/dist/utils/fetch-user-count/fetch-user-count.d.ts +0 -12
- package/dist/utils/fetch-user-count/fetch-user-count.js +0 -57
- package/dist/utils/fetch-user-count/get-user-count-query.d.ts +0 -20
- package/dist/utils/fetch-user-count/get-user-count-query.js +0 -17
- package/dist/utils/validate-user-count-integrity.d.ts +0 -13
- package/dist/utils/validate-user-count-integrity.js +0 -29
- /package/dist/database/migrations/{20240710A-permissions-policies.d.ts → 20240716A-update-files-date-fields.d.ts} +0 -0
|
@@ -6,15 +6,21 @@ import objectHash from 'object-hash';
|
|
|
6
6
|
import { getCache } from '../cache.js';
|
|
7
7
|
import getDatabase from '../database/index.js';
|
|
8
8
|
import emitter from '../emitter.js';
|
|
9
|
-
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
10
9
|
import { shouldClearCache } from '../utils/should-clear-cache.js';
|
|
11
10
|
import { ActivityService } from './activity.js';
|
|
11
|
+
import { AuthorizationService } from './authorization.js';
|
|
12
12
|
import { ItemsService } from './items.js';
|
|
13
13
|
import { PayloadService } from './payload.js';
|
|
14
14
|
import { RevisionsService } from './revisions.js';
|
|
15
15
|
export class VersionsService extends ItemsService {
|
|
16
|
+
authorizationService;
|
|
16
17
|
constructor(options) {
|
|
17
18
|
super('directus_versions', options);
|
|
19
|
+
this.authorizationService = new AuthorizationService({
|
|
20
|
+
accountability: this.accountability,
|
|
21
|
+
knex: this.knex,
|
|
22
|
+
schema: this.schema,
|
|
23
|
+
});
|
|
18
24
|
}
|
|
19
25
|
async validateCreateData(data) {
|
|
20
26
|
if (!data['key'])
|
|
@@ -49,31 +55,11 @@ export class VersionsService extends ItemsService {
|
|
|
49
55
|
});
|
|
50
56
|
}
|
|
51
57
|
// will throw an error if the accountability does not have permission to read the item
|
|
52
|
-
|
|
53
|
-
await validateAccess({
|
|
54
|
-
accountability: this.accountability,
|
|
55
|
-
action: 'read',
|
|
56
|
-
collection: data['collection'],
|
|
57
|
-
primaryKeys: [data['item']],
|
|
58
|
-
}, {
|
|
59
|
-
schema: this.schema,
|
|
60
|
-
knex: this.knex,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
58
|
+
await this.authorizationService.checkAccess('read', data['collection'], data['item']);
|
|
63
59
|
}
|
|
64
60
|
async getMainItem(collection, item, query) {
|
|
65
61
|
// will throw an error if the accountability does not have permission to read the item
|
|
66
|
-
|
|
67
|
-
await validateAccess({
|
|
68
|
-
accountability: this.accountability,
|
|
69
|
-
action: 'read',
|
|
70
|
-
collection,
|
|
71
|
-
primaryKeys: [item],
|
|
72
|
-
}, {
|
|
73
|
-
schema: this.schema,
|
|
74
|
-
knex: this.knex,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
62
|
+
await this.authorizationService.checkAccess('read', collection, item);
|
|
77
63
|
const itemsService = new ItemsService(collection, {
|
|
78
64
|
knex: this.knex,
|
|
79
65
|
accountability: this.accountability,
|
|
@@ -214,17 +200,7 @@ export class VersionsService extends ItemsService {
|
|
|
214
200
|
async promote(version, mainHash, fields) {
|
|
215
201
|
const { id, collection, item } = (await this.readOne(version));
|
|
216
202
|
// will throw an error if the accountability does not have permission to update the item
|
|
217
|
-
|
|
218
|
-
await validateAccess({
|
|
219
|
-
accountability: this.accountability,
|
|
220
|
-
action: 'update',
|
|
221
|
-
collection,
|
|
222
|
-
primaryKeys: [item],
|
|
223
|
-
}, {
|
|
224
|
-
schema: this.schema,
|
|
225
|
-
knex: this.knex,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
203
|
+
await this.authorizationService.checkAccess('update', collection, item);
|
|
228
204
|
const { outdated } = await this.verifyHash(collection, item, mainHash);
|
|
229
205
|
if (outdated) {
|
|
230
206
|
throw new UnprocessableContentError({
|
|
@@ -2,11 +2,11 @@ import { useEnv } from '@directus/env';
|
|
|
2
2
|
import { version } from 'directus/version';
|
|
3
3
|
import { getHelpers } from '../../database/helpers/index.js';
|
|
4
4
|
import { getDatabase, getDatabaseClient } from '../../database/index.js';
|
|
5
|
-
import { fetchUserCount } from '../../utils/fetch-user-count/fetch-user-count.js';
|
|
6
5
|
import { getExtensionCount } from '../utils/get-extension-count.js';
|
|
7
6
|
import { getFieldCount } from '../utils/get-field-count.js';
|
|
8
7
|
import { getFilesizeSum } from '../utils/get-filesize-sum.js';
|
|
9
8
|
import { getItemCount } from '../utils/get-item-count.js';
|
|
9
|
+
import { getUserCount } from '../utils/get-user-count.js';
|
|
10
10
|
import { getUserItemCount } from '../utils/get-user-item-count.js';
|
|
11
11
|
const basicCountTasks = [
|
|
12
12
|
{ collection: 'directus_dashboards' },
|
|
@@ -27,7 +27,7 @@ export const getReport = async () => {
|
|
|
27
27
|
const helpers = getHelpers(db);
|
|
28
28
|
const [basicCounts, userCounts, userItemCount, fieldsCounts, extensionsCounts, databaseSize, filesizes] = await Promise.all([
|
|
29
29
|
getItemCount(db, basicCountTasks),
|
|
30
|
-
|
|
30
|
+
getUserCount(db),
|
|
31
31
|
getUserItemCount(db),
|
|
32
32
|
getFieldCount(db),
|
|
33
33
|
getExtensionCount(db),
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PrimaryKey } from '@directus/types';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
import { type AccessTypeCount } from './get-user-count.js';
|
|
4
|
+
/**
|
|
5
|
+
* Ensure that user limits are not reached
|
|
6
|
+
*/
|
|
7
|
+
export declare function checkIncreasedUserLimits(db: Knex, increasedUserCounts: AccessTypeCount, ignoreIds?: PrimaryKey[]): Promise<void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
2
|
+
import { LimitExceededError } from '@directus/errors';
|
|
3
|
+
import { getUserCount } from './get-user-count.js';
|
|
4
|
+
const env = useEnv();
|
|
5
|
+
/**
|
|
6
|
+
* Ensure that user limits are not reached
|
|
7
|
+
*/
|
|
8
|
+
export async function checkIncreasedUserLimits(db, increasedUserCounts, ignoreIds = []) {
|
|
9
|
+
if (!increasedUserCounts.admin && !increasedUserCounts.app && !increasedUserCounts.api)
|
|
10
|
+
return;
|
|
11
|
+
const userCounts = await getUserCount(db, ignoreIds);
|
|
12
|
+
// Admins have full permissions, therefore should count under app access limit
|
|
13
|
+
const existingAppUsersCount = userCounts.admin + userCounts.app;
|
|
14
|
+
const newAppUsersCount = increasedUserCounts.admin + increasedUserCounts.app;
|
|
15
|
+
if (increasedUserCounts.admin > 0 &&
|
|
16
|
+
increasedUserCounts.admin + userCounts.admin > Number(env['USERS_ADMIN_ACCESS_LIMIT'])) {
|
|
17
|
+
throw new LimitExceededError({ category: 'Active Admin users' });
|
|
18
|
+
}
|
|
19
|
+
if (newAppUsersCount > 0 && newAppUsersCount + existingAppUsersCount > Number(env['USERS_APP_ACCESS_LIMIT'])) {
|
|
20
|
+
throw new LimitExceededError({ category: 'Active App users' });
|
|
21
|
+
}
|
|
22
|
+
if (increasedUserCounts.api > 0 && increasedUserCounts.api + userCounts.api > Number(env['USERS_API_ACCESS_LIMIT'])) {
|
|
23
|
+
throw new LimitExceededError({ category: 'Active API users' });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { toBoolean } from '@directus/utils';
|
|
2
|
+
import {} from './get-user-count.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get the role type counts by role IDs
|
|
5
|
+
*/
|
|
6
|
+
export async function getRoleCountsByRoles(db, roles) {
|
|
7
|
+
const counts = {
|
|
8
|
+
admin: 0,
|
|
9
|
+
app: 0,
|
|
10
|
+
api: 0,
|
|
11
|
+
};
|
|
12
|
+
const result = (await db.select('id', 'admin_access', 'app_access').from('directus_roles').whereIn('id', roles));
|
|
13
|
+
for (const role of result) {
|
|
14
|
+
const adminAccess = toBoolean(role.admin_access);
|
|
15
|
+
const appAccess = toBoolean(role.app_access);
|
|
16
|
+
if (adminAccess) {
|
|
17
|
+
counts.admin++;
|
|
18
|
+
}
|
|
19
|
+
else if (appAccess) {
|
|
20
|
+
counts.app++;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
counts.api++;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return counts;
|
|
27
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PrimaryKey } from '@directus/types';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
import type { AccessTypeCount } from './get-user-count.js';
|
|
4
|
+
type CountOptions = {
|
|
5
|
+
inactiveUsers?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Get the role type counts by user IDs
|
|
9
|
+
*/
|
|
10
|
+
export declare function getRoleCountsByUsers(db: Knex, userIds: PrimaryKey[], options?: CountOptions): Promise<AccessTypeCount>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { toBoolean } from '@directus/utils';
|
|
2
|
+
/**
|
|
3
|
+
* Get the role type counts by user IDs
|
|
4
|
+
*/
|
|
5
|
+
export async function getRoleCountsByUsers(db, userIds, options = {}) {
|
|
6
|
+
const counts = {
|
|
7
|
+
admin: 0,
|
|
8
|
+
app: 0,
|
|
9
|
+
api: 0,
|
|
10
|
+
};
|
|
11
|
+
const result = await db
|
|
12
|
+
.count('directus_users.id', { as: 'count' })
|
|
13
|
+
.select('directus_roles.admin_access', 'directus_roles.app_access')
|
|
14
|
+
.from('directus_users')
|
|
15
|
+
.whereIn('directus_users.id', userIds)
|
|
16
|
+
.andWhere('directus_users.status', options.inactiveUsers ? '!=' : '=', 'active')
|
|
17
|
+
.leftJoin('directus_roles', 'directus_users.role', '=', 'directus_roles.id')
|
|
18
|
+
.groupBy('directus_roles.admin_access', 'directus_roles.app_access');
|
|
19
|
+
for (const record of result) {
|
|
20
|
+
const adminAccess = toBoolean(record.admin_access);
|
|
21
|
+
const appAccess = toBoolean(record.app_access);
|
|
22
|
+
const count = Number(record.count);
|
|
23
|
+
if (adminAccess) {
|
|
24
|
+
counts.admin += count;
|
|
25
|
+
}
|
|
26
|
+
else if (appAccess) {
|
|
27
|
+
counts.app += count;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
counts.api += count;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return counts;
|
|
34
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PrimaryKey } from '@directus/types';
|
|
2
|
+
import { type Knex } from 'knex';
|
|
3
|
+
export interface AccessTypeCount {
|
|
4
|
+
admin: number;
|
|
5
|
+
app: number;
|
|
6
|
+
api: number;
|
|
7
|
+
}
|
|
8
|
+
export declare const getUserCount: (db: Knex, ignoreIds?: PrimaryKey[]) => Promise<AccessTypeCount>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { toBoolean } from '@directus/utils';
|
|
2
|
+
import {} from 'knex';
|
|
3
|
+
export const getUserCount = async (db, ignoreIds = []) => {
|
|
4
|
+
const counts = {
|
|
5
|
+
admin: 0,
|
|
6
|
+
app: 0,
|
|
7
|
+
api: 0,
|
|
8
|
+
};
|
|
9
|
+
const result = (await db
|
|
10
|
+
.count('directus_users.id', { as: 'count' })
|
|
11
|
+
.select('directus_roles.admin_access', 'directus_roles.app_access')
|
|
12
|
+
.from('directus_users')
|
|
13
|
+
.whereNotIn('directus_users.id', ignoreIds)
|
|
14
|
+
.andWhere('directus_users.status', 'active')
|
|
15
|
+
.leftJoin('directus_roles', 'directus_users.role', '=', 'directus_roles.id')
|
|
16
|
+
.where('directus_users.status', '=', 'active')
|
|
17
|
+
.groupBy('directus_roles.admin_access', 'directus_roles.app_access'));
|
|
18
|
+
for (const record of result) {
|
|
19
|
+
const adminAccess = toBoolean(record.admin_access);
|
|
20
|
+
const appAccess = toBoolean(record.app_access);
|
|
21
|
+
const count = Number(record.count);
|
|
22
|
+
if (adminAccess) {
|
|
23
|
+
counts.admin += count;
|
|
24
|
+
}
|
|
25
|
+
else if (appAccess) {
|
|
26
|
+
counts.app += count;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
counts.api += count;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return counts;
|
|
33
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PrimaryKey } from '@directus/types';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
import { type AccessTypeCount } from './get-user-count.js';
|
|
4
|
+
/**
|
|
5
|
+
* Get the user type counts by role IDs
|
|
6
|
+
*/
|
|
7
|
+
export declare function getUserCountsByRoles(db: Knex, roleIds: PrimaryKey[]): Promise<AccessTypeCount>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { toBoolean } from '@directus/utils';
|
|
2
|
+
import {} from './get-user-count.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get the user type counts by role IDs
|
|
5
|
+
*/
|
|
6
|
+
export async function getUserCountsByRoles(db, roleIds) {
|
|
7
|
+
const counts = {
|
|
8
|
+
admin: 0,
|
|
9
|
+
app: 0,
|
|
10
|
+
api: 0,
|
|
11
|
+
};
|
|
12
|
+
const result = (await db
|
|
13
|
+
.count('directus_users.id', { as: 'count' })
|
|
14
|
+
.select('directus_roles.admin_access', 'directus_roles.app_access')
|
|
15
|
+
.from('directus_users')
|
|
16
|
+
.whereIn('directus_roles.id', roleIds)
|
|
17
|
+
.andWhere('directus_users.status', '=', 'active')
|
|
18
|
+
.leftJoin('directus_roles', 'directus_users.role', '=', 'directus_roles.id')
|
|
19
|
+
.groupBy('directus_roles.admin_access', 'directus_roles.app_access'));
|
|
20
|
+
for (const record of result) {
|
|
21
|
+
const adminAccess = toBoolean(record.admin_access);
|
|
22
|
+
const appAccess = toBoolean(record.app_access);
|
|
23
|
+
const count = Number(record.count);
|
|
24
|
+
if (adminAccess) {
|
|
25
|
+
counts.admin += count;
|
|
26
|
+
}
|
|
27
|
+
else if (appAccess) {
|
|
28
|
+
counts.app += count;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
counts.api += count;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return counts;
|
|
35
|
+
}
|
package/dist/types/ast.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Query, Relation } from '@directus/types';
|
|
2
2
|
export type M2ONode = {
|
|
3
3
|
type: 'm2o';
|
|
4
4
|
name: string;
|
|
@@ -8,14 +8,6 @@ export type M2ONode = {
|
|
|
8
8
|
relation: Relation;
|
|
9
9
|
parentKey: string;
|
|
10
10
|
relatedKey: string;
|
|
11
|
-
/**
|
|
12
|
-
* Which permission cases have to be met on the current item for this field to return a value
|
|
13
|
-
*/
|
|
14
|
-
whenCase: number[];
|
|
15
|
-
/**
|
|
16
|
-
* Permissions rules for the item access of the children of this item.
|
|
17
|
-
*/
|
|
18
|
-
cases: Filter[];
|
|
19
11
|
};
|
|
20
12
|
export type A2MNode = {
|
|
21
13
|
type: 'a2o';
|
|
@@ -32,16 +24,6 @@ export type A2MNode = {
|
|
|
32
24
|
fieldKey: string;
|
|
33
25
|
relation: Relation;
|
|
34
26
|
parentKey: string;
|
|
35
|
-
/**
|
|
36
|
-
* Which permission cases have to be met on the current item for this field to return a value
|
|
37
|
-
*/
|
|
38
|
-
whenCase: number[];
|
|
39
|
-
/**
|
|
40
|
-
* Permissions rules for the item access of the children of this item.
|
|
41
|
-
*/
|
|
42
|
-
cases: {
|
|
43
|
-
[collection: string]: Filter[];
|
|
44
|
-
};
|
|
45
27
|
};
|
|
46
28
|
export type O2MNode = {
|
|
47
29
|
type: 'o2m';
|
|
@@ -52,24 +34,12 @@ export type O2MNode = {
|
|
|
52
34
|
relation: Relation;
|
|
53
35
|
parentKey: string;
|
|
54
36
|
relatedKey: string;
|
|
55
|
-
/**
|
|
56
|
-
* Which permission cases have to be met on the current item for this field to return a value
|
|
57
|
-
*/
|
|
58
|
-
whenCase: number[];
|
|
59
|
-
/**
|
|
60
|
-
* Permissions rules for the item access of the children of this item.
|
|
61
|
-
*/
|
|
62
|
-
cases: Filter[];
|
|
63
37
|
};
|
|
64
38
|
export type NestedCollectionNode = M2ONode | O2MNode | A2MNode;
|
|
65
39
|
export type FieldNode = {
|
|
66
40
|
type: 'field';
|
|
67
41
|
name: string;
|
|
68
42
|
fieldKey: string;
|
|
69
|
-
/**
|
|
70
|
-
* Which permission cases have to be met on the current item for this field to return a value
|
|
71
|
-
*/
|
|
72
|
-
whenCase: number[];
|
|
73
43
|
};
|
|
74
44
|
export type FunctionFieldNode = {
|
|
75
45
|
type: 'functionField';
|
|
@@ -77,22 +47,10 @@ export type FunctionFieldNode = {
|
|
|
77
47
|
fieldKey: string;
|
|
78
48
|
query: Query;
|
|
79
49
|
relatedCollection: string;
|
|
80
|
-
/**
|
|
81
|
-
* Which permission cases have to be met on the current item for this field to return a value
|
|
82
|
-
*/
|
|
83
|
-
whenCase: number[];
|
|
84
|
-
/**
|
|
85
|
-
* Permissions rules for the item access of the related collection of this item.
|
|
86
|
-
*/
|
|
87
|
-
cases: Filter[];
|
|
88
50
|
};
|
|
89
51
|
export type AST = {
|
|
90
52
|
type: 'root';
|
|
91
53
|
name: string;
|
|
92
54
|
children: (NestedCollectionNode | FieldNode | FunctionFieldNode)[];
|
|
93
55
|
query: Query;
|
|
94
|
-
/**
|
|
95
|
-
* Permissions rules for the item access of the children of this item.
|
|
96
|
-
*/
|
|
97
|
-
cases: Filter[];
|
|
98
56
|
};
|
package/dist/types/items.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { DirectusError } from '@directus/errors';
|
|
2
2
|
import type { EventContext, PrimaryKey } from '@directus/types';
|
|
3
3
|
import type { MutationTracker } from '../services/items.js';
|
|
4
|
-
import type { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
|
|
5
4
|
export type MutationOptions = {
|
|
6
5
|
/**
|
|
7
6
|
* Callback function that's fired whenever a revision is made in the mutation
|
|
@@ -34,16 +33,6 @@ export type MutationOptions = {
|
|
|
34
33
|
mutationTracker?: MutationTracker | undefined;
|
|
35
34
|
preMutationError?: DirectusError | undefined;
|
|
36
35
|
bypassAutoIncrementSequenceReset?: boolean;
|
|
37
|
-
/**
|
|
38
|
-
* Indicate that the top level mutation needs to perform a user integrity check before commiting the transaction
|
|
39
|
-
* This is a combination of flags
|
|
40
|
-
* @see UserIntegrityCheckFlag
|
|
41
|
-
*/
|
|
42
|
-
userIntegrityCheckFlags?: UserIntegrityCheckFlag;
|
|
43
|
-
/**
|
|
44
|
-
* Callback function that is called whenever a mutation requires a user integrity check to be made
|
|
45
|
-
*/
|
|
46
|
-
onRequireUserIntegrityCheck?: ((flags: UserIntegrityCheckFlag) => void) | undefined;
|
|
47
36
|
};
|
|
48
37
|
export type ActionEventParams = {
|
|
49
38
|
event: string | string[];
|
|
@@ -5,7 +5,7 @@ export declare const generateAlias: (size?: number | undefined) => string;
|
|
|
5
5
|
/**
|
|
6
6
|
* Apply the Query to a given Knex query builder instance
|
|
7
7
|
*/
|
|
8
|
-
export default function applyQuery(knex: Knex, collection: string, dbQuery: Knex.QueryBuilder, query: Query, schema: SchemaOverview,
|
|
8
|
+
export default function applyQuery(knex: Knex, collection: string, dbQuery: Knex.QueryBuilder, query: Query, schema: SchemaOverview, options?: {
|
|
9
9
|
aliasMap?: AliasMap;
|
|
10
10
|
isInnerQuery?: boolean;
|
|
11
11
|
hasMultiRelationalSort?: boolean | undefined;
|
|
@@ -32,11 +32,10 @@ export declare function applySort(knex: Knex, schema: SchemaOverview, rootQuery:
|
|
|
32
32
|
};
|
|
33
33
|
export declare function applyLimit(knex: Knex, rootQuery: Knex.QueryBuilder, limit: any): void;
|
|
34
34
|
export declare function applyOffset(knex: Knex, rootQuery: Knex.QueryBuilder, offset: any): void;
|
|
35
|
-
export declare function applyFilter(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootFilter: Filter, collection: string, aliasMap: AliasMap
|
|
35
|
+
export declare function applyFilter(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootFilter: Filter, collection: string, aliasMap: AliasMap): {
|
|
36
36
|
query: Knex.QueryBuilder<any, any>;
|
|
37
37
|
hasJoins: boolean;
|
|
38
38
|
hasMultiRelationalFilter: boolean;
|
|
39
39
|
};
|
|
40
|
-
export declare function applySearch(knex: Knex, schema: SchemaOverview, dbQuery: Knex.QueryBuilder, searchQuery: string, collection: string): void
|
|
40
|
+
export declare function applySearch(knex: Knex, schema: SchemaOverview, dbQuery: Knex.QueryBuilder, searchQuery: string, collection: string): Promise<void>;
|
|
41
41
|
export declare function applyAggregate(schema: SchemaOverview, dbQuery: Knex.QueryBuilder, aggregate: Aggregate, collection: string, hasJoins: boolean): void;
|
|
42
|
-
export declare function joinFilterWithCases(filter: Filter | null | undefined, cases: Filter[]): Filter | null;
|
|
@@ -14,7 +14,7 @@ export const generateAlias = customAlphabet('abcdefghijklmnopqrstuvwxyz', 5);
|
|
|
14
14
|
/**
|
|
15
15
|
* Apply the Query to a given Knex query builder instance
|
|
16
16
|
*/
|
|
17
|
-
export default function applyQuery(knex, collection, dbQuery, query, schema,
|
|
17
|
+
export default function applyQuery(knex, collection, dbQuery, query, schema, options) {
|
|
18
18
|
const aliasMap = options?.aliasMap ?? Object.create(null);
|
|
19
19
|
let hasJoins = false;
|
|
20
20
|
let hasMultiRelationalFilter = false;
|
|
@@ -37,14 +37,8 @@ export default function applyQuery(knex, collection, dbQuery, query, schema, cas
|
|
|
37
37
|
if (query.group) {
|
|
38
38
|
dbQuery.groupBy(query.group.map((column) => getColumn(knex, collection, column, false, schema)));
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// rules. You should be able to read an item if one or more of the cases matches. The actual case
|
|
43
|
-
// is reused in the column selection case/when to dynamically return or nullify the field values
|
|
44
|
-
// you're actually allowed to read
|
|
45
|
-
const filter = joinFilterWithCases(query.filter, cases);
|
|
46
|
-
if (filter) {
|
|
47
|
-
const filterResult = applyFilter(knex, schema, dbQuery, filter, collection, aliasMap, cases);
|
|
40
|
+
if (query.filter) {
|
|
41
|
+
const filterResult = applyFilter(knex, schema, dbQuery, query.filter, collection, aliasMap);
|
|
48
42
|
if (!hasJoins) {
|
|
49
43
|
hasJoins = filterResult.hasJoins;
|
|
50
44
|
}
|
|
@@ -232,7 +226,7 @@ export function applyOffset(knex, rootQuery, offset) {
|
|
|
232
226
|
getHelpers(knex).schema.applyOffset(rootQuery, offset);
|
|
233
227
|
}
|
|
234
228
|
}
|
|
235
|
-
export function applyFilter(knex, schema, rootQuery, rootFilter, collection, aliasMap
|
|
229
|
+
export function applyFilter(knex, schema, rootQuery, rootFilter, collection, aliasMap) {
|
|
236
230
|
const helpers = getHelpers(knex);
|
|
237
231
|
const relations = schema.relations;
|
|
238
232
|
let hasJoins = false;
|
|
@@ -241,23 +235,12 @@ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, ali
|
|
|
241
235
|
addWhereClauses(knex, rootQuery, rootFilter, collection);
|
|
242
236
|
return { query: rootQuery, hasJoins, hasMultiRelationalFilter };
|
|
243
237
|
function addJoins(dbQuery, filter, collection) {
|
|
244
|
-
|
|
245
|
-
for (let [key, value] of Object.entries(filter)) {
|
|
238
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
246
239
|
if (key === '_or' || key === '_and') {
|
|
247
240
|
// If the _or array contains an empty object (full permissions), we should short-circuit and ignore all other
|
|
248
241
|
// permission checks, as {} already matches full permissions.
|
|
249
242
|
if (key === '_or' && value.some((subFilter) => Object.keys(subFilter).length === 0)) {
|
|
250
|
-
|
|
251
|
-
// or the length of value is 1, ie. only the empty filter.
|
|
252
|
-
// If the length is more than one it means that some items (and fields) might now be available, so
|
|
253
|
-
// the joins are required for the case/when construction.
|
|
254
|
-
if (value !== cases || value.length === 1) {
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
// Otherwise we can at least filter out all empty filters that would not add joins anyway
|
|
259
|
-
value = value.filter((subFilter) => Object.keys(subFilter).length > 0);
|
|
260
|
-
}
|
|
243
|
+
continue;
|
|
261
244
|
}
|
|
262
245
|
value.forEach((subFilter) => {
|
|
263
246
|
addJoins(dbQuery, subFilter, collection);
|
|
@@ -328,7 +311,7 @@ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, ali
|
|
|
328
311
|
.select({ [field]: column })
|
|
329
312
|
.from(collection)
|
|
330
313
|
.whereNotNull(column);
|
|
331
|
-
applyQuery(knex, relation.collection, subQueryKnex, { filter }, schema
|
|
314
|
+
applyQuery(knex, relation.collection, subQueryKnex, { filter }, schema);
|
|
332
315
|
};
|
|
333
316
|
const childKey = Object.keys(value)?.[0];
|
|
334
317
|
if (childKey === '_none') {
|
|
@@ -408,11 +391,17 @@ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, ali
|
|
|
408
391
|
// Knex supports "raw" in the columnName parameter, but isn't typed as such. Too bad..
|
|
409
392
|
// See https://github.com/knex/knex/issues/4518 @TODO remove as any once knex is updated
|
|
410
393
|
// These operators don't rely on a value, and can thus be used without one (eg `?filter[field][_null]`)
|
|
411
|
-
if ((operator === '_null' && compareValue !== false) ||
|
|
394
|
+
if ((operator === '_null' && compareValue !== false) ||
|
|
395
|
+
(operator === '_nnull' && compareValue === false) ||
|
|
396
|
+
(operator === '_eq' && compareValue === null)) {
|
|
412
397
|
dbQuery[logical].whereNull(selectionRaw);
|
|
398
|
+
return;
|
|
413
399
|
}
|
|
414
|
-
if ((operator === '_nnull' && compareValue !== false) ||
|
|
400
|
+
if ((operator === '_nnull' && compareValue !== false) ||
|
|
401
|
+
(operator === '_null' && compareValue === false) ||
|
|
402
|
+
(operator === '_neq' && compareValue === null)) {
|
|
415
403
|
dbQuery[logical].whereNotNull(selectionRaw);
|
|
404
|
+
return;
|
|
416
405
|
}
|
|
417
406
|
if ((operator === '_empty' && compareValue !== false) || (operator === '_nempty' && compareValue === false)) {
|
|
418
407
|
dbQuery[logical].andWhere((query) => {
|
|
@@ -568,7 +557,7 @@ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, ali
|
|
|
568
557
|
}
|
|
569
558
|
}
|
|
570
559
|
}
|
|
571
|
-
export function applySearch(knex, schema, dbQuery, searchQuery, collection) {
|
|
560
|
+
export async function applySearch(knex, schema, dbQuery, searchQuery, collection) {
|
|
572
561
|
const { number: numberHelper } = getHelpers(knex);
|
|
573
562
|
const fields = Object.entries(schema.collections[collection].fields);
|
|
574
563
|
dbQuery.andWhere(function () {
|
|
@@ -644,18 +633,6 @@ export function applyAggregate(schema, dbQuery, aggregate, collection, hasJoins)
|
|
|
644
633
|
}
|
|
645
634
|
}
|
|
646
635
|
}
|
|
647
|
-
export function joinFilterWithCases(filter, cases) {
|
|
648
|
-
if (cases.length > 0 && !filter) {
|
|
649
|
-
return { _or: cases };
|
|
650
|
-
}
|
|
651
|
-
else if (filter && cases.length === 0) {
|
|
652
|
-
return filter ?? null;
|
|
653
|
-
}
|
|
654
|
-
else if (filter && cases.length > 0) {
|
|
655
|
-
return { _and: [filter, { _or: cases }] };
|
|
656
|
-
}
|
|
657
|
-
return null;
|
|
658
|
-
}
|
|
659
636
|
function getFilterPath(key, value) {
|
|
660
637
|
const path = [key];
|
|
661
638
|
const childKey = Object.keys(value)[0];
|
|
@@ -1,31 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { fetchGlobalAccess } from '../permissions/modules/fetch-global-access/fetch-global-access.js';
|
|
3
|
-
import { createDefaultAccountability } from '../permissions/utils/create-default-accountability.js';
|
|
1
|
+
import { getPermissions } from './get-permissions.js';
|
|
4
2
|
export async function getAccountabilityForRole(role, context) {
|
|
5
|
-
let generatedAccountability;
|
|
3
|
+
let generatedAccountability = context.accountability;
|
|
6
4
|
if (role === null) {
|
|
7
|
-
generatedAccountability =
|
|
5
|
+
generatedAccountability = {
|
|
6
|
+
role: null,
|
|
7
|
+
user: null,
|
|
8
|
+
admin: false,
|
|
9
|
+
app: false,
|
|
10
|
+
};
|
|
11
|
+
generatedAccountability.permissions = await getPermissions(generatedAccountability, context.schema);
|
|
8
12
|
}
|
|
9
13
|
else if (role === 'system') {
|
|
10
|
-
generatedAccountability =
|
|
14
|
+
generatedAccountability = {
|
|
15
|
+
user: null,
|
|
16
|
+
role: null,
|
|
11
17
|
admin: true,
|
|
12
18
|
app: true,
|
|
13
|
-
|
|
19
|
+
permissions: [],
|
|
20
|
+
};
|
|
14
21
|
}
|
|
15
22
|
else {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
const roleInfo = await context.database
|
|
24
|
+
.select(['app_access', 'admin_access'])
|
|
25
|
+
.from('directus_roles')
|
|
26
|
+
.where({ id: role })
|
|
27
|
+
.first();
|
|
28
|
+
if (!roleInfo) {
|
|
20
29
|
throw new Error(`Configured role "${role}" isn't a valid role ID or doesn't exist.`);
|
|
21
30
|
}
|
|
22
|
-
|
|
23
|
-
generatedAccountability = createDefaultAccountability({
|
|
31
|
+
generatedAccountability = {
|
|
24
32
|
role,
|
|
25
|
-
roles,
|
|
26
33
|
user: null,
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
admin: roleInfo.admin_access === 1 || roleInfo.admin_access === '1' || roleInfo.admin_access === true,
|
|
35
|
+
app: roleInfo.app_access === 1 || roleInfo.app_access === '1' || roleInfo.app_access === true,
|
|
36
|
+
};
|
|
37
|
+
generatedAccountability.permissions = await getPermissions(generatedAccountability, context.schema);
|
|
29
38
|
}
|
|
30
39
|
return generatedAccountability;
|
|
31
40
|
}
|