@directus/api 21.0.0-rc.0 → 21.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +5 -5
- package/dist/auth/drivers/ldap.js +4 -4
- package/dist/auth/drivers/local.js +4 -4
- package/dist/auth/drivers/oauth2.js +4 -4
- package/dist/auth/drivers/openid.js +4 -2
- package/dist/cache.d.ts +0 -1
- package/dist/cache.js +7 -25
- package/dist/cli/commands/bootstrap/index.js +2 -8
- package/dist/cli/commands/init/index.js +10 -9
- package/dist/cli/utils/defaults.d.ts +11 -4
- package/dist/cli/utils/defaults.js +1 -7
- package/dist/constants.d.ts +1 -1
- package/dist/controllers/auth.js +16 -5
- package/dist/controllers/permissions.js +2 -14
- package/dist/controllers/roles.js +1 -22
- package/dist/controllers/tus.js +27 -13
- package/dist/controllers/users.js +55 -0
- package/dist/database/helpers/fn/types.d.ts +1 -2
- package/dist/database/helpers/fn/types.js +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.js +2 -4
- package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.js +3 -5
- package/dist/database/helpers/geometry/types.d.ts +1 -1
- package/dist/database/helpers/geometry/types.js +2 -4
- package/dist/database/index.js +11 -8
- package/dist/database/migrations/20240305A-change-useragent-type.js +1 -1
- package/dist/database/migrations/20240716A-update-files-date-fields.js +33 -0
- package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
- package/dist/database/run-ast.js +458 -0
- package/dist/flows.js +4 -3
- package/dist/logger/index.js +1 -1
- package/dist/middleware/authenticate.js +7 -2
- package/dist/middleware/cache.js +1 -1
- package/dist/middleware/check-ip.d.ts +2 -0
- package/dist/middleware/check-ip.js +37 -0
- package/dist/middleware/error-handler.d.ts +2 -2
- package/dist/middleware/error-handler.js +54 -51
- package/dist/middleware/get-permissions.d.ts +3 -0
- package/dist/middleware/get-permissions.js +10 -0
- package/dist/middleware/respond.js +1 -1
- package/dist/services/activity.js +10 -22
- package/dist/services/assets.d.ts +3 -2
- package/dist/services/assets.js +7 -15
- package/dist/services/authentication.js +18 -18
- package/dist/services/authorization.d.ts +17 -0
- package/dist/services/authorization.js +456 -0
- package/dist/services/collections.js +17 -18
- package/dist/services/fields.d.ts +4 -0
- package/dist/services/fields.js +53 -58
- package/dist/services/files/lib/get-sharp-instance.d.ts +2 -0
- package/dist/services/files/lib/get-sharp-instance.js +10 -0
- package/dist/services/files/utils/get-metadata.js +7 -6
- package/dist/services/files.js +8 -10
- package/dist/services/graphql/index.d.ts +3 -3
- package/dist/services/graphql/index.js +22 -126
- package/dist/services/graphql/subscription.js +4 -2
- package/dist/services/import-export.js +4 -18
- package/dist/services/index.d.ts +2 -3
- package/dist/services/index.js +2 -3
- package/dist/services/items.js +44 -115
- package/dist/services/mail/index.d.ts +1 -1
- package/dist/services/mail/index.js +9 -1
- package/dist/services/meta.js +23 -60
- package/dist/services/notifications.js +6 -14
- package/dist/services/payload.d.ts +10 -9
- package/dist/services/payload.js +3 -18
- package/dist/services/{permissions.d.ts → permissions/index.d.ts} +7 -5
- package/dist/services/{permissions.js → permissions/index.js} +54 -30
- package/dist/{permissions → services/permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
- package/dist/services/permissions/lib/with-app-minimal-permissions.js +13 -0
- package/dist/services/relations.d.ts +9 -1
- package/dist/services/relations.js +56 -31
- package/dist/services/roles.d.ts +12 -4
- package/dist/services/roles.js +424 -57
- package/dist/services/shares.d.ts +2 -0
- package/dist/services/shares.js +8 -12
- package/dist/services/specifications.d.ts +2 -2
- package/dist/services/specifications.js +27 -39
- package/dist/services/tus/data-store.js +4 -5
- package/dist/services/tus/server.d.ts +1 -1
- package/dist/services/tus/server.js +9 -2
- package/dist/services/users.d.ts +5 -1
- package/dist/services/users.js +161 -78
- package/dist/services/utils.js +7 -11
- package/dist/services/versions.d.ts +2 -0
- package/dist/services/versions.js +10 -34
- package/dist/telemetry/lib/get-report.js +2 -2
- package/dist/telemetry/utils/check-increased-user-limits.d.ts +7 -0
- package/dist/telemetry/utils/check-increased-user-limits.js +25 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +6 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.js +27 -0
- package/dist/telemetry/utils/get-role-counts-by-users.d.ts +11 -0
- package/dist/telemetry/utils/get-role-counts-by-users.js +34 -0
- package/dist/telemetry/utils/get-user-count.d.ts +8 -0
- package/dist/telemetry/utils/get-user-count.js +33 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +7 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.js +35 -0
- package/dist/types/ast.d.ts +1 -43
- package/dist/types/items.d.ts +0 -11
- package/dist/utils/apply-query.d.ts +3 -4
- package/dist/utils/apply-query.js +16 -39
- package/dist/utils/get-accountability-for-role.js +25 -16
- package/dist/utils/get-accountability-for-token.js +16 -17
- package/dist/utils/get-ast-from-query.d.ts +13 -0
- package/dist/utils/get-ast-from-query.js +297 -0
- package/dist/utils/get-cache-key.d.ts +1 -1
- package/dist/utils/get-cache-key.js +1 -12
- package/dist/utils/get-column.d.ts +1 -2
- package/dist/utils/get-column.js +0 -1
- package/dist/utils/get-permissions.d.ts +2 -0
- package/dist/utils/get-permissions.js +150 -0
- package/dist/utils/get-schema.js +3 -3
- package/dist/utils/get-service.js +1 -5
- package/dist/utils/merge-permissions-for-share.d.ts +4 -0
- package/dist/utils/merge-permissions-for-share.js +109 -0
- package/dist/utils/merge-permissions.d.ts +3 -0
- package/dist/utils/merge-permissions.js +95 -0
- package/dist/utils/reduce-schema.d.ts +6 -4
- package/dist/utils/reduce-schema.js +32 -16
- package/dist/websocket/authenticate.d.ts +2 -0
- package/dist/websocket/authenticate.js +12 -0
- package/dist/websocket/controllers/graphql.js +4 -1
- package/dist/websocket/controllers/hooks.js +0 -4
- package/dist/websocket/controllers/rest.js +2 -0
- package/dist/websocket/handlers/subscribe.js +2 -0
- package/dist/websocket/utils/items.d.ts +1 -1
- package/package.json +36 -37
- package/dist/controllers/access.d.ts +0 -2
- package/dist/controllers/access.js +0 -148
- package/dist/controllers/policies.d.ts +0 -2
- package/dist/controllers/policies.js +0 -169
- package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +0 -16
- package/dist/database/get-ast-from-query/get-ast-from-query.js +0 -82
- package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +0 -13
- package/dist/database/get-ast-from-query/lib/convert-wildcards.js +0 -69
- package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +0 -15
- package/dist/database/get-ast-from-query/lib/parse-fields.js +0 -190
- package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +0 -14
- package/dist/database/get-ast-from-query/utils/get-deep-query.js +0 -17
- package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-related-collection.js +0 -13
- package/dist/database/get-ast-from-query/utils/get-relation.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-relation.js +0 -7
- package/dist/database/migrations/20240710A-permissions-policies.js +0 -169
- package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
- package/dist/database/run-ast/lib/get-db-query.js +0 -208
- package/dist/database/run-ast/lib/parse-current-level.d.ts +0 -7
- package/dist/database/run-ast/lib/parse-current-level.js +0 -41
- package/dist/database/run-ast/run-ast.d.ts +0 -7
- package/dist/database/run-ast/run-ast.js +0 -107
- package/dist/database/run-ast/types.js +0 -1
- package/dist/database/run-ast/utils/apply-case-when.d.ts +0 -16
- package/dist/database/run-ast/utils/apply-case-when.js +0 -26
- package/dist/database/run-ast/utils/apply-parent-filters.d.ts +0 -3
- package/dist/database/run-ast/utils/apply-parent-filters.js +0 -55
- package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +0 -10
- package/dist/database/run-ast/utils/get-column-pre-processor.js +0 -57
- package/dist/database/run-ast/utils/get-field-alias.d.ts +0 -2
- package/dist/database/run-ast/utils/get-field-alias.js +0 -4
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +0 -5
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +0 -23
- package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +0 -3
- package/dist/database/run-ast/utils/merge-with-parent-items.js +0 -87
- package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +0 -3
- package/dist/database/run-ast/utils/remove-temporary-fields.js +0 -73
- package/dist/permissions/cache.d.ts +0 -2
- package/dist/permissions/cache.js +0 -23
- package/dist/permissions/lib/fetch-permissions.d.ts +0 -10
- package/dist/permissions/lib/fetch-permissions.js +0 -55
- package/dist/permissions/lib/fetch-policies.d.ts +0 -7
- package/dist/permissions/lib/fetch-policies.js +0 -28
- package/dist/permissions/lib/fetch-roles-tree.d.ts +0 -3
- package/dist/permissions/lib/fetch-roles-tree.js +0 -28
- package/dist/permissions/lib/with-app-minimal-permissions.js +0 -10
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +0 -7
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +0 -56
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +0 -3
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +0 -16
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +0 -8
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +0 -24
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +0 -9
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +0 -31
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +0 -16
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +0 -27
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +0 -10
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +0 -23
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
- package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/types.js +0 -1
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +0 -12
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +0 -32
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +0 -4
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +0 -29
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +0 -49
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +0 -3
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +0 -56
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +0 -8
- package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +0 -9
- package/dist/permissions/modules/process-ast/lib/inject-cases.js +0 -93
- package/dist/permissions/modules/process-ast/process-ast.d.ts +0 -9
- package/dist/permissions/modules/process-ast/process-ast.js +0 -39
- package/dist/permissions/modules/process-ast/types.d.ts +0 -24
- package/dist/permissions/modules/process-ast/types.js +0 -1
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +0 -7
- package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +0 -12
- package/dist/permissions/modules/process-ast/utils/dedupe-access.js +0 -30
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +0 -15
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +0 -50
- package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/find-related-collection.js +0 -9
- package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/flatten-filter.js +0 -34
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +0 -1
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +0 -3
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +0 -5
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +0 -7
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +0 -3
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +0 -16
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +0 -12
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +0 -28
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +0 -5
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +0 -12
- package/dist/permissions/modules/process-payload/process-payload.d.ts +0 -13
- package/dist/permissions/modules/process-payload/process-payload.js +0 -77
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +0 -12
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +0 -11
- package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +0 -9
- package/dist/permissions/modules/validate-access/lib/validate-item-access.js +0 -33
- package/dist/permissions/modules/validate-access/validate-access.d.ts +0 -14
- package/dist/permissions/modules/validate-access/validate-access.js +0 -28
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +0 -1
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +0 -8
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +0 -5
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +0 -10
- package/dist/permissions/types.d.ts +0 -6
- package/dist/permissions/types.js +0 -1
- package/dist/permissions/utils/create-default-accountability.d.ts +0 -2
- package/dist/permissions/utils/create-default-accountability.js +0 -11
- package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +0 -8
- package/dist/permissions/utils/extract-required-dynamic-variable-context.js +0 -27
- package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +0 -9
- package/dist/permissions/utils/fetch-dynamic-variable-context.js +0 -43
- package/dist/permissions/utils/filter-policies-by-ip.d.ts +0 -2
- package/dist/permissions/utils/filter-policies-by-ip.js +0 -15
- package/dist/permissions/utils/get-unaliased-field-key.d.ts +0 -5
- package/dist/permissions/utils/get-unaliased-field-key.js +0 -17
- package/dist/permissions/utils/process-permissions.d.ts +0 -7
- package/dist/permissions/utils/process-permissions.js +0 -9
- package/dist/permissions/utils/with-cache.d.ts +0 -10
- package/dist/permissions/utils/with-cache.js +0 -25
- package/dist/services/access.d.ts +0 -10
- package/dist/services/access.js +0 -43
- package/dist/services/policies.d.ts +0 -12
- package/dist/services/policies.js +0 -87
- package/dist/telemetry/utils/check-user-limits.d.ts +0 -5
- package/dist/telemetry/utils/check-user-limits.js +0 -19
- package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +0 -17
- package/dist/utils/fetch-user-count/fetch-access-lookup.js +0 -22
- package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +0 -16
- package/dist/utils/fetch-user-count/fetch-access-roles.js +0 -37
- package/dist/utils/fetch-user-count/fetch-active-users.d.ts +0 -6
- package/dist/utils/fetch-user-count/fetch-active-users.js +0 -3
- package/dist/utils/fetch-user-count/fetch-user-count.d.ts +0 -12
- package/dist/utils/fetch-user-count/fetch-user-count.js +0 -57
- package/dist/utils/fetch-user-count/get-user-count-query.d.ts +0 -20
- package/dist/utils/fetch-user-count/get-user-count-query.js +0 -17
- package/dist/utils/validate-user-count-integrity.d.ts +0 -13
- package/dist/utils/validate-user-count-integrity.js +0 -29
- /package/dist/database/migrations/{20240710A-permissions-policies.d.ts → 20240716A-update-files-date-fields.d.ts} +0 -0
package/dist/services/fields.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { KNEX_TYPES, REGEX_BETWEEN_PARENS, DEFAULT_NUMERIC_PRECISION, DEFAULT_NUMERIC_SCALE, } from '@directus/constants';
|
|
2
2
|
import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
|
|
3
3
|
import { createInspector } from '@directus/schema';
|
|
4
4
|
import { addFieldFlag, toArray } from '@directus/utils';
|
|
5
5
|
import { isEqual, isNil, merge } from 'lodash-es';
|
|
6
|
-
import { clearSystemCache, getCache } from '../cache.js';
|
|
6
|
+
import { clearSystemCache, getCache, getCacheValue, setCacheValue } from '../cache.js';
|
|
7
7
|
import { ALIAS_TYPES } from '../constants.js';
|
|
8
8
|
import { translateDatabaseError } from '../database/errors/translate.js';
|
|
9
9
|
import { getHelpers } from '../database/helpers/index.js';
|
|
10
10
|
import getDatabase, { getSchemaInspector } from '../database/index.js';
|
|
11
11
|
import emitter from '../emitter.js';
|
|
12
|
-
import { fetchPermissions } from '../permissions/lib/fetch-permissions.js';
|
|
13
|
-
import { fetchPolicies } from '../permissions/lib/fetch-policies.js';
|
|
14
|
-
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
15
12
|
import getDefaultValue from '../utils/get-default-value.js';
|
|
16
13
|
import { getSystemFieldRowsWithAuthProviders } from '../utils/get-field-system-rows.js';
|
|
17
14
|
import getLocalType from '../utils/get-local-type.js';
|
|
@@ -22,7 +19,9 @@ import { transaction } from '../utils/transaction.js';
|
|
|
22
19
|
import { ItemsService } from './items.js';
|
|
23
20
|
import { PayloadService } from './payload.js';
|
|
24
21
|
import { RelationsService } from './relations.js';
|
|
22
|
+
import { useEnv } from '@directus/env';
|
|
25
23
|
const systemFieldRows = getSystemFieldRowsWithAuthProviders();
|
|
24
|
+
const env = useEnv();
|
|
26
25
|
export class FieldsService {
|
|
27
26
|
knex;
|
|
28
27
|
helpers;
|
|
@@ -33,6 +32,7 @@ export class FieldsService {
|
|
|
33
32
|
schema;
|
|
34
33
|
cache;
|
|
35
34
|
systemCache;
|
|
35
|
+
schemaCache;
|
|
36
36
|
constructor(options) {
|
|
37
37
|
this.knex = options.knex || getDatabase();
|
|
38
38
|
this.helpers = getHelpers(this.knex);
|
|
@@ -41,21 +41,40 @@ export class FieldsService {
|
|
|
41
41
|
this.itemsService = new ItemsService('directus_fields', options);
|
|
42
42
|
this.payloadService = new PayloadService('directus_fields', options);
|
|
43
43
|
this.schema = options.schema;
|
|
44
|
-
const { cache, systemCache } = getCache();
|
|
44
|
+
const { cache, systemCache, localSchemaCache } = getCache();
|
|
45
45
|
this.cache = cache;
|
|
46
46
|
this.systemCache = systemCache;
|
|
47
|
+
this.schemaCache = localSchemaCache;
|
|
48
|
+
}
|
|
49
|
+
get hasReadAccess() {
|
|
50
|
+
return !!this.accountability?.permissions?.find((permission) => {
|
|
51
|
+
return permission.collection === 'directus_fields' && permission.action === 'read';
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async columnInfo(collection, field) {
|
|
55
|
+
const schemaCacheIsEnabled = Boolean(env['CACHE_SCHEMA']);
|
|
56
|
+
let columnInfo = null;
|
|
57
|
+
if (schemaCacheIsEnabled) {
|
|
58
|
+
columnInfo = await getCacheValue(this.schemaCache, 'columnInfo');
|
|
59
|
+
}
|
|
60
|
+
if (!columnInfo) {
|
|
61
|
+
columnInfo = await this.schemaInspector.columnInfo();
|
|
62
|
+
if (schemaCacheIsEnabled) {
|
|
63
|
+
setCacheValue(this.schemaCache, 'columnInfo', columnInfo);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (collection) {
|
|
67
|
+
columnInfo = columnInfo.filter((column) => column.table === collection);
|
|
68
|
+
}
|
|
69
|
+
if (field) {
|
|
70
|
+
return columnInfo.find((column) => column.name === field);
|
|
71
|
+
}
|
|
72
|
+
return columnInfo;
|
|
47
73
|
}
|
|
48
74
|
async readAll(collection) {
|
|
49
75
|
let fields;
|
|
50
|
-
if (this.accountability) {
|
|
51
|
-
|
|
52
|
-
accountability: this.accountability,
|
|
53
|
-
action: 'read',
|
|
54
|
-
collection: 'directus_fields',
|
|
55
|
-
}, {
|
|
56
|
-
schema: this.schema,
|
|
57
|
-
knex: this.knex,
|
|
58
|
-
});
|
|
76
|
+
if (this.accountability && this.accountability.admin !== true && this.hasReadAccess === false) {
|
|
77
|
+
throw new ForbiddenError();
|
|
59
78
|
}
|
|
60
79
|
const nonAuthorizedItemsService = new ItemsService('directus_fields', {
|
|
61
80
|
knex: this.knex,
|
|
@@ -72,7 +91,7 @@ export class FieldsService {
|
|
|
72
91
|
fields = (await nonAuthorizedItemsService.readByQuery({ limit: -1 }));
|
|
73
92
|
fields.push(...systemFieldRows);
|
|
74
93
|
}
|
|
75
|
-
const columns = (await this.
|
|
94
|
+
const columns = (await this.columnInfo(collection)).map((column) => ({
|
|
76
95
|
...column,
|
|
77
96
|
default_value: getDefaultValue(column, fields.find((field) => field.collection === column.table && field.field === column.name)),
|
|
78
97
|
}));
|
|
@@ -124,27 +143,12 @@ export class FieldsService {
|
|
|
124
143
|
const result = [...columnsWithSystem, ...aliasFieldsAsField].filter((field) => knownCollections.includes(field.collection));
|
|
125
144
|
// Filter the result so we only return the fields you have read access to
|
|
126
145
|
if (this.accountability && this.accountability.admin !== true) {
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
action: 'read',
|
|
131
|
-
policies,
|
|
132
|
-
collections: [collection],
|
|
133
|
-
accountability: this.accountability,
|
|
134
|
-
}
|
|
135
|
-
: {
|
|
136
|
-
action: 'read',
|
|
137
|
-
policies,
|
|
138
|
-
accountability: this.accountability,
|
|
139
|
-
}, { knex: this.knex, schema: this.schema });
|
|
146
|
+
const permissions = this.accountability.permissions.filter((permission) => {
|
|
147
|
+
return permission.action === 'read';
|
|
148
|
+
});
|
|
140
149
|
const allowedFieldsInCollection = {};
|
|
141
150
|
permissions.forEach((permission) => {
|
|
142
|
-
|
|
143
|
-
allowedFieldsInCollection[permission.collection] = new Set();
|
|
144
|
-
}
|
|
145
|
-
for (const field of permission.fields ?? []) {
|
|
146
|
-
allowedFieldsInCollection[permission.collection].add(field);
|
|
147
|
-
}
|
|
151
|
+
allowedFieldsInCollection[permission.collection] = permission.fields ?? [];
|
|
148
152
|
});
|
|
149
153
|
if (collection && collection in allowedFieldsInCollection === false) {
|
|
150
154
|
throw new ForbiddenError();
|
|
@@ -153,9 +157,9 @@ export class FieldsService {
|
|
|
153
157
|
if (field.collection in allowedFieldsInCollection === false)
|
|
154
158
|
return false;
|
|
155
159
|
const allowedFields = allowedFieldsInCollection[field.collection];
|
|
156
|
-
if (allowedFields
|
|
160
|
+
if (allowedFields[0] === '*')
|
|
157
161
|
return true;
|
|
158
|
-
return allowedFields.
|
|
162
|
+
return allowedFields.includes(field.field);
|
|
159
163
|
});
|
|
160
164
|
}
|
|
161
165
|
// Update specific database type overrides
|
|
@@ -172,27 +176,18 @@ export class FieldsService {
|
|
|
172
176
|
}
|
|
173
177
|
async readOne(collection, field) {
|
|
174
178
|
if (this.accountability && this.accountability.admin !== true) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
action: 'read',
|
|
178
|
-
collection,
|
|
179
|
-
}, {
|
|
180
|
-
schema: this.schema,
|
|
181
|
-
knex: this.knex,
|
|
182
|
-
});
|
|
183
|
-
const policies = await fetchPolicies(this.accountability, { knex: this.knex, schema: this.schema });
|
|
184
|
-
const permissions = await fetchPermissions({ action: 'read', policies, collections: [collection], accountability: this.accountability }, { knex: this.knex, schema: this.schema });
|
|
185
|
-
let hasAccess = false;
|
|
186
|
-
for (const permission of permissions) {
|
|
187
|
-
if (permission.fields) {
|
|
188
|
-
if (permission.fields.includes('*') || permission.fields.includes(field)) {
|
|
189
|
-
hasAccess = true;
|
|
190
|
-
break;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
179
|
+
if (this.hasReadAccess === false) {
|
|
180
|
+
throw new ForbiddenError();
|
|
193
181
|
}
|
|
194
|
-
|
|
182
|
+
const permissions = this.accountability.permissions.find((permission) => {
|
|
183
|
+
return permission.action === 'read' && permission.collection === collection;
|
|
184
|
+
});
|
|
185
|
+
if (!permissions || !permissions.fields)
|
|
195
186
|
throw new ForbiddenError();
|
|
187
|
+
if (permissions.fields.includes('*') === false) {
|
|
188
|
+
const allowedFields = permissions.fields;
|
|
189
|
+
if (allowedFields.includes(field) === false)
|
|
190
|
+
throw new ForbiddenError();
|
|
196
191
|
}
|
|
197
192
|
}
|
|
198
193
|
let column = undefined;
|
|
@@ -204,7 +199,7 @@ export class FieldsService {
|
|
|
204
199
|
fieldInfo ||
|
|
205
200
|
systemFieldRows.find((fieldMeta) => fieldMeta.collection === collection && fieldMeta.field === field);
|
|
206
201
|
try {
|
|
207
|
-
column = await this.
|
|
202
|
+
column = await this.columnInfo(collection, field);
|
|
208
203
|
}
|
|
209
204
|
catch {
|
|
210
205
|
// Do nothing
|
|
@@ -359,7 +354,7 @@ export class FieldsService {
|
|
|
359
354
|
throw new InvalidPayloadError({ reason: 'Alias type cannot be changed' });
|
|
360
355
|
}
|
|
361
356
|
if (hookAdjustedField.schema) {
|
|
362
|
-
const existingColumn = await this.
|
|
357
|
+
const existingColumn = await this.columnInfo(collection, hookAdjustedField.field);
|
|
363
358
|
if (hookAdjustedField.schema?.is_nullable === true && existingColumn.is_primary_key) {
|
|
364
359
|
throw new InvalidPayloadError({ reason: 'Primary key cannot be null' });
|
|
365
360
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
2
|
+
import sharp, {} from 'sharp';
|
|
3
|
+
export function getSharpInstance() {
|
|
4
|
+
const env = useEnv();
|
|
5
|
+
return sharp({
|
|
6
|
+
limitInputPixels: Math.trunc(Math.pow(env['ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION'], 2)),
|
|
7
|
+
sequentialRead: true,
|
|
8
|
+
failOn: env['ASSETS_INVALID_IMAGE_SENSITIVITY_LEVEL'],
|
|
9
|
+
});
|
|
10
|
+
}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
+
import { useEnv } from '@directus/env';
|
|
1
2
|
import exif, {} from 'exif-reader';
|
|
2
3
|
import { parse as parseIcc } from 'icc';
|
|
3
4
|
import { pick } from 'lodash-es';
|
|
4
5
|
import { pipeline } from 'node:stream/promises';
|
|
5
|
-
import sharp from 'sharp';
|
|
6
|
-
import { useEnv } from '@directus/env';
|
|
7
6
|
import { useLogger } from '../../../logger/index.js';
|
|
7
|
+
import { getSharpInstance } from '../lib/get-sharp-instance.js';
|
|
8
8
|
import { parseIptc, parseXmp } from './parse-image-metadata.js';
|
|
9
9
|
const env = useEnv();
|
|
10
10
|
const logger = useLogger();
|
|
11
11
|
export async function getMetadata(stream, allowList = env['FILE_METADATA_ALLOW_LIST']) {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const transformer = getSharpInstance();
|
|
13
|
+
return new Promise((resolve) => {
|
|
14
|
+
pipeline(stream, transformer.metadata(async (err, sharpMetadata) => {
|
|
14
15
|
if (err) {
|
|
15
|
-
|
|
16
|
-
return;
|
|
16
|
+
logger.error(err);
|
|
17
|
+
return resolve({});
|
|
17
18
|
}
|
|
18
19
|
const metadata = {};
|
|
19
20
|
if (sharpMetadata.orientation && sharpMetadata.orientation >= 5) {
|
package/dist/services/files.js
CHANGED
|
@@ -12,7 +12,6 @@ import url from 'url';
|
|
|
12
12
|
import { RESUMABLE_UPLOADS } from '../constants.js';
|
|
13
13
|
import emitter from '../emitter.js';
|
|
14
14
|
import { useLogger } from '../logger/index.js';
|
|
15
|
-
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
16
15
|
import { getAxios } from '../request/index.js';
|
|
17
16
|
import { getStorage } from '../storage/index.js';
|
|
18
17
|
import { extractMetadata } from './files/lib/extract-metadata.js';
|
|
@@ -58,6 +57,10 @@ export class FilesService extends ItemsService {
|
|
|
58
57
|
const fileExtension = path.extname(payload.filename_download) || (payload.type && '.' + extension(payload.type)) || '';
|
|
59
58
|
// The filename_disk is the FINAL filename on disk
|
|
60
59
|
payload.filename_disk ||= primaryKey + (fileExtension || '');
|
|
60
|
+
// If the filename_disk extension doesn't match the new mimetype, update it
|
|
61
|
+
if (isReplacement === true && path.extname(payload.filename_disk) !== fileExtension) {
|
|
62
|
+
payload.filename_disk = primaryKey + (fileExtension || '');
|
|
63
|
+
}
|
|
61
64
|
// Temp filename is used for replacements
|
|
62
65
|
const tempFilenameDisk = 'temp_' + payload.filename_disk;
|
|
63
66
|
if (!payload.type) {
|
|
@@ -126,6 +129,7 @@ export class FilesService extends ItemsService {
|
|
|
126
129
|
const { size } = await storage.location(data.storage).stat(payload.filename_disk);
|
|
127
130
|
payload.filesize = size;
|
|
128
131
|
const metadata = await extractMetadata(data.storage, payload);
|
|
132
|
+
payload.uploaded_on = new Date().toISOString();
|
|
129
133
|
// We do this in a service without accountability. Even if you don't have update permissions to the file,
|
|
130
134
|
// we still want to be able to set the extracted values from the file on create
|
|
131
135
|
const sudoService = new ItemsService('directus_files', {
|
|
@@ -153,15 +157,9 @@ export class FilesService extends ItemsService {
|
|
|
153
157
|
* Import a single file from an external URL
|
|
154
158
|
*/
|
|
155
159
|
async importOne(importURL, body) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
action: 'create',
|
|
160
|
-
collection: 'directus_files',
|
|
161
|
-
}, {
|
|
162
|
-
knex: this.knex,
|
|
163
|
-
schema: this.schema,
|
|
164
|
-
});
|
|
160
|
+
const fileCreatePermissions = this.accountability?.permissions?.find((permission) => permission.collection === 'directus_files' && permission.action === 'create');
|
|
161
|
+
if (this.accountability && this.accountability?.admin !== true && !fileCreatePermissions) {
|
|
162
|
+
throw new ForbiddenError();
|
|
165
163
|
}
|
|
166
164
|
let fileResponse;
|
|
167
165
|
try {
|
|
@@ -20,9 +20,9 @@ export declare class GraphQLService {
|
|
|
20
20
|
/**
|
|
21
21
|
* Generate the GraphQL schema. Pulls from the schema information generated by the get-schema util.
|
|
22
22
|
*/
|
|
23
|
-
getSchema():
|
|
24
|
-
getSchema(type: 'schema'):
|
|
25
|
-
getSchema(type: 'sdl'):
|
|
23
|
+
getSchema(): GraphQLSchema;
|
|
24
|
+
getSchema(type: 'schema'): GraphQLSchema;
|
|
25
|
+
getSchema(type: 'sdl'): GraphQLSchema | string;
|
|
26
26
|
/**
|
|
27
27
|
* Generic resolver that's used for every "regular" items/system query. Converts the incoming GraphQL AST / fragments into
|
|
28
28
|
* Directus' query structure which is then executed by the services.
|
|
@@ -11,9 +11,6 @@ import { clearSystemCache, getCache } from '../../cache.js';
|
|
|
11
11
|
import { DEFAULT_AUTH_PROVIDER, GENERATE_SPECIAL, REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS, } from '../../constants.js';
|
|
12
12
|
import getDatabase from '../../database/index.js';
|
|
13
13
|
import { rateLimiter } from '../../middleware/rate-limiter-registration.js';
|
|
14
|
-
import { fetchAllowedFieldMap } from '../../permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js';
|
|
15
|
-
import { fetchInconsistentFieldMap } from '../../permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js';
|
|
16
|
-
import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
|
|
17
14
|
import { generateHash } from '../../utils/generate-hash.js';
|
|
18
15
|
import { getGraphQLType } from '../../utils/get-graphql-type.js';
|
|
19
16
|
import { getIPFromReq } from '../../utils/get-ip-from-req.js';
|
|
@@ -51,9 +48,6 @@ import { GraphQLVoid } from './types/void.js';
|
|
|
51
48
|
import { addPathToValidationError } from './utils/add-path-to-validation-error.js';
|
|
52
49
|
import processError from './utils/process-error.js';
|
|
53
50
|
import { sanitizeGraphqlSchema } from './utils/sanitize-gql-schema.js';
|
|
54
|
-
import { fetchAccountabilityCollectionAccess } from '../../permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js';
|
|
55
|
-
import { fetchAccountabilityPolicyGlobals } from '../../permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js';
|
|
56
|
-
import { RolesService } from '../roles.js';
|
|
57
51
|
const env = useEnv();
|
|
58
52
|
const validationRules = Array.from(specifiedRules);
|
|
59
53
|
if (env['GRAPHQL_INTROSPECTION'] === false) {
|
|
@@ -86,7 +80,7 @@ export class GraphQLService {
|
|
|
86
80
|
* Execute a GraphQL structure
|
|
87
81
|
*/
|
|
88
82
|
async execute({ document, variables, operationName, contextValue, }) {
|
|
89
|
-
const schema =
|
|
83
|
+
const schema = this.getSchema();
|
|
90
84
|
const validationErrors = validate(schema, document, validationRules).map((validationError) => addPathToValidationError(validationError));
|
|
91
85
|
if (validationErrors.length > 0) {
|
|
92
86
|
throw new GraphQLValidationError({ errors: validationErrors });
|
|
@@ -114,7 +108,7 @@ export class GraphQLService {
|
|
|
114
108
|
formattedResult.extensions = result['extensions'];
|
|
115
109
|
return formattedResult;
|
|
116
110
|
}
|
|
117
|
-
|
|
111
|
+
getSchema(type = 'schema') {
|
|
118
112
|
const key = `${this.scope}_${type}_${this.accountability?.role}_${this.accountability?.user}`;
|
|
119
113
|
const cachedSchema = cache.get(key);
|
|
120
114
|
if (cachedSchema)
|
|
@@ -122,53 +116,20 @@ export class GraphQLService {
|
|
|
122
116
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
123
117
|
const self = this;
|
|
124
118
|
const schemaComposer = new SchemaComposer();
|
|
125
|
-
let schema;
|
|
126
119
|
const sanitizedSchema = sanitizeGraphqlSchema(this.schema);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}, { schema: this.schema, knex: this.knex })),
|
|
141
|
-
create: reduceSchema(sanitizedSchema, await fetchAllowedFieldMap({
|
|
142
|
-
accountability: this.accountability,
|
|
143
|
-
action: 'create',
|
|
144
|
-
}, { schema: this.schema, knex: this.knex })),
|
|
145
|
-
update: reduceSchema(sanitizedSchema, await fetchAllowedFieldMap({
|
|
146
|
-
accountability: this.accountability,
|
|
147
|
-
action: 'update',
|
|
148
|
-
}, { schema: this.schema, knex: this.knex })),
|
|
149
|
-
delete: reduceSchema(sanitizedSchema, await fetchAllowedFieldMap({
|
|
150
|
-
accountability: this.accountability,
|
|
151
|
-
action: 'delete',
|
|
152
|
-
}, { schema: this.schema, knex: this.knex })),
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
const inconsistentFields = {
|
|
156
|
-
read: await fetchInconsistentFieldMap({
|
|
157
|
-
accountability: this.accountability,
|
|
158
|
-
action: 'read',
|
|
159
|
-
}, { schema: this.schema, knex: this.knex }),
|
|
160
|
-
create: await fetchInconsistentFieldMap({
|
|
161
|
-
accountability: this.accountability,
|
|
162
|
-
action: 'create',
|
|
163
|
-
}, { schema: this.schema, knex: this.knex }),
|
|
164
|
-
update: await fetchInconsistentFieldMap({
|
|
165
|
-
accountability: this.accountability,
|
|
166
|
-
action: 'update',
|
|
167
|
-
}, { schema: this.schema, knex: this.knex }),
|
|
168
|
-
delete: await fetchInconsistentFieldMap({
|
|
169
|
-
accountability: this.accountability,
|
|
170
|
-
action: 'delete',
|
|
171
|
-
}, { schema: this.schema, knex: this.knex }),
|
|
120
|
+
const schema = {
|
|
121
|
+
read: this.accountability?.admin === true
|
|
122
|
+
? sanitizedSchema
|
|
123
|
+
: reduceSchema(sanitizedSchema, this.accountability?.permissions || null, ['read']),
|
|
124
|
+
create: this.accountability?.admin === true
|
|
125
|
+
? sanitizedSchema
|
|
126
|
+
: reduceSchema(sanitizedSchema, this.accountability?.permissions || null, ['create']),
|
|
127
|
+
update: this.accountability?.admin === true
|
|
128
|
+
? sanitizedSchema
|
|
129
|
+
: reduceSchema(sanitizedSchema, this.accountability?.permissions || null, ['update']),
|
|
130
|
+
delete: this.accountability?.admin === true
|
|
131
|
+
? sanitizedSchema
|
|
132
|
+
: reduceSchema(sanitizedSchema, this.accountability?.permissions || null, ['delete']),
|
|
172
133
|
};
|
|
173
134
|
const subscriptionEventType = schemaComposer.createEnumTC({
|
|
174
135
|
name: 'EventEnum',
|
|
@@ -339,18 +300,16 @@ export class GraphQLService {
|
|
|
339
300
|
name: action === 'read' ? collection.collection : `${action}_${collection.collection}`,
|
|
340
301
|
fields: Object.values(collection.fields).reduce((acc, field) => {
|
|
341
302
|
let type = getGraphQLType(field.type, field.special);
|
|
342
|
-
const fieldIsInconsistent = inconsistentFields[action][collection.collection]?.includes(field.field);
|
|
343
303
|
// GraphQL doesn't differentiate between not-null and has-to-be-submitted. We
|
|
344
304
|
// can't non-null in update, as that would require every not-nullable field to be
|
|
345
305
|
// submitted on updates
|
|
346
306
|
if (field.nullable === false &&
|
|
347
307
|
!field.defaultValue &&
|
|
348
308
|
!GENERATE_SPECIAL.some((flag) => field.special.includes(flag)) &&
|
|
349
|
-
fieldIsInconsistent === false &&
|
|
350
309
|
action !== 'update') {
|
|
351
310
|
type = new GraphQLNonNull(type);
|
|
352
311
|
}
|
|
353
|
-
if (collection.primary === field.field
|
|
312
|
+
if (collection.primary === field.field) {
|
|
354
313
|
// permissions IDs need to be nullable https://github.com/directus/directus/issues/20509
|
|
355
314
|
if (collection.collection === 'directus_permissions') {
|
|
356
315
|
type = GraphQLID;
|
|
@@ -1803,7 +1762,7 @@ export class GraphQLService {
|
|
|
1803
1762
|
accountability: this.accountability,
|
|
1804
1763
|
scope: args['scope'] ?? 'items',
|
|
1805
1764
|
});
|
|
1806
|
-
return
|
|
1765
|
+
return service.getSchema('sdl');
|
|
1807
1766
|
},
|
|
1808
1767
|
},
|
|
1809
1768
|
server_ping: {
|
|
@@ -1856,7 +1815,7 @@ export class GraphQLService {
|
|
|
1856
1815
|
otp: GraphQLString,
|
|
1857
1816
|
},
|
|
1858
1817
|
resolve: async (_, args, { req, res }) => {
|
|
1859
|
-
const accountability =
|
|
1818
|
+
const accountability = { role: null };
|
|
1860
1819
|
if (req?.ip)
|
|
1861
1820
|
accountability.ip = req.ip;
|
|
1862
1821
|
const userAgent = req?.get('user-agent');
|
|
@@ -1896,7 +1855,7 @@ export class GraphQLService {
|
|
|
1896
1855
|
mode: AuthMode,
|
|
1897
1856
|
},
|
|
1898
1857
|
resolve: async (_, args, { req, res }) => {
|
|
1899
|
-
const accountability =
|
|
1858
|
+
const accountability = { role: null };
|
|
1900
1859
|
if (req?.ip)
|
|
1901
1860
|
accountability.ip = req.ip;
|
|
1902
1861
|
const userAgent = req?.get('user-agent');
|
|
@@ -1954,7 +1913,7 @@ export class GraphQLService {
|
|
|
1954
1913
|
mode: AuthMode,
|
|
1955
1914
|
},
|
|
1956
1915
|
resolve: async (_, args, { req, res }) => {
|
|
1957
|
-
const accountability =
|
|
1916
|
+
const accountability = { role: null };
|
|
1958
1917
|
if (req?.ip)
|
|
1959
1918
|
accountability.ip = req.ip;
|
|
1960
1919
|
const userAgent = req?.get('user-agent');
|
|
@@ -2004,7 +1963,7 @@ export class GraphQLService {
|
|
|
2004
1963
|
reset_url: GraphQLString,
|
|
2005
1964
|
},
|
|
2006
1965
|
resolve: async (_, args, { req }) => {
|
|
2007
|
-
const accountability =
|
|
1966
|
+
const accountability = { role: null };
|
|
2008
1967
|
if (req?.ip)
|
|
2009
1968
|
accountability.ip = req.ip;
|
|
2010
1969
|
const userAgent = req?.get('user-agent');
|
|
@@ -2032,7 +1991,7 @@ export class GraphQLService {
|
|
|
2032
1991
|
password: new GraphQLNonNull(GraphQLString),
|
|
2033
1992
|
},
|
|
2034
1993
|
resolve: async (_, args, { req }) => {
|
|
2035
|
-
const accountability =
|
|
1994
|
+
const accountability = { role: null };
|
|
2036
1995
|
if (req?.ip)
|
|
2037
1996
|
accountability.ip = req.ip;
|
|
2038
1997
|
const userAgent = req?.get('user-agent');
|
|
@@ -2673,69 +2632,6 @@ export class GraphQLService {
|
|
|
2673
2632
|
},
|
|
2674
2633
|
});
|
|
2675
2634
|
}
|
|
2676
|
-
if ('directus_permissions' in schema.read.collections) {
|
|
2677
|
-
schemaComposer.Query.addFields({
|
|
2678
|
-
permissions_me: {
|
|
2679
|
-
type: schemaComposer.createScalarTC({
|
|
2680
|
-
name: 'permissions_me_type',
|
|
2681
|
-
parseValue: (value) => value,
|
|
2682
|
-
serialize: (value) => value,
|
|
2683
|
-
}),
|
|
2684
|
-
resolve: async (_, _args, __, _info) => {
|
|
2685
|
-
if (!this.accountability?.user && !this.accountability?.role)
|
|
2686
|
-
return null;
|
|
2687
|
-
const result = await fetchAccountabilityCollectionAccess(this.accountability, {
|
|
2688
|
-
schema: this.schema,
|
|
2689
|
-
knex: getDatabase(),
|
|
2690
|
-
});
|
|
2691
|
-
return result;
|
|
2692
|
-
},
|
|
2693
|
-
},
|
|
2694
|
-
});
|
|
2695
|
-
}
|
|
2696
|
-
if ('directus_roles' in schema.read.collections) {
|
|
2697
|
-
schemaComposer.Query.addFields({
|
|
2698
|
-
roles_me: {
|
|
2699
|
-
type: ReadCollectionTypes['directus_roles'].List,
|
|
2700
|
-
resolve: async (_, args, __, info) => {
|
|
2701
|
-
if (!this.accountability?.user && !this.accountability?.role)
|
|
2702
|
-
return null;
|
|
2703
|
-
const service = new RolesService({
|
|
2704
|
-
accountability: this.accountability,
|
|
2705
|
-
schema: this.schema,
|
|
2706
|
-
});
|
|
2707
|
-
const selections = this.replaceFragmentsInSelections(info.fieldNodes[0]?.selectionSet?.selections, info.fragments);
|
|
2708
|
-
const query = this.getQuery(args, selections || [], info.variableValues);
|
|
2709
|
-
query.limit = -1;
|
|
2710
|
-
const roles = await service.readMany(this.accountability.roles, query);
|
|
2711
|
-
return roles;
|
|
2712
|
-
},
|
|
2713
|
-
},
|
|
2714
|
-
});
|
|
2715
|
-
}
|
|
2716
|
-
if ('directus_policies' in schema.read.collections) {
|
|
2717
|
-
schemaComposer.Query.addFields({
|
|
2718
|
-
policies_me_globals: {
|
|
2719
|
-
type: schemaComposer.createObjectTC({
|
|
2720
|
-
name: 'policy_me_globals_type',
|
|
2721
|
-
fields: {
|
|
2722
|
-
enforce_tfa: 'Boolean',
|
|
2723
|
-
app_access: 'Boolean',
|
|
2724
|
-
admin_access: 'Boolean',
|
|
2725
|
-
},
|
|
2726
|
-
}),
|
|
2727
|
-
resolve: async (_, _args, __, _info) => {
|
|
2728
|
-
if (!this.accountability?.user && !this.accountability?.role)
|
|
2729
|
-
return null;
|
|
2730
|
-
const result = await fetchAccountabilityPolicyGlobals(this.accountability, {
|
|
2731
|
-
schema: this.schema,
|
|
2732
|
-
knex: getDatabase(),
|
|
2733
|
-
});
|
|
2734
|
-
return result;
|
|
2735
|
-
},
|
|
2736
|
-
},
|
|
2737
|
-
});
|
|
2738
|
-
}
|
|
2739
2635
|
if ('directus_users' in schema.update.collections && this.accountability?.user) {
|
|
2740
2636
|
schemaComposer.Mutation.addFields({
|
|
2741
2637
|
update_users_me: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventEmitter, on } from 'events';
|
|
2
2
|
import { useBus } from '../../bus/index.js';
|
|
3
3
|
import { getSchema } from '../../utils/get-schema.js';
|
|
4
|
+
import { refreshAccountability } from '../../websocket/authenticate.js';
|
|
4
5
|
import { getPayload } from '../../websocket/utils/items.js';
|
|
5
6
|
const messages = createPubSub(new EventEmitter());
|
|
6
7
|
export function bindPubSub() {
|
|
@@ -18,6 +19,7 @@ export function createSubscriptionGenerator(self, event) {
|
|
|
18
19
|
if ('event' in args && eventData['action'] !== args['event']) {
|
|
19
20
|
continue; // skip filtered events
|
|
20
21
|
}
|
|
22
|
+
const accountability = await refreshAccountability(self.accountability);
|
|
21
23
|
const schema = await getSchema();
|
|
22
24
|
const subscription = {
|
|
23
25
|
collection: eventData['collection'],
|
|
@@ -33,7 +35,7 @@ export function createSubscriptionGenerator(self, event) {
|
|
|
33
35
|
if (eventData['action'] === 'create') {
|
|
34
36
|
try {
|
|
35
37
|
subscription.item = eventData['key'];
|
|
36
|
-
const result = await getPayload(subscription,
|
|
38
|
+
const result = await getPayload(subscription, accountability, schema, eventData);
|
|
37
39
|
yield {
|
|
38
40
|
[event]: {
|
|
39
41
|
key: eventData['key'],
|
|
@@ -50,7 +52,7 @@ export function createSubscriptionGenerator(self, event) {
|
|
|
50
52
|
for (const key of eventData['keys']) {
|
|
51
53
|
try {
|
|
52
54
|
subscription.item = key;
|
|
53
|
-
const result = await getPayload(subscription,
|
|
55
|
+
const result = await getPayload(subscription, accountability, schema, eventData);
|
|
54
56
|
yield {
|
|
55
57
|
[event]: {
|
|
56
58
|
key,
|
|
@@ -15,7 +15,6 @@ import StreamArray from 'stream-json/streamers/StreamArray.js';
|
|
|
15
15
|
import getDatabase from '../database/index.js';
|
|
16
16
|
import emitter from '../emitter.js';
|
|
17
17
|
import { useLogger } from '../logger/index.js';
|
|
18
|
-
import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
|
|
19
18
|
import { getDateFormatted } from '../utils/get-date-formatted.js';
|
|
20
19
|
import { getService } from '../utils/get-service.js';
|
|
21
20
|
import { transaction } from '../utils/transaction.js';
|
|
@@ -38,23 +37,10 @@ export class ImportService {
|
|
|
38
37
|
async import(collection, mimetype, stream) {
|
|
39
38
|
if (this.accountability?.admin !== true && isSystemCollection(collection))
|
|
40
39
|
throw new ForbiddenError();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
collection,
|
|
46
|
-
}, {
|
|
47
|
-
schema: this.schema,
|
|
48
|
-
knex: this.knex,
|
|
49
|
-
});
|
|
50
|
-
await validateAccess({
|
|
51
|
-
accountability: this.accountability,
|
|
52
|
-
action: 'update',
|
|
53
|
-
collection,
|
|
54
|
-
}, {
|
|
55
|
-
schema: this.schema,
|
|
56
|
-
knex: this.knex,
|
|
57
|
-
});
|
|
40
|
+
const createPermissions = this.accountability?.permissions?.find((permission) => permission.collection === collection && permission.action === 'create');
|
|
41
|
+
const updatePermissions = this.accountability?.permissions?.find((permission) => permission.collection === collection && permission.action === 'update');
|
|
42
|
+
if (this.accountability?.admin !== true && (!createPermissions || !updatePermissions)) {
|
|
43
|
+
throw new ForbiddenError();
|
|
58
44
|
}
|
|
59
45
|
switch (mimetype) {
|
|
60
46
|
case 'application/json':
|
package/dist/services/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from './access.js';
|
|
2
1
|
export * from './activity.js';
|
|
3
2
|
export * from './assets.js';
|
|
4
3
|
export * from './authentication.js';
|
|
4
|
+
export * from './authorization.js';
|
|
5
5
|
export * from './collections.js';
|
|
6
6
|
export * from './dashboards.js';
|
|
7
7
|
export * from './extensions.js';
|
|
@@ -18,8 +18,7 @@ export * from './notifications.js';
|
|
|
18
18
|
export * from './operations.js';
|
|
19
19
|
export * from './panels.js';
|
|
20
20
|
export * from './payload.js';
|
|
21
|
-
export * from './permissions.js';
|
|
22
|
-
export * from './policies.js';
|
|
21
|
+
export * from './permissions/index.js';
|
|
23
22
|
export * from './presets.js';
|
|
24
23
|
export * from './relations.js';
|
|
25
24
|
export * from './revisions.js';
|
package/dist/services/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from './access.js';
|
|
2
1
|
export * from './activity.js';
|
|
3
2
|
export * from './assets.js';
|
|
4
3
|
export * from './authentication.js';
|
|
4
|
+
export * from './authorization.js';
|
|
5
5
|
export * from './collections.js';
|
|
6
6
|
export * from './dashboards.js';
|
|
7
7
|
export * from './extensions.js';
|
|
@@ -18,8 +18,7 @@ export * from './notifications.js';
|
|
|
18
18
|
export * from './operations.js';
|
|
19
19
|
export * from './panels.js';
|
|
20
20
|
export * from './payload.js';
|
|
21
|
-
export * from './permissions.js';
|
|
22
|
-
export * from './policies.js';
|
|
21
|
+
export * from './permissions/index.js';
|
|
23
22
|
export * from './presets.js';
|
|
24
23
|
export * from './relations.js';
|
|
25
24
|
export * from './revisions.js';
|