directus 9.22.4 → 9.23.3
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 +19 -14
- package/dist/auth/auth.d.ts +3 -3
- package/dist/auth/auth.js +2 -0
- package/dist/auth/drivers/ldap.d.ts +2 -2
- package/dist/auth/drivers/ldap.js +47 -36
- package/dist/auth/drivers/local.d.ts +1 -1
- package/dist/auth/drivers/local.js +13 -10
- package/dist/auth/drivers/oauth2.d.ts +1 -1
- package/dist/auth/drivers/oauth2.js +22 -15
- package/dist/auth/drivers/openid.d.ts +1 -1
- package/dist/auth/drivers/openid.js +23 -16
- package/dist/auth/drivers/saml.d.ts +1 -1
- package/dist/auth/drivers/saml.js +10 -7
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +4 -4
- package/dist/cache.d.ts +9 -1
- package/dist/cache.js +59 -16
- package/dist/cli/commands/bootstrap/index.js +2 -2
- package/dist/cli/commands/init/index.js +3 -3
- package/dist/cli/commands/schema/apply.js +21 -20
- package/dist/cli/commands/schema/snapshot.js +2 -2
- package/dist/cli/utils/create-db-connection.d.ts +2 -1
- package/dist/cli/utils/create-db-connection.js +2 -1
- package/dist/cli/utils/create-env/env-stub.liquid +1 -1
- package/dist/cli/utils/create-env/index.d.ts +2 -2
- package/dist/cli/utils/drivers.d.ts +3 -9
- package/dist/constants.d.ts +3 -9
- package/dist/constants.js +5 -10
- package/dist/controllers/activity.js +1 -2
- package/dist/controllers/assets.js +17 -12
- package/dist/controllers/auth.js +29 -15
- package/dist/controllers/dashboards.js +5 -2
- package/dist/controllers/extensions.js +7 -7
- package/dist/controllers/fields.js +4 -4
- package/dist/controllers/files.js +11 -6
- package/dist/controllers/flows.js +5 -2
- package/dist/controllers/folders.js +5 -2
- package/dist/controllers/graphql.js +6 -0
- package/dist/controllers/items.js +5 -2
- package/dist/controllers/not-found.d.ts +1 -1
- package/dist/controllers/not-found.js +1 -2
- package/dist/controllers/notifications.js +5 -2
- package/dist/controllers/operations.js +5 -2
- package/dist/controllers/panels.js +5 -2
- package/dist/controllers/permissions.js +5 -2
- package/dist/controllers/presets.js +5 -2
- package/dist/controllers/roles.js +5 -2
- package/dist/controllers/schema.d.ts +2 -0
- package/dist/controllers/schema.js +98 -0
- package/dist/controllers/shares.js +8 -5
- package/dist/controllers/users.js +16 -20
- package/dist/controllers/utils.js +6 -11
- package/dist/controllers/webhooks.js +5 -2
- package/dist/database/helpers/fn/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/mssql.js +10 -11
- package/dist/database/helpers/fn/dialects/mysql.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/mysql.js +2 -3
- package/dist/database/helpers/fn/dialects/oracle.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/oracle.js +10 -11
- package/dist/database/helpers/fn/dialects/postgres.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/postgres.js +10 -11
- package/dist/database/helpers/fn/dialects/sqlite.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/sqlite.js +10 -11
- package/dist/database/helpers/fn/types.d.ts +5 -5
- package/dist/database/helpers/fn/types.js +5 -4
- package/dist/database/helpers/geometry/dialects/mssql.d.ts +3 -3
- package/dist/database/helpers/geometry/dialects/mysql.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.d.ts +3 -3
- package/dist/database/helpers/geometry/dialects/postgres.d.ts +3 -3
- package/dist/database/helpers/geometry/dialects/postgres.js +1 -2
- package/dist/database/helpers/geometry/dialects/redshift.d.ts +2 -2
- package/dist/database/helpers/geometry/dialects/sqlite.d.ts +1 -1
- package/dist/database/helpers/geometry/types.d.ts +2 -2
- package/dist/database/helpers/geometry/types.js +1 -2
- package/dist/database/helpers/index.d.ts +5 -5
- package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +2 -2
- package/dist/database/helpers/schema/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/schema/dialects/mysql.d.ts +1 -1
- package/dist/database/helpers/schema/dialects/mysql.js +1 -2
- package/dist/database/helpers/schema/dialects/oracle.d.ts +5 -2
- package/dist/database/helpers/schema/dialects/oracle.js +23 -0
- package/dist/database/helpers/schema/types.d.ts +9 -7
- package/dist/database/helpers/schema/types.js +7 -1
- package/dist/database/helpers/types.d.ts +1 -1
- package/dist/database/helpers/types.js +1 -0
- package/dist/database/index.d.ts +2 -1
- package/dist/database/index.js +8 -8
- package/dist/database/migrations/20201028A-remove-collection-foreign-keys.d.ts +1 -1
- package/dist/database/migrations/20201029A-remove-system-relations.d.ts +1 -1
- package/dist/database/migrations/20201029B-remove-system-collections.d.ts +1 -1
- package/dist/database/migrations/20201029C-remove-system-fields.d.ts +1 -1
- package/dist/database/migrations/20201105A-add-cascade-system-relations.d.ts +1 -1
- package/dist/database/migrations/20201105B-change-webhook-url-type.d.ts +1 -1
- package/dist/database/migrations/20210225A-add-relations-sort-field.d.ts +1 -1
- package/dist/database/migrations/20210225A-add-relations-sort-field.js +1 -2
- package/dist/database/migrations/20210304A-remove-locked-fields.d.ts +1 -1
- package/dist/database/migrations/20210312A-webhooks-collections-text.d.ts +1 -1
- package/dist/database/migrations/20210331A-add-refresh-interval.d.ts +1 -1
- package/dist/database/migrations/20210415A-make-filesize-nullable.d.ts +1 -1
- package/dist/database/migrations/20210416A-add-collections-accountability.d.ts +1 -1
- package/dist/database/migrations/20210422A-remove-files-interface.d.ts +1 -1
- package/dist/database/migrations/20210506A-rename-interfaces.d.ts +1 -1
- package/dist/database/migrations/20210510A-restructure-relations.d.ts +1 -1
- package/dist/database/migrations/20210518A-add-foreign-key-constraints.d.ts +1 -1
- package/dist/database/migrations/20210518A-add-foreign-key-constraints.js +1 -1
- package/dist/database/migrations/20210519A-add-system-fk-triggers.d.ts +1 -1
- package/dist/database/migrations/20210519A-add-system-fk-triggers.js +2 -2
- package/dist/database/migrations/20210521A-add-collections-icon-color.d.ts +1 -1
- package/dist/database/migrations/20210525A-add-insights.d.ts +1 -1
- package/dist/database/migrations/20210608A-add-deep-clone-config.d.ts +1 -1
- package/dist/database/migrations/20210626A-change-filesize-bigint.d.ts +1 -1
- package/dist/database/migrations/20210716A-add-conditions-to-fields.d.ts +1 -1
- package/dist/database/migrations/20210721A-add-default-folder.d.ts +1 -1
- package/dist/database/migrations/20210802A-replace-groups.d.ts +1 -1
- package/dist/database/migrations/20210803A-add-required-to-fields.d.ts +1 -1
- package/dist/database/migrations/20210805A-update-groups.d.ts +1 -1
- package/dist/database/migrations/20210805B-change-image-metadata-structure.d.ts +1 -1
- package/dist/database/migrations/20210811A-add-geometry-config.d.ts +1 -1
- package/dist/database/migrations/20210831A-remove-limit-column.d.ts +1 -1
- package/dist/database/migrations/20210903A-add-auth-provider.d.ts +1 -1
- package/dist/database/migrations/20210907A-webhooks-collections-not-null.d.ts +1 -1
- package/dist/database/migrations/20210910A-move-module-setup.d.ts +1 -1
- package/dist/database/migrations/20210920A-webhooks-url-not-null.d.ts +1 -1
- package/dist/database/migrations/20210924A-add-collection-organization.d.ts +1 -1
- package/dist/database/migrations/20210927A-replace-fields-group.d.ts +1 -1
- package/dist/database/migrations/20210927B-replace-m2m-interface.d.ts +1 -1
- package/dist/database/migrations/20210929A-rename-login-action.d.ts +1 -1
- package/dist/database/migrations/20211007A-update-presets.d.ts +1 -1
- package/dist/database/migrations/20211007A-update-presets.js +7 -9
- package/dist/database/migrations/20211009A-add-auth-data.d.ts +1 -1
- package/dist/database/migrations/20211016A-add-webhook-headers.d.ts +1 -1
- package/dist/database/migrations/20211103A-set-unique-to-user-token.d.ts +1 -1
- package/dist/database/migrations/20211103B-update-special-geometry.d.ts +1 -1
- package/dist/database/migrations/20211104A-remove-collections-listing.d.ts +1 -1
- package/dist/database/migrations/20211118A-add-notifications.d.ts +1 -1
- package/dist/database/migrations/20211211A-add-shares.d.ts +1 -1
- package/dist/database/migrations/20211230A-add-project-descriptor.d.ts +1 -1
- package/dist/database/migrations/20220303A-remove-default-project-color.d.ts +1 -1
- package/dist/database/migrations/20220308A-add-bookmark-icon-and-color.d.ts +1 -1
- package/dist/database/migrations/20220314A-add-translation-strings.d.ts +1 -1
- package/dist/database/migrations/20220322A-rename-field-typecast-flags.d.ts +1 -1
- package/dist/database/migrations/20220323A-add-field-validation.d.ts +1 -1
- package/dist/database/migrations/20220325A-fix-typecast-flags.d.ts +1 -1
- package/dist/database/migrations/20220325B-add-default-language.d.ts +1 -1
- package/dist/database/migrations/20220402A-remove-default-value-panel-icon.d.ts +1 -1
- package/dist/database/migrations/20220429A-add-flows.d.ts +1 -1
- package/dist/database/migrations/20220429B-add-color-to-insights-icon.d.ts +1 -1
- package/dist/database/migrations/20220429C-drop-non-null-from-ip-of-activity.d.ts +1 -1
- package/dist/database/migrations/20220429D-drop-non-null-from-sender-of-notifications.d.ts +1 -1
- package/dist/database/migrations/20220614A-rename-hook-trigger-to-event.d.ts +1 -1
- package/dist/database/migrations/20220801A-update-notifications-timestamp-column.d.ts +1 -1
- package/dist/database/migrations/20220802A-add-custom-aspect-ratios.d.ts +1 -1
- package/dist/database/migrations/20220826A-add-origin-to-accountability.d.ts +1 -1
- package/dist/database/migrations/run.d.ts +1 -1
- package/dist/database/run-ast.d.ts +3 -3
- package/dist/database/run-ast.js +19 -28
- package/dist/database/seeds/run.d.ts +1 -1
- package/dist/database/seeds/run.js +1 -2
- package/dist/database/system-data/app-access-permissions/index.d.ts +1 -1
- package/dist/database/system-data/collections/index.d.ts +1 -1
- package/dist/database/system-data/fields/collections.yaml +2 -0
- package/dist/database/system-data/fields/index.d.ts +1 -1
- package/dist/database/system-data/fields/index.js +1 -2
- package/dist/database/system-data/fields/settings.yaml +4 -0
- package/dist/database/system-data/relations/index.d.ts +1 -1
- package/dist/emitter.d.ts +1 -1
- package/dist/emitter.js +3 -0
- package/dist/env.js +19 -4
- package/dist/exceptions/database/dialects/mssql.d.ts +1 -1
- package/dist/exceptions/database/dialects/mssql.js +5 -6
- package/dist/exceptions/database/dialects/mysql.d.ts +1 -1
- package/dist/exceptions/database/dialects/mysql.js +19 -25
- package/dist/exceptions/database/dialects/oracle.d.ts +1 -1
- package/dist/exceptions/database/dialects/postgres.d.ts +1 -1
- package/dist/exceptions/database/dialects/sqlite.d.ts +1 -1
- package/dist/exceptions/database/translate.d.ts +1 -1
- package/dist/exceptions/database/value-out-of-range.js +1 -1
- package/dist/exceptions/range-not-satisfiable.js +2 -3
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +34 -24
- package/dist/flows.js +56 -30
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +19 -3
- package/dist/messenger.js +8 -6
- package/dist/middleware/authenticate.d.ts +1 -1
- package/dist/middleware/authenticate.js +12 -5
- package/dist/middleware/cache.d.ts +1 -1
- package/dist/middleware/cache.js +7 -7
- package/dist/middleware/check-ip.d.ts +1 -1
- package/dist/middleware/check-ip.js +1 -1
- package/dist/middleware/collection-exists.d.ts +1 -1
- package/dist/middleware/collection-exists.js +2 -2
- package/dist/middleware/cors.d.ts +1 -1
- package/dist/middleware/error-handler.d.ts +1 -1
- package/dist/middleware/error-handler.js +9 -10
- package/dist/middleware/extract-token.d.ts +1 -1
- package/dist/middleware/get-permissions.d.ts +1 -1
- package/dist/middleware/graphql.d.ts +1 -1
- package/dist/middleware/graphql.js +3 -3
- package/dist/middleware/rate-limiter-global.d.ts +5 -0
- package/dist/middleware/rate-limiter-global.js +48 -0
- package/dist/middleware/{rate-limiter.d.ts → rate-limiter-ip.d.ts} +2 -2
- package/dist/middleware/{rate-limiter.js → rate-limiter-ip.js} +3 -3
- package/dist/middleware/respond.d.ts +1 -1
- package/dist/middleware/respond.js +18 -14
- package/dist/middleware/sanitize-query.d.ts +1 -1
- package/dist/middleware/schema.d.ts +1 -1
- package/dist/middleware/use-collection.d.ts +1 -1
- package/dist/operations/condition/index.d.ts +1 -1
- package/dist/operations/exec/index.js +14 -3
- package/dist/operations/item-create/index.js +1 -2
- package/dist/operations/item-delete/index.d.ts +1 -1
- package/dist/operations/item-read/index.d.ts +1 -1
- package/dist/operations/item-update/index.d.ts +1 -1
- package/dist/operations/item-update/index.js +1 -2
- package/dist/operations/notification/index.js +1 -2
- package/dist/operations/request/index.js +21 -20
- package/dist/operations/trigger/index.d.ts +2 -0
- package/dist/operations/trigger/index.js +27 -11
- package/dist/rate-limiter.d.ts +1 -1
- package/dist/rate-limiter.js +8 -8
- package/dist/request/index.d.ts +5 -0
- package/dist/request/index.js +18 -0
- package/dist/request/index.test.d.ts +1 -0
- package/dist/request/request-interceptor.d.ts +2 -0
- package/dist/request/request-interceptor.js +33 -0
- package/dist/request/request-interceptor.test.d.ts +1 -0
- package/dist/request/response-interceptor.d.ts +2 -0
- package/dist/request/response-interceptor.js +9 -0
- package/dist/request/response-interceptor.test.d.ts +1 -0
- package/dist/request/validate-ip.d.ts +1 -0
- package/dist/request/validate-ip.js +27 -0
- package/dist/request/validate-ip.test.d.ts +1 -0
- package/dist/server.js +8 -9
- package/dist/services/activity.d.ts +1 -1
- package/dist/services/activity.js +7 -6
- package/dist/services/assets.d.ts +3 -3
- package/dist/services/assets.js +33 -26
- package/dist/services/authentication.d.ts +2 -2
- package/dist/services/authentication.js +18 -15
- package/dist/services/authorization.d.ts +3 -3
- package/dist/services/authorization.js +27 -31
- package/dist/services/collections.d.ts +5 -5
- package/dist/services/collections.js +52 -48
- package/dist/services/dashboards.d.ts +1 -1
- package/dist/services/fields.d.ts +5 -5
- package/dist/services/fields.js +49 -48
- package/dist/services/files.d.ts +1 -2
- package/dist/services/files.js +70 -108
- package/dist/services/flows.d.ts +2 -2
- package/dist/services/folders.d.ts +1 -1
- package/dist/services/graphql/index.d.ts +4 -4
- package/dist/services/graphql/index.js +181 -170
- package/dist/services/graphql/utils/add-path-to-validation-error.js +1 -2
- package/dist/services/graphql/utils/process-error.d.ts +2 -2
- package/dist/services/graphql/utils/process-error.js +29 -9
- package/dist/services/import-export.d.ts +7 -5
- package/dist/services/import-export.js +41 -24
- package/dist/services/import-export.test.d.ts +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/items.d.ts +3 -3
- package/dist/services/items.js +67 -42
- package/dist/services/mail/index.d.ts +4 -4
- package/dist/services/mail/index.js +9 -5
- package/dist/services/meta.d.ts +3 -3
- package/dist/services/meta.js +10 -9
- package/dist/services/notifications.d.ts +3 -3
- package/dist/services/notifications.js +7 -6
- package/dist/services/operations.d.ts +2 -2
- package/dist/services/panels.d.ts +1 -1
- package/dist/services/payload.d.ts +3 -3
- package/dist/services/payload.js +124 -122
- package/dist/services/permissions.d.ts +3 -3
- package/dist/services/permissions.js +11 -11
- package/dist/services/presets.d.ts +1 -1
- package/dist/services/relations.d.ts +6 -6
- package/dist/services/relations.js +47 -43
- package/dist/services/revisions.d.ts +1 -1
- package/dist/services/roles.d.ts +2 -2
- package/dist/services/roles.js +34 -13
- package/dist/services/schema.d.ts +15 -0
- package/dist/services/schema.js +56 -0
- package/dist/services/schema.test.d.ts +1 -0
- package/dist/services/server.d.ts +3 -3
- package/dist/services/server.js +69 -13
- package/dist/services/settings.d.ts +1 -1
- package/dist/services/shares.d.ts +2 -2
- package/dist/services/shares.js +14 -15
- package/dist/services/specifications.d.ts +4 -4
- package/dist/services/specifications.js +132 -116
- package/dist/services/tfa.d.ts +2 -2
- package/dist/services/tfa.js +7 -5
- package/dist/services/users.d.ts +3 -3
- package/dist/services/users.js +89 -62
- package/dist/services/utils.d.ts +3 -3
- package/dist/services/utils.js +10 -8
- package/dist/services/webhooks.d.ts +2 -2
- package/dist/services/webhooks.js +2 -1
- package/dist/types/assets.d.ts +2 -2
- package/dist/types/ast.d.ts +1 -1
- package/dist/types/auth.d.ts +2 -2
- package/dist/types/collection.d.ts +2 -2
- package/dist/types/database.d.ts +3 -0
- package/dist/types/database.js +4 -0
- package/dist/types/events.d.ts +2 -2
- package/dist/types/graphql.d.ts +2 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/items.d.ts +7 -2
- package/dist/types/services.d.ts +5 -5
- package/dist/types/snapshot.d.ts +25 -3
- package/dist/types/snapshot.js +14 -0
- package/dist/utils/apply-diff.d.ts +9 -0
- package/dist/utils/apply-diff.js +256 -0
- package/dist/utils/apply-diff.test.d.ts +1 -0
- package/dist/utils/apply-query.d.ts +3 -3
- package/dist/utils/apply-query.js +15 -16
- package/dist/utils/apply-snapshot.d.ts +3 -5
- package/dist/utils/apply-snapshot.js +9 -240
- package/dist/utils/construct-flow-tree.d.ts +1 -1
- package/dist/utils/construct-flow-tree.js +2 -2
- package/dist/utils/filter-items.d.ts +1 -1
- package/dist/utils/get-accountability-for-role.d.ts +2 -2
- package/dist/utils/get-accountability-for-role.js +1 -1
- package/dist/utils/get-ast-from-query.d.ts +3 -3
- package/dist/utils/get-ast-from-query.js +22 -28
- package/dist/utils/get-cache-headers.d.ts +4 -2
- package/dist/utils/get-cache-headers.js +21 -21
- package/dist/utils/get-cache-headers.test.d.ts +1 -0
- package/dist/utils/get-cache-key.d.ts +1 -1
- package/dist/utils/get-cache-key.js +2 -3
- package/dist/utils/get-collection-from-alias.d.ts +1 -1
- package/dist/utils/get-column-path.d.ts +2 -2
- package/dist/utils/get-column-path.js +3 -4
- package/dist/utils/get-column.d.ts +4 -4
- package/dist/utils/get-column.js +4 -5
- package/dist/utils/get-default-value.d.ts +2 -2
- package/dist/utils/get-default-value.js +1 -2
- package/dist/utils/get-graphql-query-and-variables.d.ts +1 -1
- package/dist/utils/get-graphql-query-and-variables.js +1 -2
- package/dist/utils/get-graphql-type.d.ts +2 -2
- package/dist/utils/get-graphql-type.js +1 -1
- package/dist/utils/get-ip-from-req.d.ts +1 -1
- package/dist/utils/get-local-type.d.ts +1 -1
- package/dist/utils/get-local-type.js +3 -3
- package/dist/utils/get-milliseconds.d.ts +4 -0
- package/dist/utils/get-milliseconds.js +14 -0
- package/dist/utils/get-milliseconds.test.d.ts +1 -0
- package/dist/utils/get-permissions.d.ts +1 -1
- package/dist/utils/get-permissions.js +1 -1
- package/dist/utils/get-relation-info.d.ts +1 -1
- package/dist/utils/get-relation-info.js +3 -5
- package/dist/utils/get-relation-type.d.ts +1 -1
- package/dist/utils/get-relation-type.js +3 -4
- package/dist/utils/get-schema.d.ts +2 -2
- package/dist/utils/get-schema.js +19 -21
- package/dist/utils/get-snapshot-diff.js +10 -7
- package/dist/utils/get-snapshot.d.ts +3 -3
- package/dist/utils/get-snapshot.js +35 -14
- package/dist/utils/get-versioned-hash.d.ts +1 -0
- package/dist/utils/get-versioned-hash.js +12 -0
- package/dist/utils/get-versioned-hash.test.d.ts +1 -0
- package/dist/utils/is-directus-jwt.js +1 -1
- package/dist/utils/job-queue.js +2 -0
- package/dist/utils/jwt.d.ts +1 -1
- package/dist/utils/map-values-deep.d.ts +1 -0
- package/dist/utils/map-values-deep.js +29 -0
- package/dist/utils/map-values-deep.test.d.ts +1 -0
- package/dist/utils/merge-permissions-for-share.d.ts +1 -1
- package/dist/utils/merge-permissions-for-share.js +3 -4
- package/dist/utils/merge-permissions.d.ts +3 -3
- package/dist/utils/redact-header-cookies.d.ts +1 -0
- package/dist/utils/redact-header-cookies.js +11 -0
- package/dist/utils/redact-header-cookies.test.d.ts +1 -0
- package/dist/utils/reduce-schema.d.ts +1 -1
- package/dist/utils/reduce-schema.js +12 -12
- package/dist/utils/sanitize-query.d.ts +1 -1
- package/dist/utils/sanitize-query.js +1 -1
- package/dist/utils/sanitize-schema.d.ts +30 -0
- package/dist/utils/sanitize-schema.js +80 -0
- package/dist/utils/sanitize-schema.test.d.ts +1 -0
- package/dist/utils/should-skip-cache.d.ts +7 -0
- package/dist/utils/should-skip-cache.js +21 -0
- package/dist/utils/should-skip-cache.test.d.ts +1 -0
- package/dist/utils/track.js +3 -3
- package/dist/utils/transformations.d.ts +1 -1
- package/dist/utils/transformations.js +2 -4
- package/dist/utils/url.js +9 -8
- package/dist/utils/url.test.d.ts +1 -0
- package/dist/utils/user-name.d.ts +1 -1
- package/dist/utils/validate-diff.d.ts +7 -0
- package/dist/utils/validate-diff.js +113 -0
- package/dist/utils/validate-diff.test.d.ts +1 -0
- package/dist/utils/validate-keys.d.ts +2 -2
- package/dist/utils/validate-keys.js +1 -1
- package/dist/utils/validate-query.d.ts +1 -1
- package/dist/utils/validate-query.js +3 -3
- package/dist/utils/validate-query.test.d.ts +1 -0
- package/dist/utils/validate-snapshot.d.ts +5 -0
- package/dist/utils/validate-snapshot.js +71 -0
- package/dist/utils/validate-snapshot.test.d.ts +1 -0
- package/dist/webhooks.js +4 -3
- package/package.json +62 -62
|
@@ -27,19 +27,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.RelationsService = void 0;
|
|
30
|
-
const relations_1 = require("../database/system-data/relations");
|
|
31
|
-
const exceptions_1 = require("../exceptions");
|
|
32
|
-
const utils_1 = require("@directus/shared/utils");
|
|
33
|
-
const items_1 = require("./items");
|
|
34
|
-
const permissions_1 = require("./permissions");
|
|
35
30
|
const schema_1 = __importDefault(require("@directus/schema"));
|
|
36
|
-
const
|
|
37
|
-
const get_default_index_name_1 = require("../utils/get-default-index-name");
|
|
31
|
+
const utils_1 = require("@directus/shared/utils");
|
|
38
32
|
const cache_1 = require("../cache");
|
|
33
|
+
const database_1 = __importStar(require("../database"));
|
|
39
34
|
const helpers_1 = require("../database/helpers");
|
|
35
|
+
const relations_1 = require("../database/system-data/relations");
|
|
40
36
|
const emitter_1 = __importDefault(require("../emitter"));
|
|
37
|
+
const exceptions_1 = require("../exceptions");
|
|
38
|
+
const get_default_index_name_1 = require("../utils/get-default-index-name");
|
|
41
39
|
const get_schema_1 = require("../utils/get-schema");
|
|
40
|
+
const items_1 = require("./items");
|
|
41
|
+
const permissions_1 = require("./permissions");
|
|
42
42
|
class RelationsService {
|
|
43
|
+
knex;
|
|
44
|
+
permissionsService;
|
|
45
|
+
schemaInspector;
|
|
46
|
+
accountability;
|
|
47
|
+
schema;
|
|
48
|
+
relationsItemService;
|
|
49
|
+
systemCache;
|
|
50
|
+
helpers;
|
|
43
51
|
constructor(options) {
|
|
44
52
|
this.knex = options.knex || (0, database_1.default)();
|
|
45
53
|
this.permissionsService = new permissions_1.PermissionsService(options);
|
|
@@ -83,12 +91,11 @@ class RelationsService {
|
|
|
83
91
|
return await this.filterForbidden(results);
|
|
84
92
|
}
|
|
85
93
|
async readOne(collection, field) {
|
|
86
|
-
var _a;
|
|
87
94
|
if (this.accountability && this.accountability.admin !== true) {
|
|
88
95
|
if (this.hasReadAccess === false) {
|
|
89
96
|
throw new exceptions_1.ForbiddenException();
|
|
90
97
|
}
|
|
91
|
-
const permissions =
|
|
98
|
+
const permissions = this.accountability.permissions?.find((permission) => {
|
|
92
99
|
return permission.action === 'read' && permission.collection === collection;
|
|
93
100
|
});
|
|
94
101
|
if (!permissions || !permissions.fields)
|
|
@@ -155,6 +162,7 @@ class RelationsService {
|
|
|
155
162
|
throw new exceptions_1.InvalidPayloadException(`Field "${relation.field}" in collection "${relation.collection}" already has an associated relationship`);
|
|
156
163
|
}
|
|
157
164
|
const runPostColumnChange = await this.helpers.schema.preColumnChange();
|
|
165
|
+
this.helpers.schema.preRelationChange(relation);
|
|
158
166
|
const nestedActionEvents = [];
|
|
159
167
|
try {
|
|
160
168
|
const metaRow = {
|
|
@@ -166,13 +174,12 @@ class RelationsService {
|
|
|
166
174
|
await this.knex.transaction(async (trx) => {
|
|
167
175
|
if (relation.related_collection) {
|
|
168
176
|
await trx.schema.alterTable(relation.collection, async (table) => {
|
|
169
|
-
var _a;
|
|
170
177
|
this.alterType(table, relation);
|
|
171
178
|
const constraintName = (0, get_default_index_name_1.getDefaultIndexName)('foreign', relation.collection, relation.field);
|
|
172
179
|
const builder = table
|
|
173
180
|
.foreign(relation.field, constraintName)
|
|
174
181
|
.references(`${relation.related_collection}.${this.schema.collections[relation.related_collection].primary}`);
|
|
175
|
-
if (
|
|
182
|
+
if (relation.schema?.on_delete) {
|
|
176
183
|
builder.onDelete(relation.schema.on_delete);
|
|
177
184
|
}
|
|
178
185
|
});
|
|
@@ -185,7 +192,7 @@ class RelationsService {
|
|
|
185
192
|
// happens in `filterForbidden` down below
|
|
186
193
|
});
|
|
187
194
|
await relationsItemService.createOne(metaRow, {
|
|
188
|
-
bypassEmitAction: (params) =>
|
|
195
|
+
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
189
196
|
});
|
|
190
197
|
});
|
|
191
198
|
}
|
|
@@ -193,10 +200,10 @@ class RelationsService {
|
|
|
193
200
|
if (runPostColumnChange) {
|
|
194
201
|
await this.helpers.schema.postColumnChange();
|
|
195
202
|
}
|
|
196
|
-
if (
|
|
197
|
-
await (0, cache_1.clearSystemCache)();
|
|
203
|
+
if (opts?.autoPurgeSystemCache !== false) {
|
|
204
|
+
await (0, cache_1.clearSystemCache)({ autoPurgeCache: opts?.autoPurgeCache });
|
|
198
205
|
}
|
|
199
|
-
if (
|
|
206
|
+
if (opts?.emitEvents !== false && nestedActionEvents.length > 0) {
|
|
200
207
|
const updatedSchema = await (0, get_schema_1.getSchema)();
|
|
201
208
|
for (const nestedActionEvent of nestedActionEvents) {
|
|
202
209
|
nestedActionEvent.context.schema = updatedSchema;
|
|
@@ -225,15 +232,15 @@ class RelationsService {
|
|
|
225
232
|
throw new exceptions_1.InvalidPayloadException(`Field "${field}" in collection "${collection}" doesn't have a relationship.`);
|
|
226
233
|
}
|
|
227
234
|
const runPostColumnChange = await this.helpers.schema.preColumnChange();
|
|
235
|
+
this.helpers.schema.preRelationChange(relation);
|
|
228
236
|
const nestedActionEvents = [];
|
|
229
237
|
try {
|
|
230
238
|
await this.knex.transaction(async (trx) => {
|
|
231
239
|
if (existingRelation.related_collection) {
|
|
232
240
|
await trx.schema.alterTable(collection, async (table) => {
|
|
233
|
-
var _a;
|
|
234
241
|
let constraintName = (0, get_default_index_name_1.getDefaultIndexName)('foreign', collection, field);
|
|
235
242
|
// If the FK already exists in the DB, drop it first
|
|
236
|
-
if (existingRelation
|
|
243
|
+
if (existingRelation?.schema) {
|
|
237
244
|
constraintName = existingRelation.schema.constraint_name || constraintName;
|
|
238
245
|
table.dropForeign(field, constraintName);
|
|
239
246
|
constraintName = this.helpers.schema.constraintName(constraintName);
|
|
@@ -243,7 +250,7 @@ class RelationsService {
|
|
|
243
250
|
const builder = table
|
|
244
251
|
.foreign(field, constraintName || undefined)
|
|
245
252
|
.references(`${existingRelation.related_collection}.${this.schema.collections[existingRelation.related_collection].primary}`);
|
|
246
|
-
if (
|
|
253
|
+
if (relation.schema?.on_delete) {
|
|
247
254
|
builder.onDelete(relation.schema.on_delete);
|
|
248
255
|
}
|
|
249
256
|
});
|
|
@@ -256,9 +263,9 @@ class RelationsService {
|
|
|
256
263
|
// happens in `filterForbidden` down below
|
|
257
264
|
});
|
|
258
265
|
if (relation.meta) {
|
|
259
|
-
if (existingRelation
|
|
266
|
+
if (existingRelation?.meta) {
|
|
260
267
|
await relationsItemService.updateOne(existingRelation.meta.id, relation.meta, {
|
|
261
|
-
bypassEmitAction: (params) =>
|
|
268
|
+
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
262
269
|
});
|
|
263
270
|
}
|
|
264
271
|
else {
|
|
@@ -268,7 +275,7 @@ class RelationsService {
|
|
|
268
275
|
many_field: relation.field,
|
|
269
276
|
one_collection: existingRelation.related_collection || null,
|
|
270
277
|
}, {
|
|
271
|
-
bypassEmitAction: (params) =>
|
|
278
|
+
bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
|
|
272
279
|
});
|
|
273
280
|
}
|
|
274
281
|
}
|
|
@@ -278,10 +285,10 @@ class RelationsService {
|
|
|
278
285
|
if (runPostColumnChange) {
|
|
279
286
|
await this.helpers.schema.postColumnChange();
|
|
280
287
|
}
|
|
281
|
-
if (
|
|
282
|
-
await (0, cache_1.clearSystemCache)();
|
|
288
|
+
if (opts?.autoPurgeSystemCache !== false) {
|
|
289
|
+
await (0, cache_1.clearSystemCache)({ autoPurgeCache: opts?.autoPurgeCache });
|
|
283
290
|
}
|
|
284
|
-
if (
|
|
291
|
+
if (opts?.emitEvents !== false && nestedActionEvents.length > 0) {
|
|
285
292
|
const updatedSchema = await (0, get_schema_1.getSchema)();
|
|
286
293
|
for (const nestedActionEvent of nestedActionEvents) {
|
|
287
294
|
nestedActionEvent.context.schema = updatedSchema;
|
|
@@ -311,10 +318,9 @@ class RelationsService {
|
|
|
311
318
|
const nestedActionEvents = [];
|
|
312
319
|
try {
|
|
313
320
|
await this.knex.transaction(async (trx) => {
|
|
314
|
-
var _a;
|
|
315
321
|
const existingConstraints = await this.schemaInspector.foreignKeys();
|
|
316
322
|
const constraintNames = existingConstraints.map((key) => key.constraint_name);
|
|
317
|
-
if (
|
|
323
|
+
if (existingRelation.schema?.constraint_name &&
|
|
318
324
|
constraintNames.includes(existingRelation.schema.constraint_name)) {
|
|
319
325
|
await trx.schema.alterTable(existingRelation.collection, (table) => {
|
|
320
326
|
table.dropForeign(existingRelation.field, existingRelation.schema.constraint_name);
|
|
@@ -335,7 +341,7 @@ class RelationsService {
|
|
|
335
341
|
accountability: this.accountability,
|
|
336
342
|
},
|
|
337
343
|
};
|
|
338
|
-
if (opts
|
|
344
|
+
if (opts?.bypassEmitAction) {
|
|
339
345
|
opts.bypassEmitAction(actionEvent);
|
|
340
346
|
}
|
|
341
347
|
else {
|
|
@@ -347,10 +353,10 @@ class RelationsService {
|
|
|
347
353
|
if (runPostColumnChange) {
|
|
348
354
|
await this.helpers.schema.postColumnChange();
|
|
349
355
|
}
|
|
350
|
-
if (
|
|
351
|
-
await (0, cache_1.clearSystemCache)();
|
|
356
|
+
if (opts?.autoPurgeSystemCache !== false) {
|
|
357
|
+
await (0, cache_1.clearSystemCache)({ autoPurgeCache: opts?.autoPurgeCache });
|
|
352
358
|
}
|
|
353
|
-
if (
|
|
359
|
+
if (opts?.emitEvents !== false && nestedActionEvents.length > 0) {
|
|
354
360
|
const updatedSchema = await (0, get_schema_1.getSchema)();
|
|
355
361
|
for (const nestedActionEvent of nestedActionEvents) {
|
|
356
362
|
nestedActionEvent.context.schema = updatedSchema;
|
|
@@ -363,10 +369,9 @@ class RelationsService {
|
|
|
363
369
|
* Whether or not the current user has read access to relations
|
|
364
370
|
*/
|
|
365
371
|
get hasReadAccess() {
|
|
366
|
-
|
|
367
|
-
return !!((_b = (_a = this.accountability) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.find((permission) => {
|
|
372
|
+
return !!this.accountability?.permissions?.find((permission) => {
|
|
368
373
|
return permission.collection === 'directus_relations' && permission.action === 'read';
|
|
369
|
-
})
|
|
374
|
+
});
|
|
370
375
|
}
|
|
371
376
|
/**
|
|
372
377
|
* Combine raw schema foreign key information with Directus relations meta rows to form final
|
|
@@ -398,11 +403,10 @@ class RelationsService {
|
|
|
398
403
|
return !results.find((relation) => relation.meta === meta);
|
|
399
404
|
})
|
|
400
405
|
.map((meta) => {
|
|
401
|
-
var _a;
|
|
402
406
|
return {
|
|
403
407
|
collection: meta.many_collection,
|
|
404
408
|
field: meta.many_field,
|
|
405
|
-
related_collection:
|
|
409
|
+
related_collection: meta.one_collection ?? null,
|
|
406
410
|
schema: null,
|
|
407
411
|
meta: meta,
|
|
408
412
|
};
|
|
@@ -415,16 +419,16 @@ class RelationsService {
|
|
|
415
419
|
* permissions to
|
|
416
420
|
*/
|
|
417
421
|
async filterForbidden(relations) {
|
|
418
|
-
|
|
419
|
-
if (this.accountability === null || ((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) === true)
|
|
422
|
+
if (this.accountability === null || this.accountability?.admin === true)
|
|
420
423
|
return relations;
|
|
421
|
-
const allowedCollections =
|
|
424
|
+
const allowedCollections = this.accountability.permissions
|
|
425
|
+
?.filter((permission) => {
|
|
422
426
|
return permission.action === 'read';
|
|
423
|
-
})
|
|
427
|
+
})
|
|
428
|
+
.map(({ collection }) => collection) ?? [];
|
|
424
429
|
const allowedFields = this.permissionsService.getAllowedFields('read');
|
|
425
430
|
relations = (0, utils_1.toArray)(relations);
|
|
426
431
|
return relations.filter((relation) => {
|
|
427
|
-
var _a, _b, _c;
|
|
428
432
|
let collectionsAllowed = true;
|
|
429
433
|
let fieldsAllowed = true;
|
|
430
434
|
if (allowedCollections.includes(relation.collection) === false) {
|
|
@@ -433,8 +437,8 @@ class RelationsService {
|
|
|
433
437
|
if (relation.related_collection && allowedCollections.includes(relation.related_collection) === false) {
|
|
434
438
|
collectionsAllowed = false;
|
|
435
439
|
}
|
|
436
|
-
if (
|
|
437
|
-
|
|
440
|
+
if (relation.meta?.one_allowed_collections &&
|
|
441
|
+
relation.meta?.one_allowed_collections.every((collection) => allowedCollections.includes(collection)) === false) {
|
|
438
442
|
collectionsAllowed = false;
|
|
439
443
|
}
|
|
440
444
|
if (!allowedFields[relation.collection] ||
|
|
@@ -443,7 +447,7 @@ class RelationsService {
|
|
|
443
447
|
fieldsAllowed = false;
|
|
444
448
|
}
|
|
445
449
|
if (relation.related_collection &&
|
|
446
|
-
|
|
450
|
+
relation.meta?.one_field &&
|
|
447
451
|
(!allowedFields[relation.related_collection] ||
|
|
448
452
|
(allowedFields[relation.related_collection].includes('*') === false &&
|
|
449
453
|
allowedFields[relation.related_collection].includes(relation.meta.one_field) === false))) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractServiceOptions, PrimaryKey } from '../types';
|
|
1
|
+
import type { AbstractServiceOptions, PrimaryKey } from '../types';
|
|
2
2
|
import { ItemsService } from './index';
|
|
3
3
|
export declare class RevisionsService extends ItemsService {
|
|
4
4
|
constructor(options: AbstractServiceOptions);
|
package/dist/services/roles.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { Query } from '@directus/shared/types';
|
|
2
|
+
import type { AbstractServiceOptions, MutationOptions, PrimaryKey } from '../types';
|
|
3
3
|
import { ItemsService } from './items';
|
|
4
4
|
export declare class RolesService extends ItemsService {
|
|
5
5
|
constructor(options: AbstractServiceOptions);
|
package/dist/services/roles.js
CHANGED
|
@@ -18,7 +18,7 @@ class RolesService extends items_1.ItemsService {
|
|
|
18
18
|
.whereNotIn('id', excludeKeys)
|
|
19
19
|
.andWhere({ admin_access: true })
|
|
20
20
|
.first();
|
|
21
|
-
const otherAdminRolesCount = +(
|
|
21
|
+
const otherAdminRolesCount = +(otherAdminRoles?.count || 0);
|
|
22
22
|
if (otherAdminRolesCount === 0)
|
|
23
23
|
throw new exceptions_1.UnprocessableEntityException(`You can't delete the last admin role.`);
|
|
24
24
|
}
|
|
@@ -49,15 +49,20 @@ class RolesService extends items_1.ItemsService {
|
|
|
49
49
|
.andWhere({ 'directus_roles.admin_access': true })
|
|
50
50
|
.leftJoin('directus_roles', 'directus_users.role', 'directus_roles.id')
|
|
51
51
|
.first();
|
|
52
|
-
const otherAdminUsersCount = +(
|
|
52
|
+
const otherAdminUsersCount = +(otherAdminUsers?.count || 0);
|
|
53
53
|
if (otherAdminUsersCount === 0) {
|
|
54
54
|
throw new exceptions_1.UnprocessableEntityException(`You can't remove the last admin user from the admin role.`);
|
|
55
55
|
}
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
58
|
async updateOne(key, data, opts) {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
try {
|
|
60
|
+
if ('users' in data) {
|
|
61
|
+
await this.checkForOtherAdminUsers(key, data.users);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
(opts || (opts = {})).preMutationException = err;
|
|
61
66
|
}
|
|
62
67
|
return super.updateOne(key, data, opts);
|
|
63
68
|
}
|
|
@@ -65,14 +70,24 @@ class RolesService extends items_1.ItemsService {
|
|
|
65
70
|
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
66
71
|
const keys = data.map((item) => item[primaryKeyField]);
|
|
67
72
|
const setsToNoAdmin = data.some((item) => item.admin_access === false);
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
try {
|
|
74
|
+
if (setsToNoAdmin) {
|
|
75
|
+
await this.checkForOtherAdminRoles(keys);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
(opts || (opts = {})).preMutationException = err;
|
|
70
80
|
}
|
|
71
81
|
return super.updateBatch(data, opts);
|
|
72
82
|
}
|
|
73
83
|
async updateMany(keys, data, opts) {
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
try {
|
|
85
|
+
if ('admin_access' in data && data.admin_access === false) {
|
|
86
|
+
await this.checkForOtherAdminRoles(keys);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
(opts || (opts = {})).preMutationException = err;
|
|
76
91
|
}
|
|
77
92
|
return super.updateMany(keys, data, opts);
|
|
78
93
|
}
|
|
@@ -81,7 +96,13 @@ class RolesService extends items_1.ItemsService {
|
|
|
81
96
|
return key;
|
|
82
97
|
}
|
|
83
98
|
async deleteMany(keys) {
|
|
84
|
-
|
|
99
|
+
const opts = {};
|
|
100
|
+
try {
|
|
101
|
+
await this.checkForOtherAdminRoles(keys);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
opts.preMutationException = err;
|
|
105
|
+
}
|
|
85
106
|
await this.knex.transaction(async (trx) => {
|
|
86
107
|
const itemsService = new items_1.ItemsService('directus_roles', {
|
|
87
108
|
knex: trx,
|
|
@@ -106,17 +127,17 @@ class RolesService extends items_1.ItemsService {
|
|
|
106
127
|
// Delete permissions/presets for this role, suspend all remaining users in role
|
|
107
128
|
await permissionsService.deleteByQuery({
|
|
108
129
|
filter: { role: { _in: keys } },
|
|
109
|
-
});
|
|
130
|
+
}, opts);
|
|
110
131
|
await presetsService.deleteByQuery({
|
|
111
132
|
filter: { role: { _in: keys } },
|
|
112
|
-
});
|
|
133
|
+
}, opts);
|
|
113
134
|
await usersService.updateByQuery({
|
|
114
135
|
filter: { role: { _in: keys } },
|
|
115
136
|
}, {
|
|
116
137
|
status: 'suspended',
|
|
117
138
|
role: null,
|
|
118
|
-
});
|
|
119
|
-
await itemsService.deleteMany(keys);
|
|
139
|
+
}, opts);
|
|
140
|
+
await itemsService.deleteMany(keys, opts);
|
|
120
141
|
});
|
|
121
142
|
return keys;
|
|
122
143
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Accountability } from '@directus/shared/types';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
import type { AbstractServiceOptions, Snapshot, SnapshotDiff, SnapshotDiffWithHash, SnapshotWithHash } from '../types';
|
|
4
|
+
export declare class SchemaService {
|
|
5
|
+
knex: Knex;
|
|
6
|
+
accountability: Accountability | null;
|
|
7
|
+
constructor(options: Omit<AbstractServiceOptions, 'schema'>);
|
|
8
|
+
snapshot(): Promise<Snapshot>;
|
|
9
|
+
apply(payload: SnapshotDiffWithHash): Promise<void>;
|
|
10
|
+
diff(snapshot: Snapshot, options?: {
|
|
11
|
+
currentSnapshot?: Snapshot;
|
|
12
|
+
force?: boolean;
|
|
13
|
+
}): Promise<SnapshotDiff | null>;
|
|
14
|
+
getHashedSnapshot(snapshot: Snapshot): SnapshotWithHash;
|
|
15
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SchemaService = void 0;
|
|
7
|
+
const database_1 = __importDefault(require("../database"));
|
|
8
|
+
const exceptions_1 = require("../exceptions");
|
|
9
|
+
const apply_diff_1 = require("../utils/apply-diff");
|
|
10
|
+
const get_snapshot_1 = require("../utils/get-snapshot");
|
|
11
|
+
const get_snapshot_diff_1 = require("../utils/get-snapshot-diff");
|
|
12
|
+
const get_versioned_hash_1 = require("../utils/get-versioned-hash");
|
|
13
|
+
const validate_diff_1 = require("../utils/validate-diff");
|
|
14
|
+
const validate_snapshot_1 = require("../utils/validate-snapshot");
|
|
15
|
+
class SchemaService {
|
|
16
|
+
knex;
|
|
17
|
+
accountability;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.knex = options.knex ?? (0, database_1.default)();
|
|
20
|
+
this.accountability = options.accountability ?? null;
|
|
21
|
+
}
|
|
22
|
+
async snapshot() {
|
|
23
|
+
if (this.accountability?.admin !== true)
|
|
24
|
+
throw new exceptions_1.ForbiddenException();
|
|
25
|
+
const currentSnapshot = await (0, get_snapshot_1.getSnapshot)({ database: this.knex });
|
|
26
|
+
return currentSnapshot;
|
|
27
|
+
}
|
|
28
|
+
async apply(payload) {
|
|
29
|
+
if (this.accountability?.admin !== true)
|
|
30
|
+
throw new exceptions_1.ForbiddenException();
|
|
31
|
+
const currentSnapshot = await this.snapshot();
|
|
32
|
+
const snapshotWithHash = this.getHashedSnapshot(currentSnapshot);
|
|
33
|
+
if (!(0, validate_diff_1.validateApplyDiff)(payload, snapshotWithHash))
|
|
34
|
+
return;
|
|
35
|
+
await (0, apply_diff_1.applyDiff)(currentSnapshot, payload.diff, { database: this.knex });
|
|
36
|
+
}
|
|
37
|
+
async diff(snapshot, options) {
|
|
38
|
+
if (this.accountability?.admin !== true)
|
|
39
|
+
throw new exceptions_1.ForbiddenException();
|
|
40
|
+
(0, validate_snapshot_1.validateSnapshot)(snapshot, options?.force);
|
|
41
|
+
const currentSnapshot = options?.currentSnapshot ?? (await (0, get_snapshot_1.getSnapshot)({ database: this.knex }));
|
|
42
|
+
const diff = (0, get_snapshot_diff_1.getSnapshotDiff)(currentSnapshot, snapshot);
|
|
43
|
+
if (diff.collections.length === 0 && diff.fields.length === 0 && diff.relations.length === 0) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return diff;
|
|
47
|
+
}
|
|
48
|
+
getHashedSnapshot(snapshot) {
|
|
49
|
+
const snapshotHash = (0, get_versioned_hash_1.getVersionedHash)(snapshot);
|
|
50
|
+
return {
|
|
51
|
+
...snapshot,
|
|
52
|
+
hash: snapshotHash,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.SchemaService = SchemaService;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Knex } from 'knex';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { Knex } from 'knex';
|
|
2
|
+
import type { Accountability, SchemaOverview } from '@directus/shared/types';
|
|
3
|
+
import type { AbstractServiceOptions } from '../types';
|
|
4
4
|
import { SettingsService } from './settings';
|
|
5
5
|
export declare class ServerService {
|
|
6
6
|
knex: Knex;
|
package/dist/services/server.js
CHANGED
|
@@ -30,20 +30,25 @@ exports.ServerService = void 0;
|
|
|
30
30
|
const lodash_1 = require("lodash");
|
|
31
31
|
const os_1 = __importDefault(require("os"));
|
|
32
32
|
const perf_hooks_1 = require("perf_hooks");
|
|
33
|
+
const utils_1 = require("@directus/shared/utils");
|
|
34
|
+
const node_stream_1 = require("node:stream");
|
|
33
35
|
// @ts-ignore
|
|
34
36
|
const package_json_1 = require("../../package.json");
|
|
35
37
|
const cache_1 = require("../cache");
|
|
36
38
|
const database_1 = __importStar(require("../database"));
|
|
37
39
|
const env_1 = __importDefault(require("../env"));
|
|
38
40
|
const logger_1 = __importDefault(require("../logger"));
|
|
39
|
-
const rate_limiter_1 = require("../middleware/rate-limiter");
|
|
40
|
-
const storage_1 = require("../storage");
|
|
41
|
-
const utils_1 = require("@directus/shared/utils");
|
|
42
41
|
const mailer_1 = __importDefault(require("../mailer"));
|
|
43
|
-
const
|
|
42
|
+
const rate_limiter_global_1 = require("../middleware/rate-limiter-global");
|
|
43
|
+
const rate_limiter_ip_1 = require("../middleware/rate-limiter-ip");
|
|
44
|
+
const storage_1 = require("../storage");
|
|
44
45
|
const get_os_info_1 = require("../utils/get-os-info");
|
|
45
|
-
const
|
|
46
|
+
const settings_1 = require("./settings");
|
|
46
47
|
class ServerService {
|
|
48
|
+
knex;
|
|
49
|
+
accountability;
|
|
50
|
+
settingsService;
|
|
51
|
+
schema;
|
|
47
52
|
constructor(options) {
|
|
48
53
|
this.knex = options.knex || (0, database_1.default)();
|
|
49
54
|
this.accountability = options.accountability || null;
|
|
@@ -51,7 +56,6 @@ class ServerService {
|
|
|
51
56
|
this.settingsService = new settings_1.SettingsService({ knex: this.knex, schema: this.schema });
|
|
52
57
|
}
|
|
53
58
|
async serverInfo() {
|
|
54
|
-
var _a, _b;
|
|
55
59
|
const info = {};
|
|
56
60
|
const projectInfo = await this.settingsService.readSingleton({
|
|
57
61
|
fields: [
|
|
@@ -67,7 +71,7 @@ class ServerService {
|
|
|
67
71
|
],
|
|
68
72
|
});
|
|
69
73
|
info.project = projectInfo;
|
|
70
|
-
if (
|
|
74
|
+
if (this.accountability?.user) {
|
|
71
75
|
if (env_1.default.RATE_LIMITER_ENABLED) {
|
|
72
76
|
info.rateLimit = {
|
|
73
77
|
points: env_1.default.RATE_LIMITER_POINTS,
|
|
@@ -77,11 +81,20 @@ class ServerService {
|
|
|
77
81
|
else {
|
|
78
82
|
info.rateLimit = false;
|
|
79
83
|
}
|
|
84
|
+
if (env_1.default.RATE_LIMITER_GLOBAL_ENABLED) {
|
|
85
|
+
info.rateLimitGlobal = {
|
|
86
|
+
points: env_1.default.RATE_LIMITER_GLOBAL_POINTS,
|
|
87
|
+
duration: env_1.default.RATE_LIMITER_GLOBAL_DURATION,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
info.rateLimitGlobal = false;
|
|
92
|
+
}
|
|
80
93
|
info.flows = {
|
|
81
94
|
execAllowedModules: env_1.default.FLOWS_EXEC_ALLOWED_MODULES ? (0, utils_1.toArray)(env_1.default.FLOWS_EXEC_ALLOWED_MODULES) : [],
|
|
82
95
|
};
|
|
83
96
|
}
|
|
84
|
-
if (
|
|
97
|
+
if (this.accountability?.admin === true) {
|
|
85
98
|
const { osType, osVersion } = (0, get_os_info_1.getOSInfo)();
|
|
86
99
|
info.directus = {
|
|
87
100
|
version: package_json_1.version,
|
|
@@ -100,14 +113,20 @@ class ServerService {
|
|
|
100
113
|
return info;
|
|
101
114
|
}
|
|
102
115
|
async health() {
|
|
103
|
-
var _a;
|
|
104
116
|
const { nanoid } = await import('nanoid');
|
|
105
117
|
const checkID = nanoid(5);
|
|
106
118
|
const data = {
|
|
107
119
|
status: 'ok',
|
|
108
120
|
releaseId: package_json_1.version,
|
|
109
121
|
serviceId: env_1.default.KEY,
|
|
110
|
-
checks: (0, lodash_1.merge)(...(await Promise.all([
|
|
122
|
+
checks: (0, lodash_1.merge)(...(await Promise.all([
|
|
123
|
+
testDatabase(),
|
|
124
|
+
testCache(),
|
|
125
|
+
testRateLimiter(),
|
|
126
|
+
testRateLimiterGlobal(),
|
|
127
|
+
testStorage(),
|
|
128
|
+
testEmail(),
|
|
129
|
+
]))),
|
|
111
130
|
};
|
|
112
131
|
for (const [service, healthData] of Object.entries(data.checks)) {
|
|
113
132
|
for (const healthCheck of healthData) {
|
|
@@ -126,7 +145,7 @@ class ServerService {
|
|
|
126
145
|
if (data.status === 'error')
|
|
127
146
|
break;
|
|
128
147
|
}
|
|
129
|
-
if (
|
|
148
|
+
if (this.accountability?.admin !== true) {
|
|
130
149
|
return { status: data.status };
|
|
131
150
|
}
|
|
132
151
|
else {
|
|
@@ -229,8 +248,8 @@ class ServerService {
|
|
|
229
248
|
};
|
|
230
249
|
const startTime = perf_hooks_1.performance.now();
|
|
231
250
|
try {
|
|
232
|
-
await
|
|
233
|
-
await
|
|
251
|
+
await rate_limiter_ip_1.rateLimiter.consume(`health-${checkID}`, 1);
|
|
252
|
+
await rate_limiter_ip_1.rateLimiter.delete(`health-${checkID}`);
|
|
234
253
|
}
|
|
235
254
|
catch (err) {
|
|
236
255
|
checks['rateLimiter:responseTime'][0].status = 'error';
|
|
@@ -246,6 +265,43 @@ class ServerService {
|
|
|
246
265
|
}
|
|
247
266
|
return checks;
|
|
248
267
|
}
|
|
268
|
+
async function testRateLimiterGlobal() {
|
|
269
|
+
if (env_1.default.RATE_LIMITER_GLOBAL_ENABLED !== true) {
|
|
270
|
+
return {};
|
|
271
|
+
}
|
|
272
|
+
const checks = {
|
|
273
|
+
'rateLimiterGlobal:responseTime': [
|
|
274
|
+
{
|
|
275
|
+
status: 'ok',
|
|
276
|
+
componentType: 'ratelimiter',
|
|
277
|
+
observedValue: 0,
|
|
278
|
+
observedUnit: 'ms',
|
|
279
|
+
threshold: env_1.default.RATE_LIMITER_GLOBAL_HEALTHCHECK_THRESHOLD
|
|
280
|
+
? +env_1.default.RATE_LIMITER_GLOBAL_HEALTHCHECK_THRESHOLD
|
|
281
|
+
: 150,
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
};
|
|
285
|
+
const startTime = perf_hooks_1.performance.now();
|
|
286
|
+
try {
|
|
287
|
+
await rate_limiter_global_1.rateLimiterGlobal.consume(`health-${checkID}`, 1);
|
|
288
|
+
await rate_limiter_global_1.rateLimiterGlobal.delete(`health-${checkID}`);
|
|
289
|
+
}
|
|
290
|
+
catch (err) {
|
|
291
|
+
checks['rateLimiterGlobal:responseTime'][0].status = 'error';
|
|
292
|
+
checks['rateLimiterGlobal:responseTime'][0].output = err;
|
|
293
|
+
}
|
|
294
|
+
finally {
|
|
295
|
+
const endTime = perf_hooks_1.performance.now();
|
|
296
|
+
checks['rateLimiterGlobal:responseTime'][0].observedValue = +(endTime - startTime).toFixed(3);
|
|
297
|
+
if (checks['rateLimiterGlobal:responseTime'][0].observedValue >
|
|
298
|
+
checks['rateLimiterGlobal:responseTime'][0].threshold &&
|
|
299
|
+
checks['rateLimiterGlobal:responseTime'][0].status !== 'error') {
|
|
300
|
+
checks['rateLimiterGlobal:responseTime'][0].status = 'warn';
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return checks;
|
|
304
|
+
}
|
|
249
305
|
async function testStorage() {
|
|
250
306
|
const storage = await (0, storage_1.getStorage)();
|
|
251
307
|
const checks = {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AbstractServiceOptions, LoginResult,
|
|
2
|
-
import { ItemsService } from './items';
|
|
1
|
+
import type { AbstractServiceOptions, Item, LoginResult, MutationOptions, PrimaryKey } from '../types';
|
|
3
2
|
import { AuthorizationService } from './authorization';
|
|
3
|
+
import { ItemsService } from './items';
|
|
4
4
|
export declare class SharesService extends ItemsService {
|
|
5
5
|
authorizationService: AuthorizationService;
|
|
6
6
|
constructor(options: AbstractServiceOptions);
|