zibri 2.4.0 → 2.4.1
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/cjs/application.d.ts.map +1 -1
- package/dist/cjs/application.js +8 -2
- package/dist/cjs/application.js.map +1 -1
- package/dist/cjs/auth/encryption/encryption-key.model.d.ts +5 -1
- package/dist/cjs/auth/encryption/encryption-key.model.d.ts.map +1 -1
- package/dist/cjs/auth/encryption/encryption-key.model.js +9 -1
- package/dist/cjs/auth/encryption/encryption-key.model.js.map +1 -1
- package/dist/cjs/auth/strategies/cookie/cookie-auth.auth-strategy.d.ts.map +1 -1
- package/dist/cjs/auth/strategies/cookie/cookie-auth.auth-strategy.js.map +1 -1
- package/dist/cjs/auth/strategies/jwt/jwt-credentials.model.d.ts +5 -1
- package/dist/cjs/auth/strategies/jwt/jwt-credentials.model.d.ts.map +1 -1
- package/dist/cjs/auth/strategies/jwt/jwt-credentials.model.js +9 -1
- package/dist/cjs/auth/strategies/jwt/jwt-credentials.model.js.map +1 -1
- package/dist/cjs/auth/strategies/jwt/jwt.auth-strategy.d.ts.map +1 -1
- package/dist/cjs/auth/strategies/jwt/jwt.auth-strategy.js +2 -1
- package/dist/cjs/auth/strategies/jwt/jwt.auth-strategy.js.map +1 -1
- package/dist/cjs/backup/backup-resource-entity.model.d.ts +5 -1
- package/dist/cjs/backup/backup-resource-entity.model.d.ts.map +1 -1
- package/dist/cjs/backup/backup-resource-entity.model.js +9 -1
- package/dist/cjs/backup/backup-resource-entity.model.js.map +1 -1
- package/dist/cjs/backup/backup.service.js +2 -2
- package/dist/cjs/backup/backup.service.js.map +1 -1
- package/dist/cjs/caching/cache/base-cache.model.js.map +1 -1
- package/dist/cjs/caching/cache/multi-tier.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-aside/read-aside.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-aside/write-around-read-aside.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-aside/write-behind-read-aside.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-aside/write-invalidate-read-aside-args-only.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-aside/write-invalidate-read-aside-with-result.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-aside/write-through-read-aside.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-through/read-through.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-through/write-around-read-through.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-through/write-behind-read-through.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-through/write-invalidate-read-through-args-only.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-through/write-invalidate-read-through-with-result.cache.js.map +1 -1
- package/dist/cjs/caching/cache/read-through/write-through-read-through.cache.js.map +1 -1
- package/dist/cjs/change-sets/change-set-repository.d.ts +5 -3
- package/dist/cjs/change-sets/change-set-repository.d.ts.map +1 -1
- package/dist/cjs/change-sets/change-set-repository.js +16 -16
- package/dist/cjs/change-sets/change-set-repository.js.map +1 -1
- package/dist/cjs/change-sets/models/change-set-entity.model.d.ts +2 -2
- package/dist/cjs/change-sets/models/change-set-entity.model.d.ts.map +1 -1
- package/dist/cjs/change-sets/models/change-set-entity.model.js +29 -1
- package/dist/cjs/change-sets/models/change-set-entity.model.js.map +1 -1
- package/dist/cjs/change-sets/models/change-set.model.js +1 -1
- package/dist/cjs/change-sets/models/change-set.model.js.map +1 -1
- package/dist/cjs/change-sets/models/change.model.d.ts +5 -1
- package/dist/cjs/change-sets/models/change.model.d.ts.map +1 -1
- package/dist/cjs/change-sets/models/change.model.js +9 -1
- package/dist/cjs/change-sets/models/change.model.js.map +1 -1
- package/dist/cjs/change-sets/models/soft-delete-entity.model.d.ts +2 -2
- package/dist/cjs/change-sets/models/soft-delete-entity.model.d.ts.map +1 -1
- package/dist/cjs/change-sets/models/soft-delete-entity.model.js +26 -0
- package/dist/cjs/change-sets/models/soft-delete-entity.model.js.map +1 -1
- package/dist/cjs/change-sets/soft-delete-repository.d.ts +6 -5
- package/dist/cjs/change-sets/soft-delete-repository.d.ts.map +1 -1
- package/dist/cjs/change-sets/soft-delete-repository.js +22 -6
- package/dist/cjs/change-sets/soft-delete-repository.js.map +1 -1
- package/dist/cjs/context/als.utilities.d.ts +3 -3
- package/dist/cjs/context/als.utilities.d.ts.map +1 -1
- package/dist/cjs/context/als.utilities.js.map +1 -1
- package/dist/cjs/context/cache/cache.context.d.ts +27 -0
- package/dist/cjs/context/cache/cache.context.d.ts.map +1 -0
- package/dist/cjs/context/cache/cache.context.js +61 -0
- package/dist/cjs/context/cache/cache.context.js.map +1 -0
- package/dist/cjs/data-source/data-sources/data-source-initialization.error.d.ts +7 -0
- package/dist/cjs/data-source/data-sources/data-source-initialization.error.d.ts.map +1 -0
- package/dist/cjs/data-source/data-sources/data-source-initialization.error.js +14 -0
- package/dist/cjs/data-source/data-sources/data-source-initialization.error.js.map +1 -0
- package/dist/cjs/data-source/data-sources/data-source.interface.d.ts +9 -1
- package/dist/cjs/data-source/data-sources/data-source.interface.d.ts.map +1 -1
- package/dist/cjs/data-source/data-sources/data-source.interface.js.map +1 -1
- package/dist/cjs/data-source/data-sources/postgres-typeorm-data-source.model.d.ts +44 -0
- package/dist/cjs/data-source/data-sources/postgres-typeorm-data-source.model.d.ts.map +1 -0
- package/dist/cjs/data-source/data-sources/postgres-typeorm-data-source.model.js +289 -0
- package/dist/cjs/data-source/data-sources/postgres-typeorm-data-source.model.js.map +1 -0
- package/dist/cjs/data-source/data-sources/sql-data-source.interface.d.ts +32 -0
- package/dist/cjs/data-source/data-sources/sql-data-source.interface.d.ts.map +1 -0
- package/dist/cjs/{entity/models/one-to-one-property-metadata.model.js → data-source/data-sources/sql-data-source.interface.js} +1 -1
- package/dist/cjs/data-source/data-sources/sql-data-source.interface.js.map +1 -0
- package/dist/cjs/data-source/data-sources/typeorm-base-data-source.model.d.ts +156 -0
- package/dist/cjs/data-source/data-sources/typeorm-base-data-source.model.d.ts.map +1 -0
- package/dist/cjs/data-source/data-sources/typeorm-base-data-source.model.js +378 -0
- package/dist/cjs/data-source/data-sources/typeorm-base-data-source.model.js.map +1 -0
- package/dist/cjs/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.d.ts +25 -0
- package/dist/cjs/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.d.ts.map +1 -0
- package/dist/cjs/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.js +353 -0
- package/dist/cjs/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.js.map +1 -0
- package/dist/cjs/data-source/data-sources/where-converter/typeorm-where-filter.converter.d.ts +70 -0
- package/dist/cjs/data-source/data-sources/where-converter/typeorm-where-filter.converter.d.ts.map +1 -0
- package/dist/cjs/data-source/data-sources/where-converter/typeorm-where-filter.converter.js +248 -0
- package/dist/cjs/data-source/data-sources/where-converter/typeorm-where-filter.converter.js.map +1 -0
- package/dist/cjs/data-source/models/options/count-options.model.d.ts +2 -7
- package/dist/cjs/data-source/models/options/count-options.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/options/delete-all-options.model.d.ts +2 -4
- package/dist/cjs/data-source/models/options/delete-all-options.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/options/find-all-options.model.d.ts +2 -2
- package/dist/cjs/data-source/models/options/find-all-options.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/options/find-by-id-options.model.d.ts +1 -6
- package/dist/cjs/data-source/models/options/find-by-id-options.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/options/find-one-options.model.d.ts +2 -11
- package/dist/cjs/data-source/models/options/find-one-options.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/options/update-all-options.model.d.ts +1 -7
- package/dist/cjs/data-source/models/options/update-all-options.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/options/update-by-id-options.model.d.ts +1 -7
- package/dist/cjs/data-source/models/options/update-by-id-options.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/where/array-where-filter.model.d.ts +142 -3
- package/dist/cjs/data-source/models/where/array-where-filter.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/where/base-where-filter.model.d.ts +18 -1
- package/dist/cjs/data-source/models/where/base-where-filter.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/where/boolean-where-filter.model.d.ts +4 -2
- package/dist/cjs/data-source/models/where/boolean-where-filter.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/where/date-where-filter.model.d.ts +8 -15
- package/dist/cjs/data-source/models/where/date-where-filter.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/where/number-where-filter.model.d.ts +8 -15
- package/dist/cjs/data-source/models/where/number-where-filter.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/where/object-where-filter.model.d.ts +52 -7
- package/dist/cjs/data-source/models/where/object-where-filter.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/where/string-where-filter.model.d.ts +8 -15
- package/dist/cjs/data-source/models/where/string-where-filter.model.d.ts.map +1 -1
- package/dist/cjs/data-source/models/where/where-filter-keys.model.d.ts +46 -0
- package/dist/cjs/data-source/models/where/where-filter-keys.model.d.ts.map +1 -0
- package/dist/cjs/data-source/models/where/where-filter-keys.model.js +36 -0
- package/dist/cjs/data-source/models/where/where-filter-keys.model.js.map +1 -0
- package/dist/cjs/data-source/models/where/where-filter.model.d.ts +2 -2
- package/dist/cjs/data-source/models/where/where-filter.model.d.ts.map +1 -1
- package/dist/cjs/data-source/query-failed.error.js +27 -1
- package/dist/cjs/data-source/query-failed.error.js.map +1 -1
- package/dist/cjs/data-source/repository.d.ts +8 -3
- package/dist/cjs/data-source/repository.d.ts.map +1 -1
- package/dist/cjs/data-source/repository.js +42 -16
- package/dist/cjs/data-source/repository.js.map +1 -1
- package/dist/cjs/di/decorators/inject-repository.decorator.d.ts +2 -2
- package/dist/cjs/di/decorators/inject-repository.decorator.d.ts.map +1 -1
- package/dist/cjs/di/decorators/inject-repository.decorator.js.map +1 -1
- package/dist/cjs/di/default/zibri-di-tokens.default.d.ts +2 -2
- package/dist/cjs/di/default/zibri-di-tokens.default.d.ts.map +1 -1
- package/dist/cjs/di/default/zibri-di-tokens.default.js.map +1 -1
- package/dist/cjs/email/email.service.d.ts +2 -2
- package/dist/cjs/email/email.service.d.ts.map +1 -1
- package/dist/cjs/email/email.service.js +4 -6
- package/dist/cjs/email/email.service.js.map +1 -1
- package/dist/cjs/email/models/email.model.js +1 -1
- package/dist/cjs/email/models/email.model.js.map +1 -1
- package/dist/cjs/entity/decorators/entity.decorator.d.ts +28 -1
- package/dist/cjs/entity/decorators/entity.decorator.d.ts.map +1 -1
- package/dist/cjs/entity/decorators/entity.decorator.js +6 -3
- package/dist/cjs/entity/decorators/entity.decorator.js.map +1 -1
- package/dist/cjs/entity/decorators/property.decorator.d.ts +5 -8
- package/dist/cjs/entity/decorators/property.decorator.d.ts.map +1 -1
- package/dist/cjs/entity/decorators/property.decorator.js +34 -20
- package/dist/cjs/entity/decorators/property.decorator.js.map +1 -1
- package/dist/cjs/entity/entity-metadata-missing.error.d.ts +9 -0
- package/dist/cjs/entity/entity-metadata-missing.error.d.ts.map +1 -0
- package/dist/cjs/entity/entity-metadata-missing.error.js +17 -0
- package/dist/cjs/entity/entity-metadata-missing.error.js.map +1 -0
- package/dist/cjs/entity/models/base-relation-metadata.model.d.ts +1 -1
- package/dist/cjs/entity/models/belongs-to-one-property-metadata.model.d.ts +28 -0
- package/dist/cjs/entity/models/belongs-to-one-property-metadata.model.d.ts.map +1 -0
- package/dist/cjs/entity/models/belongs-to-one-property-metadata.model.js +3 -0
- package/dist/cjs/entity/models/belongs-to-one-property-metadata.model.js.map +1 -0
- package/dist/cjs/entity/models/has-one-property-metadata.model.d.ts +18 -0
- package/dist/cjs/entity/models/has-one-property-metadata.model.d.ts.map +1 -0
- package/dist/{esm/entity/models/one-to-one-property-metadata.model.js → cjs/entity/models/has-one-property-metadata.model.js} +1 -1
- package/dist/cjs/entity/models/has-one-property-metadata.model.js.map +1 -0
- package/dist/cjs/entity/models/many-to-many-property-metadata.model.d.ts +3 -3
- package/dist/cjs/entity/models/many-to-many-property-metadata.model.d.ts.map +1 -1
- package/dist/cjs/entity/models/many-to-one-property-metadata.model.d.ts +11 -1
- package/dist/cjs/entity/models/many-to-one-property-metadata.model.d.ts.map +1 -1
- package/dist/cjs/entity/models/relation.enum.d.ts +2 -1
- package/dist/cjs/entity/models/relation.enum.d.ts.map +1 -1
- package/dist/cjs/entity/models/relation.enum.js +2 -1
- package/dist/cjs/entity/models/relation.enum.js.map +1 -1
- package/dist/cjs/entity/partial-class.model.js +1 -1
- package/dist/cjs/entity/partial-class.model.js.map +1 -1
- package/dist/cjs/event/event-cleanup.cron-job.d.ts.map +1 -1
- package/dist/cjs/event/event-cleanup.cron-job.js +4 -6
- package/dist/cjs/event/event-cleanup.cron-job.js.map +1 -1
- package/dist/cjs/event/event-subscriber-run.model.d.ts +6 -8
- package/dist/cjs/event/event-subscriber-run.model.d.ts.map +1 -1
- package/dist/cjs/event/event-subscriber-run.model.js +10 -17
- package/dist/cjs/event/event-subscriber-run.model.js.map +1 -1
- package/dist/cjs/event/event.model.js +1 -1
- package/dist/cjs/event/event.model.js.map +1 -1
- package/dist/cjs/event/event.service.d.ts.map +1 -1
- package/dist/cjs/event/event.service.js +6 -3
- package/dist/cjs/event/event.service.js.map +1 -1
- package/dist/cjs/global/model-registry/default-descriptor.d.ts.map +1 -1
- package/dist/cjs/global/model-registry/default-descriptor.js +2 -1
- package/dist/cjs/global/model-registry/default-descriptor.js.map +1 -1
- package/dist/cjs/global/model-registry/encryption-descriptor.d.ts.map +1 -1
- package/dist/cjs/global/model-registry/encryption-descriptor.js +2 -1
- package/dist/cjs/global/model-registry/encryption-descriptor.js.map +1 -1
- package/dist/cjs/global/model-registry/exclude-descriptor.d.ts.map +1 -1
- package/dist/cjs/global/model-registry/exclude-descriptor.js +2 -1
- package/dist/cjs/global/model-registry/exclude-descriptor.js.map +1 -1
- package/dist/cjs/global/model-registry/hash-descriptor.d.ts.map +1 -1
- package/dist/cjs/global/model-registry/hash-descriptor.js +2 -1
- package/dist/cjs/global/model-registry/hash-descriptor.js.map +1 -1
- package/dist/cjs/index.d.ts +12 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +12 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/logging/log-context.model.d.ts +2 -27
- package/dist/cjs/logging/log-context.model.d.ts.map +1 -1
- package/dist/cjs/logging/log-context.model.js +3 -49
- package/dist/cjs/logging/log-context.model.js.map +1 -1
- package/dist/cjs/open-api/open-api.service.d.ts.map +1 -1
- package/dist/cjs/open-api/open-api.service.js +20 -11
- package/dist/cjs/open-api/open-api.service.js.map +1 -1
- package/dist/cjs/parsing/form-data/form-data.body-parser.d.ts.map +1 -1
- package/dist/cjs/parsing/form-data/form-data.body-parser.js +2 -1
- package/dist/cjs/parsing/form-data/form-data.body-parser.js.map +1 -1
- package/dist/cjs/parsing/functions/parse-boolean.function.d.ts.map +1 -1
- package/dist/cjs/parsing/functions/parse-boolean.function.js.map +1 -1
- package/dist/cjs/parsing/functions/parse-object.function.d.ts.map +1 -1
- package/dist/cjs/parsing/functions/parse-object.function.js +2 -1
- package/dist/cjs/parsing/functions/parse-object.function.js.map +1 -1
- package/dist/cjs/parsing/parser.d.ts.map +1 -1
- package/dist/cjs/parsing/parser.js +2 -1
- package/dist/cjs/parsing/parser.js.map +1 -1
- package/dist/cjs/routing/decorators/body.decorator.js +2 -1
- package/dist/cjs/routing/decorators/body.decorator.js.map +1 -1
- package/dist/cjs/routing/resolve-route-params.function.js +1 -1
- package/dist/cjs/routing/resolve-route-params.function.js.map +1 -1
- package/dist/cjs/routing/router.d.ts.map +1 -1
- package/dist/cjs/routing/router.js +38 -2
- package/dist/cjs/routing/router.js.map +1 -1
- package/dist/cjs/utilities/metadata-injection-keys.enum.d.ts +1 -0
- package/dist/cjs/utilities/metadata-injection-keys.enum.d.ts.map +1 -1
- package/dist/cjs/utilities/metadata-injection-keys.enum.js +1 -0
- package/dist/cjs/utilities/metadata-injection-keys.enum.js.map +1 -1
- package/dist/cjs/utilities/typeorm.utilities.d.ts +39 -0
- package/dist/cjs/utilities/typeorm.utilities.d.ts.map +1 -0
- package/dist/cjs/utilities/typeorm.utilities.js +47 -0
- package/dist/cjs/utilities/typeorm.utilities.js.map +1 -0
- package/dist/cjs/validation/validation-problem.model.d.ts.map +1 -1
- package/dist/cjs/validation/validation-problem.model.js +4 -7
- package/dist/cjs/validation/validation-problem.model.js.map +1 -1
- package/dist/cjs/validation/validation.service.d.ts.map +1 -1
- package/dist/cjs/validation/validation.service.js +6 -4
- package/dist/cjs/validation/validation.service.js.map +1 -1
- package/dist/cjs/websocket/models/websocket-message.model.js +1 -1
- package/dist/cjs/websocket/models/websocket-message.model.js.map +1 -1
- package/dist/cjs/websocket/models/websocket-request.model.d.ts +5 -11
- package/dist/cjs/websocket/models/websocket-request.model.d.ts.map +1 -1
- package/dist/cjs/websocket/models/websocket-request.model.js.map +1 -1
- package/dist/cjs/websocket/services/websocket.service.d.ts.map +1 -1
- package/dist/cjs/websocket/services/websocket.service.js +1 -2
- package/dist/cjs/websocket/services/websocket.service.js.map +1 -1
- package/dist/esm/application.js +8 -2
- package/dist/esm/application.js.map +1 -1
- package/dist/esm/auth/encryption/encryption-key.model.js +9 -1
- package/dist/esm/auth/encryption/encryption-key.model.js.map +1 -1
- package/dist/esm/auth/strategies/cookie/cookie-auth.auth-strategy.js.map +1 -1
- package/dist/esm/auth/strategies/jwt/jwt-credentials.model.js +9 -1
- package/dist/esm/auth/strategies/jwt/jwt-credentials.model.js.map +1 -1
- package/dist/esm/auth/strategies/jwt/jwt.auth-strategy.js +2 -1
- package/dist/esm/auth/strategies/jwt/jwt.auth-strategy.js.map +1 -1
- package/dist/esm/backup/backup-resource-entity.model.js +9 -1
- package/dist/esm/backup/backup-resource-entity.model.js.map +1 -1
- package/dist/esm/backup/backup.service.js +2 -2
- package/dist/esm/backup/backup.service.js.map +1 -1
- package/dist/esm/caching/cache/base-cache.model.js.map +1 -1
- package/dist/esm/caching/cache/multi-tier.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-aside/read-aside.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-aside/write-around-read-aside.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-aside/write-behind-read-aside.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-aside/write-invalidate-read-aside-args-only.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-aside/write-invalidate-read-aside-with-result.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-aside/write-through-read-aside.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-through/read-through.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-through/write-around-read-through.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-through/write-behind-read-through.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-through/write-invalidate-read-through-args-only.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-through/write-invalidate-read-through-with-result.cache.js.map +1 -1
- package/dist/esm/caching/cache/read-through/write-through-read-through.cache.js.map +1 -1
- package/dist/esm/change-sets/change-set-repository.js +16 -16
- package/dist/esm/change-sets/change-set-repository.js.map +1 -1
- package/dist/esm/change-sets/models/change-set-entity.model.js +29 -1
- package/dist/esm/change-sets/models/change-set-entity.model.js.map +1 -1
- package/dist/esm/change-sets/models/change-set.model.js +1 -1
- package/dist/esm/change-sets/models/change-set.model.js.map +1 -1
- package/dist/esm/change-sets/models/change.model.js +9 -1
- package/dist/esm/change-sets/models/change.model.js.map +1 -1
- package/dist/esm/change-sets/models/soft-delete-entity.model.js +26 -0
- package/dist/esm/change-sets/models/soft-delete-entity.model.js.map +1 -1
- package/dist/esm/change-sets/soft-delete-repository.js +22 -6
- package/dist/esm/change-sets/soft-delete-repository.js.map +1 -1
- package/dist/esm/context/als.utilities.js.map +1 -1
- package/dist/esm/context/cache/cache.context.js +61 -0
- package/dist/esm/context/cache/cache.context.js.map +1 -0
- package/dist/esm/data-source/data-sources/data-source-initialization.error.js +14 -0
- package/dist/esm/data-source/data-sources/data-source-initialization.error.js.map +1 -0
- package/dist/esm/data-source/data-sources/data-source.interface.js.map +1 -1
- package/dist/esm/data-source/data-sources/postgres-typeorm-data-source.model.js +289 -0
- package/dist/esm/data-source/data-sources/postgres-typeorm-data-source.model.js.map +1 -0
- package/dist/esm/data-source/data-sources/sql-data-source.interface.js +3 -0
- package/dist/esm/data-source/data-sources/sql-data-source.interface.js.map +1 -0
- package/dist/esm/data-source/data-sources/typeorm-base-data-source.model.js +378 -0
- package/dist/esm/data-source/data-sources/typeorm-base-data-source.model.js.map +1 -0
- package/dist/esm/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.js +353 -0
- package/dist/esm/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.js.map +1 -0
- package/dist/esm/data-source/data-sources/where-converter/typeorm-where-filter.converter.js +248 -0
- package/dist/esm/data-source/data-sources/where-converter/typeorm-where-filter.converter.js.map +1 -0
- package/dist/esm/data-source/models/where/where-filter-keys.model.js +36 -0
- package/dist/esm/data-source/models/where/where-filter-keys.model.js.map +1 -0
- package/dist/esm/data-source/query-failed.error.js +27 -1
- package/dist/esm/data-source/query-failed.error.js.map +1 -1
- package/dist/esm/data-source/repository.js +42 -16
- package/dist/esm/data-source/repository.js.map +1 -1
- package/dist/esm/di/decorators/inject-repository.decorator.js.map +1 -1
- package/dist/esm/di/default/zibri-di-tokens.default.js.map +1 -1
- package/dist/esm/email/email.service.js +4 -6
- package/dist/esm/email/email.service.js.map +1 -1
- package/dist/esm/email/models/email.model.js +1 -1
- package/dist/esm/email/models/email.model.js.map +1 -1
- package/dist/esm/entity/decorators/entity.decorator.js +6 -3
- package/dist/esm/entity/decorators/entity.decorator.js.map +1 -1
- package/dist/esm/entity/decorators/property.decorator.js +34 -20
- package/dist/esm/entity/decorators/property.decorator.js.map +1 -1
- package/dist/esm/entity/entity-metadata-missing.error.js +17 -0
- package/dist/esm/entity/entity-metadata-missing.error.js.map +1 -0
- package/dist/esm/entity/models/belongs-to-one-property-metadata.model.js +3 -0
- package/dist/esm/entity/models/belongs-to-one-property-metadata.model.js.map +1 -0
- package/dist/esm/entity/models/has-one-property-metadata.model.js +3 -0
- package/dist/esm/entity/models/has-one-property-metadata.model.js.map +1 -0
- package/dist/esm/entity/models/relation.enum.js +2 -1
- package/dist/esm/entity/models/relation.enum.js.map +1 -1
- package/dist/esm/entity/partial-class.model.js +1 -1
- package/dist/esm/entity/partial-class.model.js.map +1 -1
- package/dist/esm/event/event-cleanup.cron-job.js +4 -6
- package/dist/esm/event/event-cleanup.cron-job.js.map +1 -1
- package/dist/esm/event/event-subscriber-run.model.js +10 -17
- package/dist/esm/event/event-subscriber-run.model.js.map +1 -1
- package/dist/esm/event/event.model.js +1 -1
- package/dist/esm/event/event.model.js.map +1 -1
- package/dist/esm/event/event.service.js +6 -3
- package/dist/esm/event/event.service.js.map +1 -1
- package/dist/esm/global/model-registry/default-descriptor.js +2 -1
- package/dist/esm/global/model-registry/default-descriptor.js.map +1 -1
- package/dist/esm/global/model-registry/encryption-descriptor.js +2 -1
- package/dist/esm/global/model-registry/encryption-descriptor.js.map +1 -1
- package/dist/esm/global/model-registry/exclude-descriptor.js +2 -1
- package/dist/esm/global/model-registry/exclude-descriptor.js.map +1 -1
- package/dist/esm/global/model-registry/hash-descriptor.js +2 -1
- package/dist/esm/global/model-registry/hash-descriptor.js.map +1 -1
- package/dist/esm/index.js +12 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/logging/log-context.model.js +3 -49
- package/dist/esm/logging/log-context.model.js.map +1 -1
- package/dist/esm/open-api/open-api.service.js +20 -11
- package/dist/esm/open-api/open-api.service.js.map +1 -1
- package/dist/esm/parsing/form-data/form-data.body-parser.js +2 -1
- package/dist/esm/parsing/form-data/form-data.body-parser.js.map +1 -1
- package/dist/esm/parsing/functions/parse-boolean.function.js.map +1 -1
- package/dist/esm/parsing/functions/parse-object.function.js +2 -1
- package/dist/esm/parsing/functions/parse-object.function.js.map +1 -1
- package/dist/esm/parsing/parser.js +2 -1
- package/dist/esm/parsing/parser.js.map +1 -1
- package/dist/esm/routing/decorators/body.decorator.js +2 -1
- package/dist/esm/routing/decorators/body.decorator.js.map +1 -1
- package/dist/esm/routing/resolve-route-params.function.js +1 -1
- package/dist/esm/routing/resolve-route-params.function.js.map +1 -1
- package/dist/esm/routing/router.js +38 -2
- package/dist/esm/routing/router.js.map +1 -1
- package/dist/esm/utilities/metadata-injection-keys.enum.js +1 -0
- package/dist/esm/utilities/metadata-injection-keys.enum.js.map +1 -1
- package/dist/esm/utilities/typeorm.utilities.js +47 -0
- package/dist/esm/utilities/typeorm.utilities.js.map +1 -0
- package/dist/esm/validation/validation-problem.model.js +4 -7
- package/dist/esm/validation/validation-problem.model.js.map +1 -1
- package/dist/esm/validation/validation.service.js +6 -4
- package/dist/esm/validation/validation.service.js.map +1 -1
- package/dist/esm/websocket/models/websocket-message.model.js +1 -1
- package/dist/esm/websocket/models/websocket-message.model.js.map +1 -1
- package/dist/esm/websocket/models/websocket-request.model.js.map +1 -1
- package/dist/esm/websocket/services/websocket.service.js +1 -2
- package/dist/esm/websocket/services/websocket.service.js.map +1 -1
- package/package.json +9 -9
- package/src/__testing__/mocks/entities/child.entity.ts +4 -1
- package/src/__testing__/mocks/entities/company.entity.ts +5 -2
- package/src/__testing__/mocks/entities/profile.entity.ts +5 -2
- package/src/__testing__/mocks/entities/role.entity.ts +1 -1
- package/src/__testing__/mocks/entities/user.entity.ts +1 -1
- package/src/__testing__/test-server/create-test-data-source.function.ts +5 -5
- package/src/__testing__/test-server/start-test-server.function.ts +8 -6
- package/src/__testing__/test-server/user-repository.ts +4 -3
- package/src/application.ts +8 -2
- package/src/auth/2fa/two-factor.service.test.ts +151 -0
- package/src/auth/auth.service.test.ts +381 -0
- package/src/auth/encryption/encryption-key.model.ts +7 -2
- package/src/auth/strategies/cookie/cookie-auth.auth-strategy.ts +3 -2
- package/src/auth/strategies/jwt/jwt-credentials.model.ts +7 -1
- package/src/auth/strategies/jwt/jwt.auth-strategy.ts +5 -3
- package/src/backup/backup-resource-entity.model.ts +7 -2
- package/src/backup/backup-service.test.ts +1 -1
- package/src/backup/backup.service.ts +1 -1
- package/src/caching/cache/base-cache.model.ts +3 -3
- package/src/caching/cache/multi-tier.cache.ts +3 -3
- package/src/caching/cache/read-aside/read-aside.cache.ts +2 -2
- package/src/caching/cache/read-aside/write-around-read-aside.cache.ts +2 -2
- package/src/caching/cache/read-aside/write-behind-read-aside.cache.ts +2 -2
- package/src/caching/cache/read-aside/write-invalidate-read-aside-args-only.cache.ts +2 -2
- package/src/caching/cache/read-aside/write-invalidate-read-aside-with-result.cache.ts +2 -2
- package/src/caching/cache/read-aside/write-through-read-aside.cache.ts +2 -2
- package/src/caching/cache/read-through/read-through.cache.ts +2 -2
- package/src/caching/cache/read-through/write-around-read-through.cache.ts +2 -2
- package/src/caching/cache/read-through/write-behind-read-through.cache.ts +2 -2
- package/src/caching/cache/read-through/write-invalidate-read-through-args-only.cache.ts +2 -2
- package/src/caching/cache/read-through/write-invalidate-read-through-with-result.cache.ts +2 -2
- package/src/caching/cache/read-through/write-through-read-through.cache.ts +2 -2
- package/src/change-sets/change-set-repository.test.ts +317 -0
- package/src/change-sets/change-set-repository.ts +17 -17
- package/src/change-sets/models/change-set-entity.model.ts +6 -4
- package/src/change-sets/models/change-set.model.ts +1 -1
- package/src/change-sets/models/change.model.ts +7 -2
- package/src/change-sets/models/soft-delete-entity.model.ts +5 -3
- package/src/change-sets/soft-delete-repository.test.ts +326 -0
- package/src/change-sets/soft-delete-repository.ts +29 -10
- package/src/context/als.utilities.ts +5 -5
- package/src/context/cache/cache.context.ts +33 -0
- package/src/cron/cron.test.ts +421 -0
- package/src/data-source/array-where-filter.test.ts +332 -0
- package/src/data-source/data-sources/data-source-initialization.error.ts +9 -0
- package/src/data-source/data-sources/data-source.interface.ts +14 -1
- package/src/data-source/data-sources/postgres-typeorm-data-source.model.ts +330 -0
- package/src/data-source/data-sources/sql-data-source.interface.ts +35 -0
- package/src/data-source/data-sources/typeorm-base-data-source.model.ts +544 -0
- package/src/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.ts +451 -0
- package/src/data-source/data-sources/where-converter/typeorm-where-filter.converter.ts +376 -0
- package/src/data-source/exclude-property.test.ts +4 -1
- package/src/data-source/hooks/hooks.test.ts +268 -0
- package/src/data-source/migration/migration.test.ts +4 -3
- package/src/data-source/models/options/count-options.model.ts +2 -7
- package/src/data-source/models/options/delete-all-options.model.ts +2 -4
- package/src/data-source/models/options/find-all-options.model.ts +2 -2
- package/src/data-source/models/options/find-by-id-options.model.ts +1 -6
- package/src/data-source/models/options/find-one-options.model.ts +2 -11
- package/src/data-source/models/options/update-all-options.model.ts +2 -5
- package/src/data-source/models/options/update-by-id-options.model.ts +2 -5
- package/src/data-source/models/where/array-where-filter.model.ts +147 -5
- package/src/data-source/models/where/base-where-filter.model.ts +19 -1
- package/src/data-source/models/where/boolean-where-filter.model.ts +7 -2
- package/src/data-source/models/where/date-where-filter.model.ts +9 -16
- package/src/data-source/models/where/number-where-filter.model.ts +9 -16
- package/src/data-source/models/where/object-where-filter.model.ts +66 -7
- package/src/data-source/models/where/string-where-filter.model.ts +9 -16
- package/src/data-source/models/where/where-filter-keys.model.ts +88 -0
- package/src/data-source/models/where/where-filter-to-find-options-where-function.test.ts +35 -13
- package/src/data-source/models/where/where-filter.model.ts +7 -4
- package/src/data-source/nested-where-filter.test.ts +344 -0
- package/src/data-source/query-failed.error.ts +38 -1
- package/src/data-source/repository-relation-pitfalls.test.ts +232 -0
- package/src/data-source/repository.test.ts +274 -37
- package/src/data-source/repository.ts +50 -16
- package/src/data-source/transaction/transaction.test.ts +1 -1
- package/src/data-source/where-filter.test.ts +479 -0
- package/src/di/decorators/inject-repository.decorator.ts +3 -2
- package/src/di/default/zibri-di-tokens.default.ts +2 -2
- package/src/email/email.service.test.ts +382 -0
- package/src/email/email.service.ts +4 -5
- package/src/email/models/email.model.ts +1 -1
- package/src/entity/decorators/entity.decorator.ts +44 -5
- package/src/entity/decorators/property.decorator.ts +54 -36
- package/src/entity/entity-metadata-missing.error.ts +15 -0
- package/src/entity/models/base-relation-metadata.model.ts +1 -1
- package/src/entity/models/belongs-to-one-property-metadata.model.ts +34 -0
- package/src/entity/models/has-one-property-metadata.model.ts +20 -0
- package/src/entity/models/many-to-many-property-metadata.model.ts +3 -3
- package/src/entity/models/many-to-one-property-metadata.model.ts +17 -3
- package/src/entity/models/relation.enum.ts +2 -1
- package/src/entity/partial-class.model.ts +1 -1
- package/src/event/event-cleanup.cron-job.ts +4 -6
- package/src/event/event-subscriber-run.model.ts +8 -9
- package/src/event/event.model.ts +1 -1
- package/src/event/event.service.ts +6 -3
- package/src/global/model-registry/default-descriptor.ts +2 -1
- package/src/global/model-registry/encryption-descriptor.ts +2 -1
- package/src/global/model-registry/exclude-descriptor.ts +2 -1
- package/src/global/model-registry/hash-descriptor.ts +2 -1
- package/src/index.ts +15 -3
- package/src/logging/log-context.model.ts +3 -34
- package/src/open-api/open-api.service.ts +32 -13
- package/src/parsing/form-data/form-data.body-parser.ts +2 -1
- package/src/parsing/functions/parse-boolean.function.ts +0 -1
- package/src/parsing/functions/parse-object.function.ts +2 -1
- package/src/parsing/parser.ts +2 -1
- package/src/routing/decorators/body.decorator.ts +2 -1
- package/src/routing/resolve-route-params.function.ts +1 -1
- package/src/routing/router.ts +41 -7
- package/src/utilities/metadata-injection-keys.enum.ts +1 -0
- package/src/utilities/typeorm.utilities.ts +75 -0
- package/src/validation/validation-problem.model.ts +7 -9
- package/src/validation/validation.service.ts +6 -4
- package/src/websocket/models/websocket-message.model.ts +1 -1
- package/src/websocket/models/websocket-request.model.ts +17 -9
- package/src/websocket/services/websocket.service.ts +1 -2
- package/dist/cjs/data-source/data-sources/postgres-data-source.model.d.ts +0 -129
- package/dist/cjs/data-source/data-sources/postgres-data-source.model.d.ts.map +0 -1
- package/dist/cjs/data-source/data-sources/postgres-data-source.model.js +0 -534
- package/dist/cjs/data-source/data-sources/postgres-data-source.model.js.map +0 -1
- package/dist/cjs/data-source/models/where/where-filter-to-find-options-where.function.d.ts +0 -11
- package/dist/cjs/data-source/models/where/where-filter-to-find-options-where.function.d.ts.map +0 -1
- package/dist/cjs/data-source/models/where/where-filter-to-find-options-where.function.js +0 -229
- package/dist/cjs/data-source/models/where/where-filter-to-find-options-where.function.js.map +0 -1
- package/dist/cjs/entity/models/one-to-one-property-metadata.model.d.ts +0 -30
- package/dist/cjs/entity/models/one-to-one-property-metadata.model.d.ts.map +0 -1
- package/dist/cjs/entity/models/one-to-one-property-metadata.model.js.map +0 -1
- package/dist/esm/data-source/data-sources/postgres-data-source.model.js +0 -534
- package/dist/esm/data-source/data-sources/postgres-data-source.model.js.map +0 -1
- package/dist/esm/data-source/models/where/where-filter-to-find-options-where.function.js +0 -229
- package/dist/esm/data-source/models/where/where-filter-to-find-options-where.function.js.map +0 -1
- package/dist/esm/entity/models/one-to-one-property-metadata.model.js.map +0 -1
- package/src/data-source/data-sources/postgres-data-source.model.ts +0 -675
- package/src/data-source/models/where/where-filter-to-find-options-where.function.ts +0 -307
- package/src/entity/models/one-to-one-property-metadata.model.ts +0 -35
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, it } from '@jest/globals';
|
|
2
|
+
import { TOTP } from 'otpauth';
|
|
3
|
+
|
|
4
|
+
import { OtpCredentials } from './methods/otp/otp-credentials.model';
|
|
5
|
+
import { TwoFactorServiceInterface } from './two-factor-service.interface';
|
|
6
|
+
import { createTestDataSource, defaultTestServerEntities } from '../../__testing__/test-server/create-test-data-source.function';
|
|
7
|
+
import { startTestServer, StartedTestServer } from '../../__testing__/test-server/start-test-server.function';
|
|
8
|
+
import { HttpRequestContext } from '../../context/request/http-request.context';
|
|
9
|
+
import { RequestContextToken } from '../../context/request/request-context-token.model';
|
|
10
|
+
import { PostgresDataSource } from '../../data-source/data-sources/postgres-typeorm-data-source.model';
|
|
11
|
+
import { Repository } from '../../data-source/repository';
|
|
12
|
+
import { repositoryTokenFor } from '../../di/decorators/inject-repository.decorator';
|
|
13
|
+
import { ZIBRI_DI_TOKENS } from '../../di/default/zibri-di-tokens.default';
|
|
14
|
+
import { inject } from '../../di/inject.function';
|
|
15
|
+
import { BaseUserEntity } from '../models/base-user.model';
|
|
16
|
+
import { OtpConfirmRegisterData, OtpTwoFactorMethod } from './methods/otp/otp.two-factor-method';
|
|
17
|
+
import { Entity } from '../../entity/decorators/entity.decorator';
|
|
18
|
+
import { Newable } from '../../types/newable.type';
|
|
19
|
+
|
|
20
|
+
enum TestRole {
|
|
21
|
+
USER = 'user'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Entity()
|
|
25
|
+
class User extends BaseUserEntity(TestRole) {}
|
|
26
|
+
|
|
27
|
+
let server: StartedTestServer;
|
|
28
|
+
let twoFactorService: TwoFactorServiceInterface;
|
|
29
|
+
let otpMethod: OtpTwoFactorMethod;
|
|
30
|
+
let userRepo: Repository<User>;
|
|
31
|
+
let otpCredentialsRepo: Repository<OtpCredentials>;
|
|
32
|
+
let otpHeader: string; // injected value of ZIBRI_DI_TOKENS.OTP_HEADER
|
|
33
|
+
let otpLength: number;
|
|
34
|
+
|
|
35
|
+
describe('TwoFactorService (contract via OTP method)', () => {
|
|
36
|
+
beforeAll(async () => {
|
|
37
|
+
const dataSourceClass: Newable<PostgresDataSource> = createTestDataSource({
|
|
38
|
+
entities: [...defaultTestServerEntities, User]
|
|
39
|
+
});
|
|
40
|
+
server = await startTestServer({ dataSources: [dataSourceClass] });
|
|
41
|
+
|
|
42
|
+
twoFactorService = inject(ZIBRI_DI_TOKENS.TWO_FACTOR_SERVICE);
|
|
43
|
+
otpMethod = inject(OtpTwoFactorMethod);
|
|
44
|
+
userRepo = inject(repositoryTokenFor(User));
|
|
45
|
+
otpCredentialsRepo = inject(repositoryTokenFor(OtpCredentials));
|
|
46
|
+
otpHeader = inject(ZIBRI_DI_TOKENS.OTP_HEADER);
|
|
47
|
+
otpLength = inject(ZIBRI_DI_TOKENS.OTP_LENGTH);
|
|
48
|
+
}, 15000);
|
|
49
|
+
|
|
50
|
+
afterAll(async () => {
|
|
51
|
+
await server.shutdown();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
let user: User;
|
|
55
|
+
|
|
56
|
+
beforeEach(async () => {
|
|
57
|
+
// start fresh every test
|
|
58
|
+
await otpCredentialsRepo.deleteAll({});
|
|
59
|
+
await userRepo.deleteAll({});
|
|
60
|
+
user = await userRepo.create({ email: '2fa-test@example.com', roles: [TestRole.USER] });
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('requestRegister should create an unconfirmed credential', async () => {
|
|
64
|
+
await twoFactorService.requestRegisterTwoFactorMethodForUser(user, otpMethod, undefined as never);
|
|
65
|
+
const credentials: OtpCredentials[] = await otpCredentialsRepo.findAll({ where: { userId: user.id } });
|
|
66
|
+
expect(credentials).toHaveLength(1);
|
|
67
|
+
expect(credentials[0].secret).toBeTruthy();
|
|
68
|
+
expect(credentials[0].confirmed).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('confirmRegister with a valid token should mark the credential as confirmed', async () => {
|
|
72
|
+
await twoFactorService.requestRegisterTwoFactorMethodForUser(user, otpMethod, undefined as never);
|
|
73
|
+
const credentials: OtpCredentials[] = await otpCredentialsRepo.findAll({ where: { userId: user.id } });
|
|
74
|
+
const secret: string = credentials[0].secret;
|
|
75
|
+
|
|
76
|
+
const validToken: string = new TOTP({ secret }).generate();
|
|
77
|
+
await twoFactorService.confirmRegisterTwoFactorMethodForUser(user, otpMethod, {
|
|
78
|
+
token: validToken
|
|
79
|
+
} as OtpConfirmRegisterData);
|
|
80
|
+
|
|
81
|
+
const updated: OtpCredentials[] = await otpCredentialsRepo.findAll({ where: { userId: user.id } });
|
|
82
|
+
expect(updated[0].confirmed).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('confirmRegister with an invalid token should throw', async () => {
|
|
86
|
+
await twoFactorService.requestRegisterTwoFactorMethodForUser(user, otpMethod, undefined as never);
|
|
87
|
+
await expect(
|
|
88
|
+
twoFactorService.confirmRegisterTwoFactorMethodForUser(user, otpMethod, {
|
|
89
|
+
token: '000000'.slice(0, otpLength)
|
|
90
|
+
} as OtpConfirmRegisterData)
|
|
91
|
+
).rejects.toThrow('The provided two factor code is invalid.');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('has2fa should return true when a valid OTP header is present', async () => {
|
|
95
|
+
// register & confirm
|
|
96
|
+
await twoFactorService.requestRegisterTwoFactorMethodForUser(user, otpMethod, undefined as never);
|
|
97
|
+
const credentials: OtpCredentials[] = await otpCredentialsRepo.findAll({ where: { userId: user.id } });
|
|
98
|
+
const validToken: string = new TOTP({ secret: credentials[0].secret }).generate();
|
|
99
|
+
await twoFactorService.confirmRegisterTwoFactorMethodForUser(user, otpMethod, {
|
|
100
|
+
token: validToken
|
|
101
|
+
} as OtpConfirmRegisterData);
|
|
102
|
+
|
|
103
|
+
const context: HttpRequestContext = {
|
|
104
|
+
request: { headers: { [otpHeader]: validToken } },
|
|
105
|
+
// eslint-disable-next-line unusedImports/no-unused-vars
|
|
106
|
+
has: <T>(token: RequestContextToken<T>) => false
|
|
107
|
+
} as HttpRequestContext;
|
|
108
|
+
|
|
109
|
+
const result: boolean = await twoFactorService.has2fa(user, context);
|
|
110
|
+
expect(result).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('has2fa should return false when the token is invalid', async () => {
|
|
114
|
+
await twoFactorService.requestRegisterTwoFactorMethodForUser(user, otpMethod, undefined as never);
|
|
115
|
+
const credentials: OtpCredentials[] = await otpCredentialsRepo.findAll({ where: { userId: user.id } });
|
|
116
|
+
const validToken: string = new TOTP({ secret: credentials[0].secret }).generate();
|
|
117
|
+
await twoFactorService.confirmRegisterTwoFactorMethodForUser(user, otpMethod, {
|
|
118
|
+
token: validToken
|
|
119
|
+
} as OtpConfirmRegisterData);
|
|
120
|
+
|
|
121
|
+
const context: HttpRequestContext = {
|
|
122
|
+
request: { headers: { [otpHeader]: '000000'.slice(0, otpLength) } },
|
|
123
|
+
// eslint-disable-next-line unusedImports/no-unused-vars
|
|
124
|
+
has: <T>(token: RequestContextToken<T>) => false
|
|
125
|
+
} as HttpRequestContext;
|
|
126
|
+
|
|
127
|
+
const result: boolean = await twoFactorService.has2fa(user, context);
|
|
128
|
+
expect(result).toBe(false);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('unregister should delete all credentials and make has2fa false', async () => {
|
|
132
|
+
await twoFactorService.requestRegisterTwoFactorMethodForUser(user, otpMethod, undefined as never);
|
|
133
|
+
const credentials: OtpCredentials[] = await otpCredentialsRepo.findAll({ where: { userId: user.id } });
|
|
134
|
+
await twoFactorService.confirmRegisterTwoFactorMethodForUser(user, otpMethod, {
|
|
135
|
+
token: new TOTP({ secret: credentials[0].secret }).generate()
|
|
136
|
+
} as OtpConfirmRegisterData);
|
|
137
|
+
|
|
138
|
+
await twoFactorService.unregisterTwoFactorMethodForUser(user, otpMethod);
|
|
139
|
+
|
|
140
|
+
const remaining: OtpCredentials[] = await otpCredentialsRepo.findAll({ where: { userId: user.id } });
|
|
141
|
+
expect(remaining).toHaveLength(0);
|
|
142
|
+
|
|
143
|
+
const context: HttpRequestContext = {
|
|
144
|
+
request: { headers: { [otpHeader]: 'does-not-matter' } },
|
|
145
|
+
// eslint-disable-next-line unusedImports/no-unused-vars
|
|
146
|
+
has: <T>(token: RequestContextToken<T>) => false
|
|
147
|
+
} as HttpRequestContext;
|
|
148
|
+
const result: boolean = await twoFactorService.has2fa(user, context);
|
|
149
|
+
expect(result).toBe(false);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, it } from '@jest/globals';
|
|
2
|
+
|
|
3
|
+
import { AuthServiceInterface } from './auth-service.interface';
|
|
4
|
+
import { Auth } from './decorators/auth.decorator';
|
|
5
|
+
import { BelongsToMetadata } from './models/belongs-to-metadata.model';
|
|
6
|
+
import { HasRoleMetadata } from './models/has-role-metadata.model';
|
|
7
|
+
import { IsLoggedInMetadata } from './models/is-logged-in-metadata.model';
|
|
8
|
+
import { IsNotLoggedInMetadata } from './models/is-not-logged-in-metadata.model';
|
|
9
|
+
import { Require2faMetadata } from './models/require-2fa-metadata.model';
|
|
10
|
+
import { AuthStrategies } from './strategies/auth-strategies.model';
|
|
11
|
+
import { JwtUser } from '../__testing__/mocks/entities/jwt-user.entity';
|
|
12
|
+
import { Roles } from '../__testing__/mocks/entities/roles.enum';
|
|
13
|
+
import { createTestDataSource, defaultTestServerEntities } from '../__testing__/test-server/create-test-data-source.function';
|
|
14
|
+
import { StartedTestServer, startTestServer } from '../__testing__/test-server/start-test-server.function';
|
|
15
|
+
import { HttpRequestContext } from '../context/request/http-request.context';
|
|
16
|
+
import { Repository } from '../data-source/repository';
|
|
17
|
+
import { repositoryTokenFor } from '../di/decorators/inject-repository.decorator';
|
|
18
|
+
import { ZIBRI_DI_TOKENS } from '../di/default/zibri-di-tokens.default';
|
|
19
|
+
import { inject } from '../di/inject.function';
|
|
20
|
+
import { BaseEntity } from '../entity/base-entity.model';
|
|
21
|
+
import { PasswordResetToken, PasswordResetTokenCreateData } from './models/password-reset-token.model';
|
|
22
|
+
import { Entity } from '../entity/decorators/entity.decorator';
|
|
23
|
+
import { Property } from '../entity/decorators/property.decorator';
|
|
24
|
+
import { Controller } from '../routing/decorators/controller.decorator';
|
|
25
|
+
import { Get } from '../routing/decorators/get.decorator';
|
|
26
|
+
import { Newable } from '../types/newable.type';
|
|
27
|
+
import { JwtAuthData } from './strategies/jwt/jwt-auth-data.model';
|
|
28
|
+
import { JwtCredentials, JwtCredentialsCreateData } from './strategies/jwt/jwt-credentials.model';
|
|
29
|
+
import { JwtAuthStrategy } from './strategies/jwt/jwt.auth-strategy';
|
|
30
|
+
import { DefaultTestServerUserRepository } from '../__testing__/test-server/user-repository';
|
|
31
|
+
import { Transaction } from '../data-source/transaction/transaction.model';
|
|
32
|
+
|
|
33
|
+
@Entity()
|
|
34
|
+
class Note extends BaseEntity {
|
|
35
|
+
@Property.string()
|
|
36
|
+
title!: string;
|
|
37
|
+
|
|
38
|
+
@Property.string({ format: 'uuid' })
|
|
39
|
+
userId!: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ----- dummy controller with auth decorators -----
|
|
43
|
+
@Controller('/dummy')
|
|
44
|
+
class DummyController {
|
|
45
|
+
@Get('/open')
|
|
46
|
+
open(): void {}
|
|
47
|
+
|
|
48
|
+
@Get('/login-required')
|
|
49
|
+
@Auth.isLoggedIn([JwtAuthStrategy])
|
|
50
|
+
loginRequired(): void {}
|
|
51
|
+
|
|
52
|
+
@Get('/admin-only')
|
|
53
|
+
@Auth.hasRole([Roles.ADMIN], [JwtAuthStrategy])
|
|
54
|
+
adminOnly(): void {}
|
|
55
|
+
|
|
56
|
+
@Get('/note/:id')
|
|
57
|
+
@Auth.belongsTo(Note, 'id', 'userId', [JwtAuthStrategy])
|
|
58
|
+
belongsToNote(): void {}
|
|
59
|
+
|
|
60
|
+
@Get('/2fa-required')
|
|
61
|
+
@Auth.require2fa([])
|
|
62
|
+
require2fa(): void {}
|
|
63
|
+
|
|
64
|
+
@Get('/logged-out-only')
|
|
65
|
+
@Auth.isNotLoggedIn([JwtAuthStrategy])
|
|
66
|
+
loggedOutOnly(): void {}
|
|
67
|
+
|
|
68
|
+
@Get('/skip-auth')
|
|
69
|
+
@Auth.skip()
|
|
70
|
+
skipAuth(): void {}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ---- helper to build contexts ----
|
|
74
|
+
function buildContext(accessToken?: string, params?: Record<string, string>): HttpRequestContext {
|
|
75
|
+
return {
|
|
76
|
+
request: {
|
|
77
|
+
headers: accessToken ? { authorization: `Bearer ${accessToken}` } : {},
|
|
78
|
+
params: params ?? {}
|
|
79
|
+
},
|
|
80
|
+
has: () => false
|
|
81
|
+
// minimal other properties as needed by your actual HttpRequestContext interface
|
|
82
|
+
} as unknown as HttpRequestContext;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let server: StartedTestServer;
|
|
86
|
+
let authService: AuthServiceInterface;
|
|
87
|
+
let userRepo: DefaultTestServerUserRepository;
|
|
88
|
+
let credentialsRepository: Repository<JwtCredentials, JwtCredentialsCreateData>;
|
|
89
|
+
let noteRepo: Repository<Note>;
|
|
90
|
+
const strategies: AuthStrategies = [JwtAuthStrategy];
|
|
91
|
+
|
|
92
|
+
const adminEmail: string = 'auth-test@example.com';
|
|
93
|
+
const adminPassword: string = 'secure123';
|
|
94
|
+
const userEmail: string = 'auth-test2@example.com';
|
|
95
|
+
const userPassword: string = 'secure123';
|
|
96
|
+
|
|
97
|
+
describe('AuthService contract', () => {
|
|
98
|
+
let testAdmin: JwtUser;
|
|
99
|
+
let testUser: JwtUser;
|
|
100
|
+
let adminAuthData: JwtAuthData<Roles>;
|
|
101
|
+
let userAuthData: JwtAuthData<Roles>;
|
|
102
|
+
|
|
103
|
+
beforeAll(async () => {
|
|
104
|
+
server = await startTestServer({
|
|
105
|
+
dataSources: [createTestDataSource({ entities: [...defaultTestServerEntities, Note] })],
|
|
106
|
+
controllers: [DummyController]
|
|
107
|
+
});
|
|
108
|
+
authService = inject(ZIBRI_DI_TOKENS.AUTH_SERVICE);
|
|
109
|
+
userRepo = inject(DefaultTestServerUserRepository);
|
|
110
|
+
credentialsRepository = inject(repositoryTokenFor(JwtCredentials));
|
|
111
|
+
noteRepo = inject(repositoryTokenFor(Note));
|
|
112
|
+
}, 15000);
|
|
113
|
+
|
|
114
|
+
afterAll(async () => {
|
|
115
|
+
await server.shutdown();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
beforeEach(async () => {
|
|
119
|
+
await noteRepo.deleteAll({});
|
|
120
|
+
await userRepo.deleteAll({});
|
|
121
|
+
await credentialsRepository.deleteAll({});
|
|
122
|
+
|
|
123
|
+
testAdmin = await userRepo.create({
|
|
124
|
+
email: adminEmail,
|
|
125
|
+
roles: [Roles.USER, Roles.ADMIN]
|
|
126
|
+
});
|
|
127
|
+
await credentialsRepository.create({ email: adminEmail, password: adminPassword, userId: testAdmin.id });
|
|
128
|
+
testUser = await userRepo.create({
|
|
129
|
+
email: userEmail,
|
|
130
|
+
roles: [Roles.USER]
|
|
131
|
+
});
|
|
132
|
+
await credentialsRepository.create({ email: userEmail, password: userPassword, userId: testUser.id });
|
|
133
|
+
|
|
134
|
+
adminAuthData = await authService.login(
|
|
135
|
+
JwtAuthStrategy<Roles>,
|
|
136
|
+
{ email: adminEmail, password: adminPassword }
|
|
137
|
+
);
|
|
138
|
+
userAuthData = await authService.login(
|
|
139
|
+
JwtAuthStrategy<Roles>,
|
|
140
|
+
{ email: userEmail, password: userPassword }
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// --------- login & logout ----------
|
|
145
|
+
describe('login / logout / refresh', () => {
|
|
146
|
+
it('login returns valid auth data', () => {
|
|
147
|
+
expect(adminAuthData.accessToken).toBeTruthy();
|
|
148
|
+
expect(adminAuthData.refreshToken).toBeTruthy();
|
|
149
|
+
expect(adminAuthData.roles).toBeTruthy();
|
|
150
|
+
expect(adminAuthData.userId).toBeTruthy();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('refreshLogin returns fresh auth data', async () => {
|
|
154
|
+
const transaction: Transaction = await userRepo.dataSource.startTransaction();
|
|
155
|
+
const refreshed: JwtAuthData<Roles> = await authService.refreshLogin(
|
|
156
|
+
JwtAuthStrategy<Roles>,
|
|
157
|
+
{ refreshToken: adminAuthData.refreshToken.value, transaction }
|
|
158
|
+
);
|
|
159
|
+
await transaction.commit();
|
|
160
|
+
|
|
161
|
+
expect(refreshed).toHaveProperty('accessToken');
|
|
162
|
+
expect(refreshed.accessToken).not.toBe(adminAuthData.accessToken);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('logout invalidates the refresh token (refreshLogin fails)', async () => {
|
|
166
|
+
await authService.logout(
|
|
167
|
+
JwtAuthStrategy,
|
|
168
|
+
{ refreshToken: adminAuthData.refreshToken.value }
|
|
169
|
+
);
|
|
170
|
+
// Attempt to refresh after logout – must throw.
|
|
171
|
+
await expect(
|
|
172
|
+
authService.refreshLogin(
|
|
173
|
+
JwtAuthStrategy<Roles>,
|
|
174
|
+
{ refreshToken: adminAuthData.refreshToken.value, transaction: await userRepo.dataSource.startTransaction() }
|
|
175
|
+
)
|
|
176
|
+
).rejects.toThrow();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// --------- getCurrentUser ----------
|
|
181
|
+
describe('getCurrentUser', () => {
|
|
182
|
+
it('returns the logged in user', async () => {
|
|
183
|
+
const ctx: HttpRequestContext = buildContext(adminAuthData.accessToken.value);
|
|
184
|
+
const current: JwtUser = await authService.getCurrentUser(ctx, strategies, true);
|
|
185
|
+
expect(current.id).toBe(testAdmin.id);
|
|
186
|
+
expect(current.email).toBe(adminEmail);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('required=false returns undefined without token', async () => {
|
|
190
|
+
const ctx: HttpRequestContext = buildContext();
|
|
191
|
+
const current: JwtUser | undefined = await authService.getCurrentUser(ctx, strategies, false);
|
|
192
|
+
expect(current).toBeUndefined();
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('required=true throws without token', async () => {
|
|
196
|
+
const ctx: HttpRequestContext = buildContext();
|
|
197
|
+
await expect(
|
|
198
|
+
authService.getCurrentUser(ctx, strategies, true)
|
|
199
|
+
).rejects.toThrow();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// --------- isLoggedIn / hasRole ----------
|
|
204
|
+
describe('isLoggedIn / hasRole', () => {
|
|
205
|
+
it('isLoggedIn returns true with valid token', async () => {
|
|
206
|
+
const ctx: HttpRequestContext = buildContext(adminAuthData.accessToken.value);
|
|
207
|
+
expect(await authService.isLoggedIn(ctx, strategies)).toBe(true);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('isLoggedIn returns false without token', async () => {
|
|
211
|
+
const ctx: HttpRequestContext = buildContext();
|
|
212
|
+
expect(await authService.isLoggedIn(ctx, strategies)).toBe(false);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('hasRole returns true if role present', async () => {
|
|
216
|
+
const ctx: HttpRequestContext = buildContext(adminAuthData.accessToken.value);
|
|
217
|
+
expect(await authService.hasRole(ctx, strategies, [Roles.ADMIN])).toBe(true);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('hasRole returns false if role missing', async () => {
|
|
221
|
+
const ctx: HttpRequestContext = buildContext(adminAuthData.accessToken.value);
|
|
222
|
+
expect(await authService.hasRole(ctx, strategies, ['nonexistent'])).toBe(false);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('hasRole returns false without token', async () => {
|
|
226
|
+
const ctx: HttpRequestContext = buildContext();
|
|
227
|
+
expect(await authService.hasRole(ctx, strategies, [Roles.USER])).toBe(false);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// --------- belongsTo ----------
|
|
232
|
+
describe('belongsTo', () => {
|
|
233
|
+
let note: Note;
|
|
234
|
+
|
|
235
|
+
beforeEach(async () => {
|
|
236
|
+
note = await noteRepo.create({ title: 'my note', userId: testAdmin.id });
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('returns true for owned resource', async () => {
|
|
240
|
+
const ctx: HttpRequestContext = buildContext(adminAuthData.accessToken.value, { id: note.id });
|
|
241
|
+
const result: boolean = await authService.belongsTo(ctx, strategies, Note, 'userId', 'id');
|
|
242
|
+
expect(result).toBe(true);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('returns false for resource owned by someone else', async () => {
|
|
246
|
+
const ctx: HttpRequestContext = buildContext(userAuthData.accessToken.value, { id: note.id });
|
|
247
|
+
const result: boolean = await authService.belongsTo(ctx, strategies, Note, 'userId', 'id');
|
|
248
|
+
expect(result).toBe(false);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// --------- metadata resolvers ----------
|
|
253
|
+
describe('resolve*Metadata', () => {
|
|
254
|
+
it('resolveIsLoggedInMetadata reads @Auth.isLoggedIn', async () => {
|
|
255
|
+
const meta: IsLoggedInMetadata | undefined = await authService.resolveIsLoggedInMetadata(DummyController, 'loginRequired');
|
|
256
|
+
expect(meta).toBeDefined();
|
|
257
|
+
expect((meta as IsLoggedInMetadata).allowedStrategies).toEqual([JwtAuthStrategy]);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it('resolveIsNotLoggedInMetadata reads @Auth.isNotLoggedIn', async () => {
|
|
261
|
+
const meta: IsNotLoggedInMetadata | undefined = await authService.resolveIsNotLoggedInMetadata(DummyController, 'loggedOutOnly');
|
|
262
|
+
expect(meta).toBeDefined();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('resolveHasRoleMetadata reads @Auth.hasRole', async () => {
|
|
266
|
+
const meta: HasRoleMetadata | undefined = await authService.resolveHasRoleMetadata(DummyController, 'adminOnly');
|
|
267
|
+
expect(meta).toBeDefined();
|
|
268
|
+
const hasRoleMeta: HasRoleMetadata = meta as HasRoleMetadata;
|
|
269
|
+
expect(hasRoleMeta.allowedRoles).toEqual([Roles.ADMIN]);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('resolveBelongsToMetadata reads @Auth.belongsTo', async () => {
|
|
273
|
+
const meta: BelongsToMetadata<Newable<BaseEntity>> | undefined = await authService.resolveBelongsToMetadata(DummyController, 'belongsToNote');
|
|
274
|
+
expect(meta).toBeDefined();
|
|
275
|
+
const belongsMeta: BelongsToMetadata<Newable<BaseEntity>> = meta as BelongsToMetadata<Newable<BaseEntity>>;
|
|
276
|
+
expect(belongsMeta.targetEntity).toBe(Note);
|
|
277
|
+
expect(belongsMeta.targetUserIdKey).toBe('userId');
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('resolveRequire2faMetadata reads @Auth.require2fa', async () => {
|
|
281
|
+
const meta: Require2faMetadata | undefined = await authService.resolveRequire2faMetadata(DummyController, 'require2fa');
|
|
282
|
+
expect(meta).toBeDefined();
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// --------- checkAccess ----------
|
|
287
|
+
describe('checkAccess', () => {
|
|
288
|
+
it('throws when not logged in for loginRequired', async () => {
|
|
289
|
+
const ctx: HttpRequestContext = buildContext();
|
|
290
|
+
await expect(
|
|
291
|
+
authService.checkAccess(DummyController, 'loginRequired', ctx)
|
|
292
|
+
).rejects.toThrow();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('succeeds when logged in for loginRequired', async () => {
|
|
296
|
+
const ctx: HttpRequestContext = buildContext(adminAuthData.accessToken.value);
|
|
297
|
+
await expect(
|
|
298
|
+
authService.checkAccess(DummyController, 'loginRequired', ctx)
|
|
299
|
+
).resolves.toBeUndefined();
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('throws when missing role for adminOnly', async () => {
|
|
303
|
+
const ctx: HttpRequestContext = buildContext(userAuthData.accessToken.value);
|
|
304
|
+
await expect(
|
|
305
|
+
authService.checkAccess(DummyController, 'adminOnly', ctx)
|
|
306
|
+
).rejects.toThrow();
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('succeeds when role present for adminOnly', async () => {
|
|
310
|
+
const ctx: HttpRequestContext = buildContext(adminAuthData.accessToken.value);
|
|
311
|
+
await expect(
|
|
312
|
+
authService.checkAccess(DummyController, 'adminOnly', ctx)
|
|
313
|
+
).resolves.toBeUndefined();
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('skip auth always succeeds', async () => {
|
|
317
|
+
const ctx: HttpRequestContext = buildContext();
|
|
318
|
+
await expect(
|
|
319
|
+
authService.checkAccess(DummyController, 'skipAuth', ctx)
|
|
320
|
+
).resolves.toBeUndefined();
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// --------- password reset ----------
|
|
325
|
+
describe('requestPasswordReset / confirmPasswordReset', () => {
|
|
326
|
+
let resetTokenRepo: Repository<PasswordResetToken, PasswordResetTokenCreateData>;
|
|
327
|
+
|
|
328
|
+
beforeAll(() => {
|
|
329
|
+
resetTokenRepo = inject(repositoryTokenFor(PasswordResetToken));
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
beforeEach(async () => {
|
|
333
|
+
await resetTokenRepo.deleteAll({});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('requestPasswordReset creates a reset token', async () => {
|
|
337
|
+
const transaction: Transaction = await userRepo.dataSource.startTransaction();
|
|
338
|
+
await authService.requestPasswordReset(
|
|
339
|
+
JwtAuthStrategy,
|
|
340
|
+
{ user: testAdmin, transaction }
|
|
341
|
+
);
|
|
342
|
+
await transaction.commit();
|
|
343
|
+
|
|
344
|
+
const tokens: PasswordResetToken[] = await resetTokenRepo.findAll({ where: { userId: testAdmin.id } });
|
|
345
|
+
expect(tokens).toHaveLength(1);
|
|
346
|
+
expect(tokens[0].value).toBeTruthy();
|
|
347
|
+
expect(tokens[0].expirationDate).toBeInstanceOf(Date);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it('confirmPasswordReset with valid token updates password', async () => {
|
|
351
|
+
// 1. Request reset → token created
|
|
352
|
+
const transaction: Transaction = await userRepo.dataSource.startTransaction();
|
|
353
|
+
await authService.requestPasswordReset(
|
|
354
|
+
JwtAuthStrategy,
|
|
355
|
+
{ user: testAdmin, transaction }
|
|
356
|
+
);
|
|
357
|
+
await transaction.commit();
|
|
358
|
+
const tokens: PasswordResetToken[] = await resetTokenRepo.findAll({ where: { userId: testAdmin.id } });
|
|
359
|
+
const resetValue: string = tokens[0].value;
|
|
360
|
+
|
|
361
|
+
// 2. Confirm reset with new password
|
|
362
|
+
const transaction2: Transaction = await userRepo.dataSource.startTransaction();
|
|
363
|
+
await authService.confirmPasswordReset(
|
|
364
|
+
JwtAuthStrategy,
|
|
365
|
+
{ resetToken: resetValue, newPassword: 'newPass456', transaction: transaction2 }
|
|
366
|
+
);
|
|
367
|
+
await transaction2.commit();
|
|
368
|
+
|
|
369
|
+
// 3. Verify the token is consumed (deleted / no longer valid)
|
|
370
|
+
const afterTokens: PasswordResetToken[] = await resetTokenRepo.findAll({ where: { userId: testAdmin.id } });
|
|
371
|
+
expect(afterTokens).toHaveLength(0);
|
|
372
|
+
|
|
373
|
+
// 4. Verify login with new password works
|
|
374
|
+
const authData: JwtAuthData<Roles> = await authService.login(
|
|
375
|
+
JwtAuthStrategy<Roles>,
|
|
376
|
+
{ email: adminEmail, password: 'newPass456' }
|
|
377
|
+
);
|
|
378
|
+
expect(authData.accessToken).toBeTruthy();
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
});
|
|
@@ -29,8 +29,13 @@ export class EncryptionKey extends BaseEntity {
|
|
|
29
29
|
/**
|
|
30
30
|
* The encryption strategy that this key belongs to.
|
|
31
31
|
*/
|
|
32
|
-
@Property.manyToOne({ target: () => EncryptionStrategyEntity, inverseSide: 'keys' })
|
|
32
|
+
@Property.manyToOne({ target: () => EncryptionStrategyEntity, joinColumn: 'strategyId', inverseSide: 'keys' })
|
|
33
33
|
strategy!: EncryptionStrategyEntity;
|
|
34
|
+
/**
|
|
35
|
+
* The id of the strategy that this key belongs to.
|
|
36
|
+
*/
|
|
37
|
+
@Property.string({ format: 'uuid' })
|
|
38
|
+
strategyId!: string;
|
|
34
39
|
/**
|
|
35
40
|
* The status of the key.
|
|
36
41
|
*/
|
|
@@ -41,7 +46,7 @@ export class EncryptionKey extends BaseEntity {
|
|
|
41
46
|
/**
|
|
42
47
|
* The data for creating a new key.
|
|
43
48
|
*/
|
|
44
|
-
export type EncryptionKeyCreateData = OmitStrict<EncryptionKey, 'id' | 'strategy' | 'status'>
|
|
49
|
+
export type EncryptionKeyCreateData = OmitStrict<EncryptionKey, 'id' | 'strategy' | 'strategyId' | 'status'>
|
|
45
50
|
& DeepPartial<Pick<EncryptionKey, 'strategy'>>
|
|
46
51
|
& {
|
|
47
52
|
/**
|
|
@@ -9,6 +9,7 @@ import { CookieAuthSession, CookieAuthSessionCreateData } from './cookie-auth-se
|
|
|
9
9
|
import { ZibriApplication } from '../../../application';
|
|
10
10
|
import { HttpRequestContext } from '../../../context/request/http-request.context';
|
|
11
11
|
import { WebsocketRequestContext } from '../../../context/request/websocket-request.context';
|
|
12
|
+
import { RepositoryTypeForEntity } from '../../../data-source/data-sources/data-source.interface';
|
|
12
13
|
import { Repository } from '../../../data-source/repository';
|
|
13
14
|
import { Transaction } from '../../../data-source/transaction/transaction.model';
|
|
14
15
|
import { InjectRepository, repositoryTokenFor } from '../../../di/decorators/inject-repository.decorator';
|
|
@@ -326,12 +327,12 @@ export class CookieAuthStrategy<
|
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
try {
|
|
329
|
-
const repo:
|
|
330
|
+
const repo: RepositoryTypeForEntity<InstanceType<TargetEntity>> = inject(repositoryTokenFor(targetEntity));
|
|
330
331
|
const targetId: string | undefined = context.request.params?.[targetIdParamKey];
|
|
331
332
|
if (targetId == undefined) {
|
|
332
333
|
throw new Error(`Could not find the target id specified as path param "${targetId}"`);
|
|
333
334
|
}
|
|
334
|
-
const foundTarget: InstanceType<TargetEntity> = await repo.findById(targetId)
|
|
335
|
+
const foundTarget: InstanceType<TargetEntity> = await repo.findById(targetId) as InstanceType<TargetEntity>;
|
|
335
336
|
const userIdProperty: unknown = foundTarget[targetUserIdKey];
|
|
336
337
|
if (Array.isArray(userIdProperty)) {
|
|
337
338
|
return userIdProperty.includes(session.userId);
|
|
@@ -43,4 +43,10 @@ export class JwtCredentialsDto extends OmitClass(JwtCredentials, ['id', 'userId'
|
|
|
43
43
|
/**
|
|
44
44
|
* The data for creating new jwt credentials.
|
|
45
45
|
*/
|
|
46
|
-
export class JwtCredentialsCreateData extends OmitClass(JwtCredentials, ['id']) {
|
|
46
|
+
export class JwtCredentialsCreateData extends OmitClass(JwtCredentials, ['id', 'password']) {
|
|
47
|
+
/**
|
|
48
|
+
* The password.
|
|
49
|
+
*/
|
|
50
|
+
@Property.string({ hash: true })
|
|
51
|
+
password!: string;
|
|
52
|
+
}
|
|
@@ -14,6 +14,7 @@ import { JwtUtilities } from './jwt.utilities';
|
|
|
14
14
|
import { ZibriApplication } from '../../../application';
|
|
15
15
|
import { HttpRequestContext } from '../../../context/request/http-request.context';
|
|
16
16
|
import { WebsocketRequestContext } from '../../../context/request/websocket-request.context';
|
|
17
|
+
import { RepositoryTypeForEntity } from '../../../data-source/data-sources/data-source.interface';
|
|
17
18
|
import { Repository } from '../../../data-source/repository';
|
|
18
19
|
import { Transaction } from '../../../data-source/transaction/transaction.model';
|
|
19
20
|
import { InjectRepository, repositoryTokenFor } from '../../../di/decorators/inject-repository.decorator';
|
|
@@ -362,12 +363,12 @@ implements AuthStrategyInterface<
|
|
|
362
363
|
return false;
|
|
363
364
|
}
|
|
364
365
|
try {
|
|
365
|
-
const repo:
|
|
366
|
+
const repo: RepositoryTypeForEntity<InstanceType<TargetEntity>> = inject(repositoryTokenFor(targetEntity));
|
|
366
367
|
const targetId: string | undefined = context.request.params?.[targetIdParamKey];
|
|
367
368
|
if (targetId == undefined) {
|
|
368
369
|
throw new Error(`Could not find the target id specified as path param "${targetId}"`);
|
|
369
370
|
}
|
|
370
|
-
const foundTarget: InstanceType<TargetEntity> = await repo.findById(targetId)
|
|
371
|
+
const foundTarget: InstanceType<TargetEntity> = await repo.findById(targetId) as InstanceType<TargetEntity>;
|
|
371
372
|
const userIdProperty: unknown = foundTarget[targetUserIdKey];
|
|
372
373
|
if (Array.isArray(userIdProperty)) {
|
|
373
374
|
return userIdProperty.includes(jwtData.payload.id);
|
|
@@ -419,7 +420,8 @@ implements AuthStrategyInterface<
|
|
|
419
420
|
|
|
420
421
|
return await JwtUtilities.sign(payload, this.refreshTokenSecret, {
|
|
421
422
|
expiresIn: this.refreshTokenExpiresInMs / Ms.SECOND,
|
|
422
|
-
issuer: GlobalRegistry.getAppData('name')
|
|
423
|
+
issuer: GlobalRegistry.getAppData('name'),
|
|
424
|
+
jwtid: UUIDUtilities.generate()
|
|
423
425
|
});
|
|
424
426
|
}
|
|
425
427
|
}
|
|
@@ -32,11 +32,16 @@ export class BackupResourceEntity extends BaseEntity {
|
|
|
32
32
|
/**
|
|
33
33
|
* The backup that this resource belongs to.
|
|
34
34
|
*/
|
|
35
|
-
@Property.belongsToOne({ target: () => BackupEntity, inverseSide: 'resources' })
|
|
35
|
+
@Property.belongsToOne({ target: () => BackupEntity, joinColumn: 'backupId', inverseSide: 'resources' })
|
|
36
36
|
backup!: BackupEntity;
|
|
37
|
+
/**
|
|
38
|
+
* The id of the backup that this resource belongs to.
|
|
39
|
+
*/
|
|
40
|
+
@Property.string({ format: 'uuid' })
|
|
41
|
+
backupId!: string;
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
/**
|
|
40
45
|
* The data required to create a new backup resource.
|
|
41
46
|
*/
|
|
42
|
-
export type BackupResourceEntityCreateData = OmitStrict<BackupResourceEntity, 'id' | 'completed' | 'backup' | 'size'>;
|
|
47
|
+
export type BackupResourceEntityCreateData = OmitStrict<BackupResourceEntity, 'id' | 'completed' | 'backup' | 'backupId' | 'size'>;
|
|
@@ -8,7 +8,7 @@ import { Backup } from './decorators/backup-resource.decorator';
|
|
|
8
8
|
import { FsBackupTransport } from './transports/fs.backup-transport';
|
|
9
9
|
import { defaultTestServerEntities } from '../__testing__/test-server/create-test-data-source.function';
|
|
10
10
|
import { StartedTestServer, startTestServer } from '../__testing__/test-server/start-test-server.function';
|
|
11
|
-
import { PostgresDataSource, PostgresOptions } from '../data-source/data-sources/postgres-data-source.model';
|
|
11
|
+
import { PostgresDataSource, PostgresOptions } from '../data-source/data-sources/postgres-typeorm-data-source.model';
|
|
12
12
|
import { DataSource } from '../data-source/decorators/data-source.decorator';
|
|
13
13
|
import { Repository } from '../data-source/repository';
|
|
14
14
|
import { repositoryTokenFor } from '../di/decorators/inject-repository.decorator';
|
|
@@ -7,7 +7,7 @@ import { BackupResourceEntity, BackupResourceEntityCreateData } from './backup-r
|
|
|
7
7
|
import { BackupResourceInterface } from './backup-resource.interface';
|
|
8
8
|
import { BackupCreateData, BackupServiceInterface } from './backup-service.interface';
|
|
9
9
|
import { ZibriApplication } from '../application';
|
|
10
|
-
import { PostgresDataSource } from '../data-source/data-sources/postgres-data-source.model';
|
|
10
|
+
import { PostgresDataSource } from '../data-source/data-sources/postgres-typeorm-data-source.model';
|
|
11
11
|
import { repositoryTokenFor } from '../di/decorators/inject-repository.decorator';
|
|
12
12
|
import { Inject } from '../di/decorators/inject.decorator';
|
|
13
13
|
import { Injectable } from '../di/decorators/injectable.decorator';
|