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
package/dist/app.js
CHANGED
|
@@ -44,20 +44,21 @@ const folders_1 = __importDefault(require("./controllers/folders"));
|
|
|
44
44
|
const graphql_1 = __importDefault(require("./controllers/graphql"));
|
|
45
45
|
const items_1 = __importDefault(require("./controllers/items"));
|
|
46
46
|
const not_found_1 = __importDefault(require("./controllers/not-found"));
|
|
47
|
-
const panels_1 = __importDefault(require("./controllers/panels"));
|
|
48
47
|
const notifications_1 = __importDefault(require("./controllers/notifications"));
|
|
49
48
|
const operations_1 = __importDefault(require("./controllers/operations"));
|
|
49
|
+
const panels_1 = __importDefault(require("./controllers/panels"));
|
|
50
50
|
const permissions_1 = __importDefault(require("./controllers/permissions"));
|
|
51
51
|
const presets_1 = __importDefault(require("./controllers/presets"));
|
|
52
52
|
const relations_1 = __importDefault(require("./controllers/relations"));
|
|
53
53
|
const revisions_1 = __importDefault(require("./controllers/revisions"));
|
|
54
54
|
const roles_1 = __importDefault(require("./controllers/roles"));
|
|
55
|
+
const schema_1 = __importDefault(require("./controllers/schema"));
|
|
55
56
|
const server_1 = __importDefault(require("./controllers/server"));
|
|
56
57
|
const settings_1 = __importDefault(require("./controllers/settings"));
|
|
58
|
+
const shares_1 = __importDefault(require("./controllers/shares"));
|
|
57
59
|
const users_1 = __importDefault(require("./controllers/users"));
|
|
58
60
|
const utils_1 = __importDefault(require("./controllers/utils"));
|
|
59
61
|
const webhooks_1 = __importDefault(require("./controllers/webhooks"));
|
|
60
|
-
const shares_1 = __importDefault(require("./controllers/shares"));
|
|
61
62
|
const database_1 = require("./database");
|
|
62
63
|
const emitter_1 = __importDefault(require("./emitter"));
|
|
63
64
|
const env_1 = __importDefault(require("./env"));
|
|
@@ -66,25 +67,25 @@ const extensions_2 = require("./extensions");
|
|
|
66
67
|
const flows_2 = require("./flows");
|
|
67
68
|
const logger_1 = __importStar(require("./logger"));
|
|
68
69
|
const authenticate_1 = __importDefault(require("./middleware/authenticate"));
|
|
69
|
-
const get_permissions_1 = __importDefault(require("./middleware/get-permissions"));
|
|
70
70
|
const cache_1 = __importDefault(require("./middleware/cache"));
|
|
71
71
|
const check_ip_1 = require("./middleware/check-ip");
|
|
72
72
|
const cors_1 = __importDefault(require("./middleware/cors"));
|
|
73
73
|
const error_handler_1 = __importDefault(require("./middleware/error-handler"));
|
|
74
74
|
const extract_token_1 = __importDefault(require("./middleware/extract-token"));
|
|
75
|
-
const
|
|
75
|
+
const get_permissions_1 = __importDefault(require("./middleware/get-permissions"));
|
|
76
|
+
const rate_limiter_global_1 = __importDefault(require("./middleware/rate-limiter-global"));
|
|
77
|
+
const rate_limiter_ip_1 = __importDefault(require("./middleware/rate-limiter-ip"));
|
|
76
78
|
const sanitize_query_1 = __importDefault(require("./middleware/sanitize-query"));
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
+
const schema_2 = __importDefault(require("./middleware/schema"));
|
|
80
|
+
const lodash_1 = require("lodash");
|
|
81
|
+
const auth_2 = require("./auth");
|
|
82
|
+
const cache_2 = require("./cache");
|
|
83
|
+
const get_config_from_env_1 = require("./utils/get-config-from-env");
|
|
79
84
|
const track_1 = require("./utils/track");
|
|
85
|
+
const url_1 = require("./utils/url");
|
|
80
86
|
const validate_env_1 = require("./utils/validate-env");
|
|
81
87
|
const validate_storage_1 = require("./utils/validate-storage");
|
|
82
88
|
const webhooks_2 = require("./webhooks");
|
|
83
|
-
const cache_2 = require("./cache");
|
|
84
|
-
const auth_2 = require("./auth");
|
|
85
|
-
const url_1 = require("./utils/url");
|
|
86
|
-
const get_config_from_env_1 = require("./utils/get-config-from-env");
|
|
87
|
-
const lodash_1 = require("lodash");
|
|
88
89
|
async function createApp() {
|
|
89
90
|
const helmet = await import('helmet');
|
|
90
91
|
(0, validate_env_1.validateEnv)(['KEY', 'SECRET']);
|
|
@@ -165,7 +166,7 @@ async function createApp() {
|
|
|
165
166
|
app.get('/robots.txt', (_, res) => {
|
|
166
167
|
res.set('Content-Type', 'text/plain');
|
|
167
168
|
res.status(200);
|
|
168
|
-
res.send(
|
|
169
|
+
res.send(env_1.default.ROBOTS_TXT);
|
|
169
170
|
});
|
|
170
171
|
if (env_1.default.SERVE_APP) {
|
|
171
172
|
const adminPath = require.resolve('@directus/app');
|
|
@@ -191,15 +192,18 @@ async function createApp() {
|
|
|
191
192
|
app.use('/admin/*', sendHtml);
|
|
192
193
|
}
|
|
193
194
|
// use the rate limiter - all routes for now
|
|
195
|
+
if (env_1.default.RATE_LIMITER_GLOBAL_ENABLED === true) {
|
|
196
|
+
app.use(rate_limiter_global_1.default);
|
|
197
|
+
}
|
|
194
198
|
if (env_1.default.RATE_LIMITER_ENABLED === true) {
|
|
195
|
-
app.use(
|
|
199
|
+
app.use(rate_limiter_ip_1.default);
|
|
196
200
|
}
|
|
197
201
|
app.get('/server/ping', (req, res) => res.send('pong'));
|
|
198
202
|
app.use(authenticate_1.default);
|
|
199
203
|
app.use(check_ip_1.checkIP);
|
|
200
204
|
app.use(sanitize_query_1.default);
|
|
201
205
|
app.use(cache_1.default);
|
|
202
|
-
app.use(
|
|
206
|
+
app.use(schema_2.default);
|
|
203
207
|
app.use(get_permissions_1.default);
|
|
204
208
|
await emitter_1.default.emitInit('middlewares.after', { app });
|
|
205
209
|
await emitter_1.default.emitInit('routes.before', { app });
|
|
@@ -223,6 +227,7 @@ async function createApp() {
|
|
|
223
227
|
app.use('/relations', relations_1.default);
|
|
224
228
|
app.use('/revisions', revisions_1.default);
|
|
225
229
|
app.use('/roles', roles_1.default);
|
|
230
|
+
app.use('/schema', schema_1.default);
|
|
226
231
|
app.use('/server', server_1.default);
|
|
227
232
|
app.use('/settings', settings_1.default);
|
|
228
233
|
app.use('/shares', shares_1.default);
|
package/dist/auth/auth.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SchemaOverview } from '@directus/shared/types';
|
|
2
|
-
import { Knex } from 'knex';
|
|
3
|
-
import { AuthDriverOptions, User } from '../types';
|
|
1
|
+
import type { SchemaOverview } from '@directus/shared/types';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
import type { AuthDriverOptions, User } from '../types';
|
|
4
4
|
export declare abstract class AuthDriver {
|
|
5
5
|
knex: Knex;
|
|
6
6
|
schema: SchemaOverview;
|
package/dist/auth/auth.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { Client } from 'ldapjs';
|
|
3
|
-
import { AuthDriver } from '../auth';
|
|
4
|
-
import { AuthDriverOptions, User } from '../../types';
|
|
5
3
|
import { UsersService } from '../../services';
|
|
4
|
+
import type { AuthDriverOptions, User } from '../../types';
|
|
5
|
+
import { AuthDriver } from '../auth';
|
|
6
6
|
export declare class LDAPAuthDriver extends AuthDriver {
|
|
7
7
|
bindClient: Client;
|
|
8
8
|
usersService: UsersService;
|
|
@@ -28,32 +28,34 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.createLDAPAuthRouter = exports.LDAPAuthDriver = void 0;
|
|
30
30
|
const express_1 = require("express");
|
|
31
|
-
const ldapjs_1 = __importStar(require("ldapjs"));
|
|
32
|
-
const ms_1 = __importDefault(require("ms"));
|
|
33
|
-
const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
|
|
34
31
|
const joi_1 = __importDefault(require("joi"));
|
|
35
|
-
const
|
|
32
|
+
const ldapjs_1 = __importStar(require("ldapjs"));
|
|
33
|
+
const env_1 = __importDefault(require("../../env"));
|
|
36
34
|
const exceptions_1 = require("../../exceptions");
|
|
37
35
|
const record_not_unique_1 = require("../../exceptions/database/record-not-unique");
|
|
36
|
+
const logger_1 = __importDefault(require("../../logger"));
|
|
37
|
+
const respond_1 = require("../../middleware/respond");
|
|
38
38
|
const services_1 = require("../../services");
|
|
39
39
|
const async_handler_1 = __importDefault(require("../../utils/async-handler"));
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
40
|
+
const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
|
|
41
|
+
const get_milliseconds_1 = require("../../utils/get-milliseconds");
|
|
42
|
+
const auth_1 = require("../auth");
|
|
43
43
|
// 0x2: ACCOUNTDISABLE
|
|
44
44
|
// 0x10: LOCKOUT
|
|
45
45
|
// 0x800000: PASSWORD_EXPIRED
|
|
46
46
|
const INVALID_ACCOUNT_FLAGS = 0x800012;
|
|
47
47
|
class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
48
|
+
bindClient;
|
|
49
|
+
usersService;
|
|
50
|
+
config;
|
|
48
51
|
constructor(options, config) {
|
|
49
|
-
var _a;
|
|
50
52
|
super(options, config);
|
|
51
53
|
const { bindDn, bindPassword, userDn, provider, clientUrl } = config;
|
|
52
54
|
if (bindDn === undefined ||
|
|
53
55
|
bindPassword === undefined ||
|
|
54
56
|
!userDn ||
|
|
55
57
|
!provider ||
|
|
56
|
-
(!clientUrl && !
|
|
58
|
+
(!clientUrl && !config.client?.socketPath)) {
|
|
57
59
|
throw new exceptions_1.InvalidConfigException('Invalid provider config', { provider });
|
|
58
60
|
}
|
|
59
61
|
const clientConfig = typeof config.client === 'object' ? config.client : {};
|
|
@@ -95,7 +97,7 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
95
97
|
});
|
|
96
98
|
res.on('end', (result) => {
|
|
97
99
|
// Handle edge case where authenticated bind user cannot read their own DN
|
|
98
|
-
if (
|
|
100
|
+
if (result?.status === 0) {
|
|
99
101
|
reject(new exceptions_1.UnexpectedResponseException('Failed to find bind user record'));
|
|
100
102
|
}
|
|
101
103
|
});
|
|
@@ -104,9 +106,9 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
104
106
|
}
|
|
105
107
|
async fetchUserInfo(baseDn, filter, scope) {
|
|
106
108
|
let { firstNameAttribute, lastNameAttribute, mailAttribute } = this.config;
|
|
107
|
-
firstNameAttribute
|
|
108
|
-
lastNameAttribute
|
|
109
|
-
mailAttribute
|
|
109
|
+
firstNameAttribute ??= 'givenName';
|
|
110
|
+
lastNameAttribute ??= 'sn';
|
|
111
|
+
mailAttribute ??= 'mail';
|
|
110
112
|
return new Promise((resolve, reject) => {
|
|
111
113
|
// Search for the user in LDAP by filter
|
|
112
114
|
this.bindClient.search(baseDn, {
|
|
@@ -119,15 +121,22 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
119
121
|
return;
|
|
120
122
|
}
|
|
121
123
|
res.on('searchEntry', ({ object }) => {
|
|
122
|
-
var _a;
|
|
123
124
|
const user = {
|
|
124
125
|
dn: object.dn,
|
|
125
|
-
|
|
126
|
-
firstName: getEntryValue(object[firstNameAttribute]),
|
|
127
|
-
lastName: getEntryValue(object[lastNameAttribute]),
|
|
128
|
-
email: getEntryValue(object[mailAttribute]),
|
|
129
|
-
userAccountControl: Number((_a = getEntryValue(object.userAccountControl)) !== null && _a !== void 0 ? _a : 0),
|
|
126
|
+
userAccountControl: Number(getEntryValue(object.userAccountControl) ?? 0),
|
|
130
127
|
};
|
|
128
|
+
const firstName = getEntryValue(object[firstNameAttribute]);
|
|
129
|
+
if (firstName)
|
|
130
|
+
user.firstName = firstName;
|
|
131
|
+
const lastName = getEntryValue(object[lastNameAttribute]);
|
|
132
|
+
if (lastName)
|
|
133
|
+
user.lastName = lastName;
|
|
134
|
+
const email = getEntryValue(object[mailAttribute]);
|
|
135
|
+
if (email)
|
|
136
|
+
user.email = email;
|
|
137
|
+
const uid = getEntryValue(object.uid);
|
|
138
|
+
if (uid)
|
|
139
|
+
user.uid = uid;
|
|
131
140
|
resolve(user);
|
|
132
141
|
});
|
|
133
142
|
res.on('error', (err) => {
|
|
@@ -175,28 +184,27 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
175
184
|
.from('directus_users')
|
|
176
185
|
.orWhereRaw('LOWER(??) = ?', ['external_identifier', userDn.toLowerCase()])
|
|
177
186
|
.first();
|
|
178
|
-
return user
|
|
187
|
+
return user?.id;
|
|
179
188
|
}
|
|
180
189
|
async getUserID(payload) {
|
|
181
|
-
var _a, _b, _c;
|
|
182
190
|
if (!payload.identifier) {
|
|
183
191
|
throw new exceptions_1.InvalidCredentialsException();
|
|
184
192
|
}
|
|
185
193
|
await this.validateBindClient();
|
|
186
194
|
const { userDn, userScope, userAttribute, groupDn, groupScope, groupAttribute, defaultRoleId } = this.config;
|
|
187
195
|
const userInfo = await this.fetchUserInfo(userDn, new ldapjs_1.EqualityFilter({
|
|
188
|
-
attribute: userAttribute
|
|
196
|
+
attribute: userAttribute ?? 'cn',
|
|
189
197
|
value: payload.identifier,
|
|
190
|
-
}), userScope
|
|
191
|
-
if (!
|
|
198
|
+
}), userScope ?? 'one');
|
|
199
|
+
if (!userInfo?.dn) {
|
|
192
200
|
throw new exceptions_1.InvalidCredentialsException();
|
|
193
201
|
}
|
|
194
202
|
let userRole;
|
|
195
203
|
if (groupDn) {
|
|
196
204
|
const userGroups = await this.fetchUserGroups(groupDn, new ldapjs_1.EqualityFilter({
|
|
197
|
-
attribute: groupAttribute
|
|
198
|
-
value:
|
|
199
|
-
}), groupScope
|
|
205
|
+
attribute: groupAttribute ?? 'member',
|
|
206
|
+
value: groupAttribute?.toLowerCase() === 'memberuid' && userInfo.uid ? userInfo.uid : userInfo.dn,
|
|
207
|
+
}), groupScope ?? 'one');
|
|
200
208
|
if (userGroups.length) {
|
|
201
209
|
userRole = await this.knex
|
|
202
210
|
.select('id')
|
|
@@ -212,7 +220,7 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
212
220
|
if (userId) {
|
|
213
221
|
// Only sync roles if the AD groups are configured
|
|
214
222
|
if (groupDn) {
|
|
215
|
-
await this.usersService.updateOne(userId, { role:
|
|
223
|
+
await this.usersService.updateOne(userId, { role: userRole?.id ?? defaultRoleId ?? null });
|
|
216
224
|
}
|
|
217
225
|
return userId;
|
|
218
226
|
}
|
|
@@ -226,7 +234,7 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
226
234
|
last_name: userInfo.lastName,
|
|
227
235
|
email: userInfo.email,
|
|
228
236
|
external_identifier: userInfo.dn,
|
|
229
|
-
role:
|
|
237
|
+
role: userRole?.id ?? defaultRoleId,
|
|
230
238
|
});
|
|
231
239
|
}
|
|
232
240
|
catch (e) {
|
|
@@ -269,7 +277,7 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
269
277
|
async refresh(user) {
|
|
270
278
|
await this.validateBindClient();
|
|
271
279
|
const userInfo = await this.fetchUserInfo(user.external_identifier);
|
|
272
|
-
if (
|
|
280
|
+
if (userInfo?.userAccountControl && userInfo.userAccountControl & INVALID_ACCOUNT_FLAGS) {
|
|
273
281
|
throw new exceptions_1.InvalidCredentialsException();
|
|
274
282
|
}
|
|
275
283
|
}
|
|
@@ -298,13 +306,16 @@ function createLDAPAuthRouter(provider) {
|
|
|
298
306
|
otp: joi_1.default.string(),
|
|
299
307
|
}).unknown();
|
|
300
308
|
router.post('/', (0, async_handler_1.default)(async (req, res, next) => {
|
|
301
|
-
var _a, _b;
|
|
302
309
|
const accountability = {
|
|
303
310
|
ip: (0, get_ip_from_req_1.getIPFromReq)(req),
|
|
304
|
-
userAgent: req.get('user-agent'),
|
|
305
|
-
origin: req.get('origin'),
|
|
306
311
|
role: null,
|
|
307
312
|
};
|
|
313
|
+
const userAgent = req.get('user-agent');
|
|
314
|
+
if (userAgent)
|
|
315
|
+
accountability.userAgent = userAgent;
|
|
316
|
+
const origin = req.get('origin');
|
|
317
|
+
if (origin)
|
|
318
|
+
accountability.origin = origin;
|
|
308
319
|
const authenticationService = new services_1.AuthenticationService({
|
|
309
320
|
accountability: accountability,
|
|
310
321
|
schema: req.schema,
|
|
@@ -314,7 +325,7 @@ function createLDAPAuthRouter(provider) {
|
|
|
314
325
|
throw new exceptions_1.InvalidPayloadException(error.message);
|
|
315
326
|
}
|
|
316
327
|
const mode = req.body.mode || 'json';
|
|
317
|
-
const { accessToken, refreshToken, expires } = await authenticationService.login(provider, req.body,
|
|
328
|
+
const { accessToken, refreshToken, expires } = await authenticationService.login(provider, req.body, req.body?.otp);
|
|
318
329
|
const payload = {
|
|
319
330
|
data: { access_token: accessToken, expires },
|
|
320
331
|
};
|
|
@@ -325,8 +336,8 @@ function createLDAPAuthRouter(provider) {
|
|
|
325
336
|
res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
|
|
326
337
|
httpOnly: true,
|
|
327
338
|
domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
|
|
328
|
-
maxAge: (0,
|
|
329
|
-
secure:
|
|
339
|
+
maxAge: (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL),
|
|
340
|
+
secure: env_1.default.REFRESH_TOKEN_COOKIE_SECURE ?? false,
|
|
330
341
|
sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
|
|
331
342
|
});
|
|
332
343
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
+
import type { User } from '../../types';
|
|
2
3
|
import { AuthDriver } from '../auth';
|
|
3
|
-
import { User } from '../../types';
|
|
4
4
|
export declare class LocalAuthDriver extends AuthDriver {
|
|
5
5
|
getUserID(payload: Record<string, any>): Promise<string>;
|
|
6
6
|
verify(user: User, password?: string): Promise<void>;
|
|
@@ -4,19 +4,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createLocalAuthRouter = exports.LocalAuthDriver = void 0;
|
|
7
|
-
const express_1 = require("express");
|
|
8
7
|
const argon2_1 = __importDefault(require("argon2"));
|
|
8
|
+
const express_1 = require("express");
|
|
9
9
|
const joi_1 = __importDefault(require("joi"));
|
|
10
|
-
const
|
|
10
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
11
|
+
const constants_1 = require("../../constants");
|
|
12
|
+
const env_1 = __importDefault(require("../../env"));
|
|
11
13
|
const exceptions_1 = require("../../exceptions");
|
|
14
|
+
const respond_1 = require("../../middleware/respond");
|
|
12
15
|
const services_1 = require("../../services");
|
|
13
16
|
const async_handler_1 = __importDefault(require("../../utils/async-handler"));
|
|
14
|
-
const env_1 = __importDefault(require("../../env"));
|
|
15
|
-
const respond_1 = require("../../middleware/respond");
|
|
16
|
-
const constants_1 = require("../../constants");
|
|
17
17
|
const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
|
|
18
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
19
18
|
const stall_1 = require("../../utils/stall");
|
|
19
|
+
const auth_1 = require("../auth");
|
|
20
20
|
class LocalAuthDriver extends auth_1.AuthDriver {
|
|
21
21
|
async getUserID(payload) {
|
|
22
22
|
if (!payload.email) {
|
|
@@ -51,15 +51,18 @@ function createLocalAuthRouter(provider) {
|
|
|
51
51
|
otp: joi_1.default.string(),
|
|
52
52
|
}).unknown();
|
|
53
53
|
router.post('/', (0, async_handler_1.default)(async (req, res, next) => {
|
|
54
|
-
var _a;
|
|
55
54
|
const STALL_TIME = env_1.default.LOGIN_STALL_TIME;
|
|
56
55
|
const timeStart = perf_hooks_1.performance.now();
|
|
57
56
|
const accountability = {
|
|
58
57
|
ip: (0, get_ip_from_req_1.getIPFromReq)(req),
|
|
59
|
-
userAgent: req.get('user-agent'),
|
|
60
|
-
origin: req.get('origin'),
|
|
61
58
|
role: null,
|
|
62
59
|
};
|
|
60
|
+
const userAgent = req.get('user-agent');
|
|
61
|
+
if (userAgent)
|
|
62
|
+
accountability.userAgent = userAgent;
|
|
63
|
+
const origin = req.get('origin');
|
|
64
|
+
if (origin)
|
|
65
|
+
accountability.origin = origin;
|
|
63
66
|
const authenticationService = new services_1.AuthenticationService({
|
|
64
67
|
accountability: accountability,
|
|
65
68
|
schema: req.schema,
|
|
@@ -70,7 +73,7 @@ function createLocalAuthRouter(provider) {
|
|
|
70
73
|
throw new exceptions_1.InvalidPayloadException(error.message);
|
|
71
74
|
}
|
|
72
75
|
const mode = req.body.mode || 'json';
|
|
73
|
-
const { accessToken, refreshToken, expires } = await authenticationService.login(provider, req.body,
|
|
76
|
+
const { accessToken, refreshToken, expires } = await authenticationService.login(provider, req.body, req.body?.otp);
|
|
74
77
|
const payload = {
|
|
75
78
|
data: { access_token: accessToken, expires },
|
|
76
79
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { Client } from 'openid-client';
|
|
3
3
|
import { UsersService } from '../../services';
|
|
4
|
-
import { AuthDriverOptions, User } from '../../types';
|
|
4
|
+
import type { AuthDriverOptions, User } from '../../types';
|
|
5
5
|
import { LocalAuthDriver } from './local';
|
|
6
6
|
export declare class OAuth2AuthDriver extends LocalAuthDriver {
|
|
7
7
|
client: Client;
|
|
@@ -32,7 +32,6 @@ const utils_1 = require("@directus/shared/utils");
|
|
|
32
32
|
const express_1 = __importStar(require("express"));
|
|
33
33
|
const flat_1 = __importDefault(require("flat"));
|
|
34
34
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
35
|
-
const ms_1 = __importDefault(require("ms"));
|
|
36
35
|
const openid_client_1 = require("openid-client");
|
|
37
36
|
const auth_1 = require("../../auth");
|
|
38
37
|
const env_1 = __importDefault(require("../../env"));
|
|
@@ -44,9 +43,14 @@ const services_1 = require("../../services");
|
|
|
44
43
|
const async_handler_1 = __importDefault(require("../../utils/async-handler"));
|
|
45
44
|
const get_config_from_env_1 = require("../../utils/get-config-from-env");
|
|
46
45
|
const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
|
|
46
|
+
const get_milliseconds_1 = require("../../utils/get-milliseconds");
|
|
47
47
|
const url_1 = require("../../utils/url");
|
|
48
48
|
const local_1 = require("./local");
|
|
49
49
|
class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
50
|
+
client;
|
|
51
|
+
redirectUrl;
|
|
52
|
+
usersService;
|
|
53
|
+
config;
|
|
50
54
|
constructor(options, config) {
|
|
51
55
|
super(options, config);
|
|
52
56
|
const { authorizeUrl, accessUrl, profileUrl, clientId, clientSecret, ...additionalConfig } = config;
|
|
@@ -76,12 +80,11 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
76
80
|
return openid_client_1.generators.codeVerifier();
|
|
77
81
|
}
|
|
78
82
|
generateAuthUrl(codeVerifier, prompt = false) {
|
|
79
|
-
var _a;
|
|
80
83
|
try {
|
|
81
84
|
const codeChallenge = openid_client_1.generators.codeChallenge(codeVerifier);
|
|
82
85
|
const paramsConfig = typeof this.config.params === 'object' ? this.config.params : {};
|
|
83
86
|
return this.client.authorizationUrl({
|
|
84
|
-
scope:
|
|
87
|
+
scope: this.config.scope ?? 'email',
|
|
85
88
|
access_type: 'offline',
|
|
86
89
|
prompt: prompt ? 'consent' : undefined,
|
|
87
90
|
...paramsConfig,
|
|
@@ -101,7 +104,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
101
104
|
.from('directus_users')
|
|
102
105
|
.whereRaw('LOWER(??) = ?', ['external_identifier', identifier.toLowerCase()])
|
|
103
106
|
.first();
|
|
104
|
-
return user
|
|
107
|
+
return user?.id;
|
|
105
108
|
}
|
|
106
109
|
async getUserID(payload) {
|
|
107
110
|
if (!payload.code || !payload.codeVerifier || !payload.state) {
|
|
@@ -120,7 +123,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
120
123
|
// Flatten response to support dot indexes
|
|
121
124
|
userInfo = (0, flat_1.default)(userInfo);
|
|
122
125
|
const { provider, emailKey, identifierKey, allowPublicRegistration } = this.config;
|
|
123
|
-
const email = userInfo[emailKey
|
|
126
|
+
const email = userInfo[emailKey ?? 'email'] ? String(userInfo[emailKey ?? 'email']) : undefined;
|
|
124
127
|
// Fallback to email if explicit identifier not found
|
|
125
128
|
const identifier = userInfo[identifierKey] ? String(userInfo[identifierKey]) : email;
|
|
126
129
|
if (!identifier) {
|
|
@@ -175,7 +178,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
175
178
|
logger_1.default.warn(`[OAuth2] Session data isn't valid JSON: ${authData}`);
|
|
176
179
|
}
|
|
177
180
|
}
|
|
178
|
-
if (authData
|
|
181
|
+
if (authData?.refreshToken) {
|
|
179
182
|
try {
|
|
180
183
|
const tokenSet = await this.client.refresh(authData.refreshToken);
|
|
181
184
|
// Update user refreshToken if provided
|
|
@@ -234,7 +237,6 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
234
237
|
res.redirect(303, `./callback?${new URLSearchParams(req.body)}`);
|
|
235
238
|
}, respond_1.respond);
|
|
236
239
|
router.get('/callback', (0, async_handler_1.default)(async (req, res, next) => {
|
|
237
|
-
var _a;
|
|
238
240
|
let tokenData;
|
|
239
241
|
try {
|
|
240
242
|
tokenData = jsonwebtoken_1.default.verify(req.cookies[`oauth2.${providerName}`], env_1.default.SECRET, { issuer: 'directus' });
|
|
@@ -244,13 +246,18 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
244
246
|
throw new exceptions_2.InvalidCredentialsException();
|
|
245
247
|
}
|
|
246
248
|
const { verifier, redirect, prompt } = tokenData;
|
|
249
|
+
const accountability = {
|
|
250
|
+
ip: (0, get_ip_from_req_1.getIPFromReq)(req),
|
|
251
|
+
role: null,
|
|
252
|
+
};
|
|
253
|
+
const userAgent = req.get('user-agent');
|
|
254
|
+
if (userAgent)
|
|
255
|
+
accountability.userAgent = userAgent;
|
|
256
|
+
const origin = req.get('origin');
|
|
257
|
+
if (origin)
|
|
258
|
+
accountability.origin = origin;
|
|
247
259
|
const authenticationService = new services_1.AuthenticationService({
|
|
248
|
-
accountability
|
|
249
|
-
ip: (0, get_ip_from_req_1.getIPFromReq)(req),
|
|
250
|
-
userAgent: req.get('user-agent'),
|
|
251
|
-
origin: req.get('origin'),
|
|
252
|
-
role: null,
|
|
253
|
-
},
|
|
260
|
+
accountability,
|
|
254
261
|
schema: req.schema,
|
|
255
262
|
});
|
|
256
263
|
let authResponse;
|
|
@@ -285,8 +292,8 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
285
292
|
res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
|
|
286
293
|
httpOnly: true,
|
|
287
294
|
domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
|
|
288
|
-
maxAge: (0,
|
|
289
|
-
secure:
|
|
295
|
+
maxAge: (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL),
|
|
296
|
+
secure: env_1.default.REFRESH_TOKEN_COOKIE_SECURE ?? false,
|
|
290
297
|
sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
|
|
291
298
|
});
|
|
292
299
|
return res.redirect(redirect);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { Client } from 'openid-client';
|
|
3
3
|
import { UsersService } from '../../services';
|
|
4
|
-
import { AuthDriverOptions, User } from '../../types';
|
|
4
|
+
import type { AuthDriverOptions, User } from '../../types';
|
|
5
5
|
import { LocalAuthDriver } from './local';
|
|
6
6
|
export declare class OpenIDAuthDriver extends LocalAuthDriver {
|
|
7
7
|
client: Promise<Client>;
|
|
@@ -32,7 +32,6 @@ const utils_1 = require("@directus/shared/utils");
|
|
|
32
32
|
const express_1 = __importStar(require("express"));
|
|
33
33
|
const flat_1 = __importDefault(require("flat"));
|
|
34
34
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
35
|
-
const ms_1 = __importDefault(require("ms"));
|
|
36
35
|
const openid_client_1 = require("openid-client");
|
|
37
36
|
const auth_1 = require("../../auth");
|
|
38
37
|
const env_1 = __importDefault(require("../../env"));
|
|
@@ -44,9 +43,14 @@ const services_1 = require("../../services");
|
|
|
44
43
|
const async_handler_1 = __importDefault(require("../../utils/async-handler"));
|
|
45
44
|
const get_config_from_env_1 = require("../../utils/get-config-from-env");
|
|
46
45
|
const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
|
|
46
|
+
const get_milliseconds_1 = require("../../utils/get-milliseconds");
|
|
47
47
|
const url_1 = require("../../utils/url");
|
|
48
48
|
const local_1 = require("./local");
|
|
49
49
|
class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
50
|
+
client;
|
|
51
|
+
redirectUrl;
|
|
52
|
+
usersService;
|
|
53
|
+
config;
|
|
50
54
|
constructor(options, config) {
|
|
51
55
|
super(options, config);
|
|
52
56
|
const { issuerUrl, clientId, clientSecret, ...additionalConfig } = config;
|
|
@@ -62,7 +66,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
62
66
|
openid_client_1.Issuer.discover(issuerUrl)
|
|
63
67
|
.then((issuer) => {
|
|
64
68
|
const supportedTypes = issuer.metadata.response_types_supported;
|
|
65
|
-
if (!
|
|
69
|
+
if (!supportedTypes?.includes('code')) {
|
|
66
70
|
reject(new exceptions_2.InvalidConfigException('OpenID provider does not support required code flow', {
|
|
67
71
|
provider: additionalConfig.provider,
|
|
68
72
|
}));
|
|
@@ -85,13 +89,12 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
85
89
|
return openid_client_1.generators.codeVerifier();
|
|
86
90
|
}
|
|
87
91
|
async generateAuthUrl(codeVerifier, prompt = false) {
|
|
88
|
-
var _a;
|
|
89
92
|
try {
|
|
90
93
|
const client = await this.client;
|
|
91
94
|
const codeChallenge = openid_client_1.generators.codeChallenge(codeVerifier);
|
|
92
95
|
const paramsConfig = typeof this.config.params === 'object' ? this.config.params : {};
|
|
93
96
|
return client.authorizationUrl({
|
|
94
|
-
scope:
|
|
97
|
+
scope: this.config.scope ?? 'openid profile email',
|
|
95
98
|
access_type: 'offline',
|
|
96
99
|
prompt: prompt ? 'consent' : undefined,
|
|
97
100
|
...paramsConfig,
|
|
@@ -112,7 +115,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
112
115
|
.from('directus_users')
|
|
113
116
|
.whereRaw('LOWER(??) = ?', ['external_identifier', identifier.toLowerCase()])
|
|
114
117
|
.first();
|
|
115
|
-
return user
|
|
118
|
+
return user?.id;
|
|
116
119
|
}
|
|
117
120
|
async getUserID(payload) {
|
|
118
121
|
if (!payload.code || !payload.codeVerifier || !payload.state) {
|
|
@@ -141,7 +144,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
141
144
|
const { provider, identifierKey, allowPublicRegistration, requireVerifiedEmail } = this.config;
|
|
142
145
|
const email = userInfo.email ? String(userInfo.email) : undefined;
|
|
143
146
|
// Fallback to email if explicit identifier not found
|
|
144
|
-
const identifier = userInfo[identifierKey
|
|
147
|
+
const identifier = userInfo[identifierKey ?? 'sub'] ? String(userInfo[identifierKey ?? 'sub']) : email;
|
|
145
148
|
if (!identifier) {
|
|
146
149
|
logger_1.default.warn(`[OpenID] Failed to find user identifier for provider "${provider}"`);
|
|
147
150
|
throw new exceptions_2.InvalidCredentialsException();
|
|
@@ -195,7 +198,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
195
198
|
logger_1.default.warn(`[OpenID] Session data isn't valid JSON: ${authData}`);
|
|
196
199
|
}
|
|
197
200
|
}
|
|
198
|
-
if (authData
|
|
201
|
+
if (authData?.refreshToken) {
|
|
199
202
|
try {
|
|
200
203
|
const client = await this.client;
|
|
201
204
|
const tokenSet = await client.refresh(authData.refreshToken);
|
|
@@ -255,7 +258,6 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
255
258
|
res.redirect(303, `./callback?${new URLSearchParams(req.body)}`);
|
|
256
259
|
}, respond_1.respond);
|
|
257
260
|
router.get('/callback', (0, async_handler_1.default)(async (req, res, next) => {
|
|
258
|
-
var _a;
|
|
259
261
|
let tokenData;
|
|
260
262
|
try {
|
|
261
263
|
tokenData = jsonwebtoken_1.default.verify(req.cookies[`openid.${providerName}`], env_1.default.SECRET, { issuer: 'directus' });
|
|
@@ -265,13 +267,18 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
265
267
|
throw new exceptions_2.InvalidCredentialsException();
|
|
266
268
|
}
|
|
267
269
|
const { verifier, redirect, prompt } = tokenData;
|
|
270
|
+
const accountability = {
|
|
271
|
+
ip: (0, get_ip_from_req_1.getIPFromReq)(req),
|
|
272
|
+
role: null,
|
|
273
|
+
};
|
|
274
|
+
const userAgent = req.get('user-agent');
|
|
275
|
+
if (userAgent)
|
|
276
|
+
accountability.userAgent = userAgent;
|
|
277
|
+
const origin = req.get('origin');
|
|
278
|
+
if (origin)
|
|
279
|
+
accountability.origin = origin;
|
|
268
280
|
const authenticationService = new services_1.AuthenticationService({
|
|
269
|
-
accountability
|
|
270
|
-
ip: (0, get_ip_from_req_1.getIPFromReq)(req),
|
|
271
|
-
userAgent: req.get('user-agent'),
|
|
272
|
-
origin: req.get('origin'),
|
|
273
|
-
role: null,
|
|
274
|
-
},
|
|
281
|
+
accountability,
|
|
275
282
|
schema: req.schema,
|
|
276
283
|
});
|
|
277
284
|
let authResponse;
|
|
@@ -307,8 +314,8 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
307
314
|
res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
|
|
308
315
|
httpOnly: true,
|
|
309
316
|
domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
|
|
310
|
-
maxAge: (0,
|
|
311
|
-
secure:
|
|
317
|
+
maxAge: (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL),
|
|
318
|
+
secure: env_1.default.REFRESH_TOKEN_COOKIE_SECURE ?? false,
|
|
312
319
|
sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
|
|
313
320
|
});
|
|
314
321
|
return res.redirect(redirect);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UsersService } from '../../services';
|
|
2
|
-
import { AuthDriverOptions, User } from '../../types';
|
|
2
|
+
import type { AuthDriverOptions, User } from '../../types';
|
|
3
3
|
import { LocalAuthDriver } from './local';
|
|
4
4
|
export declare class SAMLAuthDriver extends LocalAuthDriver {
|
|
5
5
|
idp: any;
|