@digitaldefiance/node-express-suite 4.22.2 → 4.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +173 -407
- package/package.json +1 -5
- package/src/__tests__/fixtures/index.d.ts +1 -1
- package/src/__tests__/fixtures/index.d.ts.map +1 -1
- package/src/__tests__/fixtures/index.js +1 -2
- package/src/__tests__/fixtures/index.js.map +1 -1
- package/src/__tests__/helpers/index.d.ts +1 -3
- package/src/__tests__/helpers/index.d.ts.map +1 -1
- package/src/__tests__/helpers/index.js +1 -4
- package/src/__tests__/helpers/index.js.map +1 -1
- package/src/__tests__/index.d.ts.map +1 -1
- package/src/__tests__/index.js +1 -0
- package/src/__tests__/index.js.map +1 -1
- package/src/application.d.ts +8 -11
- package/src/application.d.ts.map +1 -1
- package/src/application.js +8 -17
- package/src/application.js.map +1 -1
- package/src/branded-responses/branded-api-responses.d.ts +10 -2
- package/src/branded-responses/branded-api-responses.d.ts.map +1 -1
- package/src/branded-responses/branded-api-responses.js +5 -0
- package/src/branded-responses/branded-api-responses.js.map +1 -1
- package/src/branded-responses/serializers.d.ts +4 -1
- package/src/branded-responses/serializers.d.ts.map +1 -1
- package/src/builders/index.d.ts +1 -1
- package/src/builders/index.d.ts.map +1 -1
- package/src/builders/index.js +1 -2
- package/src/builders/index.js.map +1 -1
- package/src/controllers/base.d.ts +5 -18
- package/src/controllers/base.d.ts.map +1 -1
- package/src/controllers/base.js +7 -62
- package/src/controllers/base.js.map +1 -1
- package/src/controllers/index.d.ts +1 -1
- package/src/controllers/index.d.ts.map +1 -1
- package/src/controllers/index.js +2 -1
- package/src/controllers/index.js.map +1 -1
- package/src/controllers/openapi.d.ts +3 -3
- package/src/controllers/openapi.d.ts.map +1 -1
- package/src/controllers/openapi.js.map +1 -1
- package/src/enumerations/index.d.ts +0 -2
- package/src/enumerations/index.d.ts.map +1 -1
- package/src/enumerations/index.js +0 -2
- package/src/enumerations/index.js.map +1 -1
- package/src/environment.d.ts +4 -3
- package/src/environment.d.ts.map +1 -1
- package/src/environment.js +3 -1
- package/src/environment.js.map +1 -1
- package/src/errors/index.d.ts +0 -3
- package/src/errors/index.d.ts.map +1 -1
- package/src/errors/index.js +0 -3
- package/src/errors/index.js.map +1 -1
- package/src/index.d.ts +1 -8
- package/src/index.d.ts.map +1 -1
- package/src/index.js +1 -11
- package/src/index.js.map +1 -1
- package/src/interfaces/controller-config.d.ts +1 -2
- package/src/interfaces/controller-config.d.ts.map +1 -1
- package/src/interfaces/document-store.d.ts +3 -2
- package/src/interfaces/document-store.d.ts.map +1 -1
- package/src/interfaces/document-store.js +3 -3
- package/src/interfaces/document-store.js.map +1 -1
- package/src/interfaces/environment.d.ts +3 -2
- package/src/interfaces/environment.d.ts.map +1 -1
- package/src/interfaces/index.d.ts +0 -11
- package/src/interfaces/index.d.ts.map +1 -1
- package/src/interfaces/index.js +0 -11
- package/src/interfaces/index.js.map +1 -1
- package/src/plugins/database-plugin.d.ts +12 -0
- package/src/plugins/database-plugin.d.ts.map +1 -1
- package/src/plugins/index.d.ts +0 -1
- package/src/plugins/index.d.ts.map +1 -1
- package/src/plugins/index.js +0 -1
- package/src/plugins/index.js.map +1 -1
- package/src/routers/index.d.ts +0 -1
- package/src/routers/index.d.ts.map +1 -1
- package/src/routers/index.js +0 -1
- package/src/routers/index.js.map +1 -1
- package/src/services/base.d.ts +10 -13
- package/src/services/base.d.ts.map +1 -1
- package/src/services/base.js +7 -21
- package/src/services/base.js.map +1 -1
- package/src/services/index.d.ts +0 -15
- package/src/services/index.d.ts.map +1 -1
- package/src/services/index.js +0 -15
- package/src/services/index.js.map +1 -1
- package/src/testing.d.ts +1 -1
- package/src/testing.d.ts.map +1 -1
- package/src/testing.js +1 -1
- package/src/testing.js.map +1 -1
- package/src/types.d.ts +6 -17
- package/src/types.d.ts.map +1 -1
- package/src/types.js.map +1 -1
- package/src/utils.d.ts +5 -34
- package/src/utils.d.ts.map +1 -1
- package/src/utils.js +24 -165
- package/src/utils.js.map +1 -1
- package/src/__tests__/fixtures/model-mocks.mock.d.ts +0 -12
- package/src/__tests__/fixtures/model-mocks.mock.d.ts.map +0 -1
- package/src/__tests__/fixtures/model-mocks.mock.js +0 -102
- package/src/__tests__/fixtures/model-mocks.mock.js.map +0 -1
- package/src/__tests__/helpers/application.mock.d.ts +0 -8
- package/src/__tests__/helpers/application.mock.d.ts.map +0 -1
- package/src/__tests__/helpers/application.mock.js +0 -85
- package/src/__tests__/helpers/application.mock.js.map +0 -1
- package/src/__tests__/helpers/setup-test-env.d.ts +0 -13
- package/src/__tests__/helpers/setup-test-env.d.ts.map +0 -1
- package/src/__tests__/helpers/setup-test-env.js +0 -133
- package/src/__tests__/helpers/setup-test-env.js.map +0 -1
- package/src/builders/application-builder.d.ts +0 -53
- package/src/builders/application-builder.d.ts.map +0 -1
- package/src/builders/application-builder.js +0 -91
- package/src/builders/application-builder.js.map +0 -1
- package/src/controllers/user.d.ts +0 -66
- package/src/controllers/user.d.ts.map +0 -1
- package/src/controllers/user.js +0 -949
- package/src/controllers/user.js.map +0 -1
- package/src/documents/base.d.ts +0 -15
- package/src/documents/base.d.ts.map +0 -1
- package/src/documents/base.js +0 -8
- package/src/documents/base.js.map +0 -1
- package/src/documents/email-token.d.ts +0 -15
- package/src/documents/email-token.d.ts.map +0 -1
- package/src/documents/email-token.js +0 -8
- package/src/documents/email-token.js.map +0 -1
- package/src/documents/index.d.ts +0 -8
- package/src/documents/index.d.ts.map +0 -1
- package/src/documents/index.js +0 -3
- package/src/documents/index.js.map +0 -1
- package/src/documents/mnemonic.d.ts +0 -16
- package/src/documents/mnemonic.d.ts.map +0 -1
- package/src/documents/mnemonic.js +0 -8
- package/src/documents/mnemonic.js.map +0 -1
- package/src/documents/role.d.ts +0 -15
- package/src/documents/role.d.ts.map +0 -1
- package/src/documents/role.js +0 -8
- package/src/documents/role.js.map +0 -1
- package/src/documents/used-direct-login-token.d.ts +0 -16
- package/src/documents/used-direct-login-token.d.ts.map +0 -1
- package/src/documents/used-direct-login-token.js +0 -8
- package/src/documents/used-direct-login-token.js.map +0 -1
- package/src/documents/user-role.d.ts +0 -16
- package/src/documents/user-role.d.ts.map +0 -1
- package/src/documents/user-role.js +0 -8
- package/src/documents/user-role.js.map +0 -1
- package/src/documents/user.d.ts +0 -16
- package/src/documents/user.d.ts.map +0 -1
- package/src/documents/user.js +0 -8
- package/src/documents/user.js.map +0 -1
- package/src/enumerations/base-model-name.d.ts +0 -43
- package/src/enumerations/base-model-name.d.ts.map +0 -1
- package/src/enumerations/base-model-name.js +0 -39
- package/src/enumerations/base-model-name.js.map +0 -1
- package/src/enumerations/schema-collection.d.ts +0 -39
- package/src/enumerations/schema-collection.d.ts.map +0 -1
- package/src/enumerations/schema-collection.js +0 -43
- package/src/enumerations/schema-collection.js.map +0 -1
- package/src/errors/invalid-model.d.ts +0 -18
- package/src/errors/invalid-model.d.ts.map +0 -1
- package/src/errors/invalid-model.js +0 -26
- package/src/errors/invalid-model.js.map +0 -1
- package/src/errors/model-not-registered.d.ts +0 -18
- package/src/errors/model-not-registered.d.ts.map +0 -1
- package/src/errors/model-not-registered.js +0 -26
- package/src/errors/model-not-registered.js.map +0 -1
- package/src/errors/mongoose-validation.d.ts +0 -28
- package/src/errors/mongoose-validation.d.ts.map +0 -1
- package/src/errors/mongoose-validation.js +0 -33
- package/src/errors/mongoose-validation.js.map +0 -1
- package/src/interfaces/api-mongo-validation-error-response.d.ts +0 -16
- package/src/interfaces/api-mongo-validation-error-response.d.ts.map +0 -1
- package/src/interfaces/api-mongo-validation-error-response.js +0 -8
- package/src/interfaces/api-mongo-validation-error-response.js.map +0 -1
- package/src/interfaces/database-init-result-tx.d.ts +0 -27
- package/src/interfaces/database-init-result-tx.d.ts.map +0 -1
- package/src/interfaces/database-init-result-tx.js +0 -3
- package/src/interfaces/database-init-result-tx.js.map +0 -1
- package/src/interfaces/db-init-result.d.ts +0 -16
- package/src/interfaces/db-init-result.d.ts.map +0 -1
- package/src/interfaces/db-init-result.js +0 -8
- package/src/interfaces/db-init-result.js.map +0 -1
- package/src/interfaces/discriminator-collections.d.ts +0 -17
- package/src/interfaces/discriminator-collections.d.ts.map +0 -1
- package/src/interfaces/discriminator-collections.js +0 -8
- package/src/interfaces/discriminator-collections.js.map +0 -1
- package/src/interfaces/environment-mongo.d.ts +0 -86
- package/src/interfaces/environment-mongo.d.ts.map +0 -1
- package/src/interfaces/environment-mongo.js +0 -8
- package/src/interfaces/environment-mongo.js.map +0 -1
- package/src/interfaces/models/email-token.d.ts +0 -12
- package/src/interfaces/models/email-token.d.ts.map +0 -1
- package/src/interfaces/models/email-token.js +0 -8
- package/src/interfaces/models/email-token.js.map +0 -1
- package/src/interfaces/models/index.d.ts +0 -8
- package/src/interfaces/models/index.d.ts.map +0 -1
- package/src/interfaces/models/index.js +0 -11
- package/src/interfaces/models/index.js.map +0 -1
- package/src/interfaces/models/mnemonic.d.ts +0 -13
- package/src/interfaces/models/mnemonic.d.ts.map +0 -1
- package/src/interfaces/models/mnemonic.js +0 -8
- package/src/interfaces/models/mnemonic.js.map +0 -1
- package/src/interfaces/models/role.d.ts +0 -12
- package/src/interfaces/models/role.d.ts.map +0 -1
- package/src/interfaces/models/role.js +0 -8
- package/src/interfaces/models/role.js.map +0 -1
- package/src/interfaces/models/token-role.d.ts +0 -19
- package/src/interfaces/models/token-role.d.ts.map +0 -1
- package/src/interfaces/models/token-role.js +0 -8
- package/src/interfaces/models/token-role.js.map +0 -1
- package/src/interfaces/models/used-direct-login-token.d.ts +0 -19
- package/src/interfaces/models/used-direct-login-token.d.ts.map +0 -1
- package/src/interfaces/models/used-direct-login-token.js +0 -8
- package/src/interfaces/models/used-direct-login-token.js.map +0 -1
- package/src/interfaces/models/user-role.d.ts +0 -19
- package/src/interfaces/models/user-role.d.ts.map +0 -1
- package/src/interfaces/models/user-role.js +0 -8
- package/src/interfaces/models/user-role.js.map +0 -1
- package/src/interfaces/models/user.d.ts +0 -21
- package/src/interfaces/models/user.d.ts.map +0 -1
- package/src/interfaces/models/user.js +0 -8
- package/src/interfaces/models/user.js.map +0 -1
- package/src/interfaces/mongo-application.d.ts +0 -35
- package/src/interfaces/mongo-application.d.ts.map +0 -1
- package/src/interfaces/mongo-application.js +0 -10
- package/src/interfaces/mongo-application.js.map +0 -1
- package/src/interfaces/mongo-errors.d.ts +0 -13
- package/src/interfaces/mongo-errors.d.ts.map +0 -1
- package/src/interfaces/mongo-errors.js +0 -8
- package/src/interfaces/mongo-errors.js.map +0 -1
- package/src/interfaces/mongoose-document-store.d.ts +0 -42
- package/src/interfaces/mongoose-document-store.d.ts.map +0 -1
- package/src/interfaces/mongoose-document-store.js +0 -10
- package/src/interfaces/mongoose-document-store.js.map +0 -1
- package/src/interfaces/schema.d.ts +0 -37
- package/src/interfaces/schema.d.ts.map +0 -1
- package/src/interfaces/schema.js +0 -8
- package/src/interfaces/schema.js.map +0 -1
- package/src/interfaces/server-init-result.d.ts +0 -45
- package/src/interfaces/server-init-result.d.ts.map +0 -1
- package/src/interfaces/server-init-result.js +0 -8
- package/src/interfaces/server-init-result.js.map +0 -1
- package/src/interfaces/test-environment.d.ts +0 -22
- package/src/interfaces/test-environment.d.ts.map +0 -1
- package/src/interfaces/test-environment.js +0 -8
- package/src/interfaces/test-environment.js.map +0 -1
- package/src/model-registry.d.ts +0 -79
- package/src/model-registry.d.ts.map +0 -1
- package/src/model-registry.js +0 -97
- package/src/model-registry.js.map +0 -1
- package/src/models/email-token.d.ts +0 -24
- package/src/models/email-token.d.ts.map +0 -1
- package/src/models/email-token.js +0 -16
- package/src/models/email-token.js.map +0 -1
- package/src/models/index.d.ts +0 -7
- package/src/models/index.d.ts.map +0 -1
- package/src/models/index.js +0 -10
- package/src/models/index.js.map +0 -1
- package/src/models/mnemonic.d.ts +0 -24
- package/src/models/mnemonic.d.ts.map +0 -1
- package/src/models/mnemonic.js +0 -27
- package/src/models/mnemonic.js.map +0 -1
- package/src/models/role.d.ts +0 -24
- package/src/models/role.d.ts.map +0 -1
- package/src/models/role.js +0 -27
- package/src/models/role.js.map +0 -1
- package/src/models/used-direct-login-token.d.ts +0 -24
- package/src/models/used-direct-login-token.d.ts.map +0 -1
- package/src/models/used-direct-login-token.js +0 -16
- package/src/models/used-direct-login-token.js.map +0 -1
- package/src/models/user-role.d.ts +0 -23
- package/src/models/user-role.d.ts.map +0 -1
- package/src/models/user-role.js +0 -26
- package/src/models/user-role.js.map +0 -1
- package/src/models/user.d.ts +0 -24
- package/src/models/user.d.ts.map +0 -1
- package/src/models/user.js +0 -27
- package/src/models/user.js.map +0 -1
- package/src/mongo-application-concrete.d.ts +0 -32
- package/src/mongo-application-concrete.d.ts.map +0 -1
- package/src/mongo-application-concrete.js +0 -49
- package/src/mongo-application-concrete.js.map +0 -1
- package/src/plugins/mongo-database-plugin.d.ts +0 -115
- package/src/plugins/mongo-database-plugin.d.ts.map +0 -1
- package/src/plugins/mongo-database-plugin.js +0 -234
- package/src/plugins/mongo-database-plugin.js.map +0 -1
- package/src/routers/api.d.ts +0 -60
- package/src/routers/api.d.ts.map +0 -1
- package/src/routers/api.js +0 -116
- package/src/routers/api.js.map +0 -1
- package/src/schemas/email-token.d.ts +0 -65
- package/src/schemas/email-token.d.ts.map +0 -1
- package/src/schemas/email-token.js +0 -68
- package/src/schemas/email-token.js.map +0 -1
- package/src/schemas/index.d.ts +0 -8
- package/src/schemas/index.d.ts.map +0 -1
- package/src/schemas/index.js +0 -11
- package/src/schemas/index.js.map +0 -1
- package/src/schemas/mnemonic.d.ts +0 -37
- package/src/schemas/mnemonic.d.ts.map +0 -1
- package/src/schemas/mnemonic.js +0 -41
- package/src/schemas/mnemonic.js.map +0 -1
- package/src/schemas/role.d.ts +0 -57
- package/src/schemas/role.d.ts.map +0 -1
- package/src/schemas/role.js +0 -102
- package/src/schemas/role.js.map +0 -1
- package/src/schemas/schema.d.ts +0 -62
- package/src/schemas/schema.d.ts.map +0 -1
- package/src/schemas/schema.js +0 -81
- package/src/schemas/schema.js.map +0 -1
- package/src/schemas/used-direct-login-token.d.ts +0 -49
- package/src/schemas/used-direct-login-token.d.ts.map +0 -1
- package/src/schemas/used-direct-login-token.js +0 -35
- package/src/schemas/used-direct-login-token.js.map +0 -1
- package/src/schemas/user-role.d.ts +0 -52
- package/src/schemas/user-role.d.ts.map +0 -1
- package/src/schemas/user-role.js +0 -67
- package/src/schemas/user-role.js.map +0 -1
- package/src/schemas/user.d.ts +0 -43
- package/src/schemas/user.d.ts.map +0 -1
- package/src/schemas/user.js +0 -214
- package/src/schemas/user.js.map +0 -1
- package/src/services/backup-code.d.ts +0 -120
- package/src/services/backup-code.d.ts.map +0 -1
- package/src/services/backup-code.js +0 -323
- package/src/services/backup-code.js.map +0 -1
- package/src/services/database-initialization.d.ts +0 -138
- package/src/services/database-initialization.d.ts.map +0 -1
- package/src/services/database-initialization.js +0 -913
- package/src/services/database-initialization.js.map +0 -1
- package/src/services/db-init-cache.d.ts +0 -18
- package/src/services/db-init-cache.d.ts.map +0 -1
- package/src/services/db-init-cache.js +0 -7
- package/src/services/db-init-cache.js.map +0 -1
- package/src/services/direct-login-token.d.ts +0 -28
- package/src/services/direct-login-token.d.ts.map +0 -1
- package/src/services/direct-login-token.js +0 -62
- package/src/services/direct-login-token.js.map +0 -1
- package/src/services/jwt.d.ts +0 -45
- package/src/services/jwt.d.ts.map +0 -1
- package/src/services/jwt.js +0 -105
- package/src/services/jwt.js.map +0 -1
- package/src/services/mnemonic.d.ts +0 -68
- package/src/services/mnemonic.d.ts.map +0 -1
- package/src/services/mnemonic.js +0 -120
- package/src/services/mnemonic.js.map +0 -1
- package/src/services/mongo-authentication-provider.d.ts +0 -27
- package/src/services/mongo-authentication-provider.d.ts.map +0 -1
- package/src/services/mongo-authentication-provider.js +0 -84
- package/src/services/mongo-authentication-provider.js.map +0 -1
- package/src/services/mongo-backup-code-store.d.ts +0 -40
- package/src/services/mongo-backup-code-store.d.ts.map +0 -1
- package/src/services/mongo-backup-code-store.js +0 -104
- package/src/services/mongo-backup-code-store.js.map +0 -1
- package/src/services/mongo-base.d.ts +0 -24
- package/src/services/mongo-base.d.ts.map +0 -1
- package/src/services/mongo-base.js +0 -28
- package/src/services/mongo-base.js.map +0 -1
- package/src/services/mongoose-collection.d.ts +0 -52
- package/src/services/mongoose-collection.d.ts.map +0 -1
- package/src/services/mongoose-collection.js +0 -326
- package/src/services/mongoose-collection.js.map +0 -1
- package/src/services/mongoose-database.d.ts +0 -64
- package/src/services/mongoose-database.d.ts.map +0 -1
- package/src/services/mongoose-database.js +0 -121
- package/src/services/mongoose-database.js.map +0 -1
- package/src/services/mongoose-document-store.d.ts +0 -109
- package/src/services/mongoose-document-store.d.ts.map +0 -1
- package/src/services/mongoose-document-store.js +0 -264
- package/src/services/mongoose-document-store.js.map +0 -1
- package/src/services/mongoose-session-adapter.d.ts +0 -39
- package/src/services/mongoose-session-adapter.d.ts.map +0 -1
- package/src/services/mongoose-session-adapter.js +0 -63
- package/src/services/mongoose-session-adapter.js.map +0 -1
- package/src/services/request-user.d.ts +0 -45
- package/src/services/request-user.d.ts.map +0 -1
- package/src/services/request-user.js +0 -90
- package/src/services/request-user.js.map +0 -1
- package/src/services/role.d.ts +0 -97
- package/src/services/role.d.ts.map +0 -1
- package/src/services/role.js +0 -289
- package/src/services/role.js.map +0 -1
- package/src/services/user.d.ts +0 -368
- package/src/services/user.d.ts.map +0 -1
- package/src/services/user.js +0 -1495
- package/src/services/user.js.map +0 -1
- package/src/transactions/index.d.ts +0 -2
- package/src/transactions/index.d.ts.map +0 -1
- package/src/transactions/index.js +0 -5
- package/src/transactions/index.js.map +0 -1
- package/src/transactions/transaction-manager.d.ts +0 -37
- package/src/transactions/transaction-manager.d.ts.map +0 -1
- package/src/transactions/transaction-manager.js +0 -50
- package/src/transactions/transaction-manager.js.map +0 -1
- package/src/types/mongoose-helpers.d.ts +0 -16
- package/src/types/mongoose-helpers.d.ts.map +0 -1
- package/src/types/mongoose-helpers.js +0 -8
- package/src/types/mongoose-helpers.js.map +0 -1
- package/src/utils/default-mongo-uri-validator.d.ts +0 -15
- package/src/utils/default-mongo-uri-validator.d.ts.map +0 -1
- package/src/utils/default-mongo-uri-validator.js +0 -46
- package/src/utils/default-mongo-uri-validator.js.map +0 -1
package/src/schemas/user.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview User schema factory for MongoDB with comprehensive validation.
|
|
4
|
-
* Creates schema for user management with authentication and preferences.
|
|
5
|
-
* @module schemas/user
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.UserSchema = void 0;
|
|
9
|
-
exports.createUserSchema = createUserSchema;
|
|
10
|
-
const tslib_1 = require("tslib");
|
|
11
|
-
const i18n_lib_1 = require("@digitaldefiance/i18n-lib");
|
|
12
|
-
const mongoose_types_1 = require("@digitaldefiance/mongoose-types");
|
|
13
|
-
const suite_core_lib_1 = require("@digitaldefiance/suite-core-lib");
|
|
14
|
-
const currency_codes_1 = require("currency-codes");
|
|
15
|
-
const validator_1 = tslib_1.__importDefault(require("validator"));
|
|
16
|
-
const constants_1 = require("../constants");
|
|
17
|
-
const enumerations_1 = require("../enumerations");
|
|
18
|
-
/**
|
|
19
|
-
* Creates a user schema with custom or default constants.
|
|
20
|
-
* Includes validation for username, email, timezone, currency, and language.
|
|
21
|
-
* @template T - Constants type extending IConstants
|
|
22
|
-
* @param {Function} [usernameValidationMessage] - Custom username validation message
|
|
23
|
-
* @param {Function} [emailValidationMessage] - Custom email validation message
|
|
24
|
-
* @param {Function} [timezoneValidationMessage] - Custom timezone validation message
|
|
25
|
-
* @param {Function} [currencyValidationMessage] - Custom currency validation message
|
|
26
|
-
* @param {readonly string[]} [supportedLanguages] - Supported language codes
|
|
27
|
-
* @param {any} idType - ID type for references (defaults to ObjectId)
|
|
28
|
-
* @param {T} constants - Constants for validation (defaults to AppConstants)
|
|
29
|
-
* @returns {Schema} Configured user schema with timestamps
|
|
30
|
-
*/
|
|
31
|
-
function createUserSchema(usernameValidationMessage, emailValidationMessage, timezoneValidationMessage, currencyValidationMessage, supportedLanguages, idType = mongoose_types_1.Schema.Types.ObjectId, constants = constants_1.LocalhostConstants) {
|
|
32
|
-
const definition = {
|
|
33
|
-
/**
|
|
34
|
-
* The unique identifier for the user
|
|
35
|
-
*/
|
|
36
|
-
username: {
|
|
37
|
-
type: String,
|
|
38
|
-
required: true,
|
|
39
|
-
unique: true,
|
|
40
|
-
validate: {
|
|
41
|
-
validator: (v) => constants.UsernameRegex.test(v),
|
|
42
|
-
message: usernameValidationMessage ||
|
|
43
|
-
(() => (0, suite_core_lib_1.getSuiteCoreTranslation)(suite_core_lib_1.SuiteCoreStringKey.Validation_UsernameRegexErrorTemplate)),
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
/**
|
|
47
|
-
* The email address for the user
|
|
48
|
-
*/
|
|
49
|
-
email: {
|
|
50
|
-
type: String,
|
|
51
|
-
required: true,
|
|
52
|
-
unique: true,
|
|
53
|
-
validate: {
|
|
54
|
-
validator: (v) => validator_1.default.isEmail(v),
|
|
55
|
-
message: emailValidationMessage ||
|
|
56
|
-
((props) => (0, suite_core_lib_1.getSuiteCoreTranslation)(suite_core_lib_1.SuiteCoreStringKey.Error_InvalidEmailTemplate, { email: props.value })),
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
/**
|
|
60
|
-
* The user's public key, stored in hex format.
|
|
61
|
-
*/
|
|
62
|
-
publicKey: {
|
|
63
|
-
type: String,
|
|
64
|
-
required: true,
|
|
65
|
-
unique: true,
|
|
66
|
-
},
|
|
67
|
-
/**
|
|
68
|
-
* The timezone for the user
|
|
69
|
-
*/
|
|
70
|
-
timezone: {
|
|
71
|
-
type: String,
|
|
72
|
-
required: true,
|
|
73
|
-
default: 'UTC',
|
|
74
|
-
validate: {
|
|
75
|
-
validator: function (v) {
|
|
76
|
-
return (0, i18n_lib_1.isValidTimezone)(v);
|
|
77
|
-
},
|
|
78
|
-
message: timezoneValidationMessage ||
|
|
79
|
-
((props) => (0, suite_core_lib_1.getSuiteCoreTranslation)(suite_core_lib_1.SuiteCoreStringKey.Common_NotValidTimeZoneTemplate, { timezone: props.value })),
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
currency: {
|
|
83
|
-
type: String,
|
|
84
|
-
required: true,
|
|
85
|
-
default: 'USD',
|
|
86
|
-
validate: {
|
|
87
|
-
validator: function (v) {
|
|
88
|
-
return (0, currency_codes_1.codes)().includes(v);
|
|
89
|
-
},
|
|
90
|
-
message: currencyValidationMessage ||
|
|
91
|
-
((props) => (0, suite_core_lib_1.getSuiteCoreTranslation)(suite_core_lib_1.SuiteCoreStringKey.Common_NotValidCurrencyTemplate, { currency: props.value })),
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
/**
|
|
95
|
-
* The language of the site for the user
|
|
96
|
-
*/
|
|
97
|
-
siteLanguage: {
|
|
98
|
-
type: String,
|
|
99
|
-
enum: supportedLanguages || Object.values(i18n_lib_1.LanguageCodes),
|
|
100
|
-
default: i18n_lib_1.LanguageCodes.EN_US,
|
|
101
|
-
required: true,
|
|
102
|
-
},
|
|
103
|
-
/**
|
|
104
|
-
* Whether the user prefers dark mode
|
|
105
|
-
*/
|
|
106
|
-
darkMode: {
|
|
107
|
-
type: Boolean,
|
|
108
|
-
default: false,
|
|
109
|
-
required: true,
|
|
110
|
-
},
|
|
111
|
-
/**
|
|
112
|
-
* Whether to enable direct challenge login for the user
|
|
113
|
-
*/
|
|
114
|
-
directChallenge: {
|
|
115
|
-
type: Boolean,
|
|
116
|
-
default: true,
|
|
117
|
-
required: true,
|
|
118
|
-
},
|
|
119
|
-
/**
|
|
120
|
-
* The date the user last logged in
|
|
121
|
-
*/
|
|
122
|
-
lastLogin: { type: Date, required: false },
|
|
123
|
-
/**
|
|
124
|
-
* Whether the user has verified their email address
|
|
125
|
-
*/
|
|
126
|
-
emailVerified: { type: Boolean, default: false },
|
|
127
|
-
/**
|
|
128
|
-
* The status of the user's account
|
|
129
|
-
*/
|
|
130
|
-
accountStatus: {
|
|
131
|
-
type: String,
|
|
132
|
-
enum: Object.values(suite_core_lib_1.AccountStatus),
|
|
133
|
-
default: suite_core_lib_1.AccountStatus.PendingEmailVerification,
|
|
134
|
-
},
|
|
135
|
-
/**
|
|
136
|
-
* The user who created the user.
|
|
137
|
-
*/
|
|
138
|
-
createdBy: {
|
|
139
|
-
type: idType,
|
|
140
|
-
ref: enumerations_1.BaseModelName.User,
|
|
141
|
-
required: true,
|
|
142
|
-
immutable: true,
|
|
143
|
-
},
|
|
144
|
-
/**
|
|
145
|
-
* The user who last updated the user.
|
|
146
|
-
*/
|
|
147
|
-
updatedBy: {
|
|
148
|
-
type: idType,
|
|
149
|
-
ref: enumerations_1.BaseModelName.User,
|
|
150
|
-
optional: true,
|
|
151
|
-
},
|
|
152
|
-
/**
|
|
153
|
-
* The date/time the user was deleted.
|
|
154
|
-
*/
|
|
155
|
-
deletedAt: { type: Date, optional: true },
|
|
156
|
-
/**
|
|
157
|
-
* The user who deleted the user.
|
|
158
|
-
*/
|
|
159
|
-
deletedBy: {
|
|
160
|
-
type: idType,
|
|
161
|
-
ref: enumerations_1.BaseModelName.User,
|
|
162
|
-
optional: true,
|
|
163
|
-
},
|
|
164
|
-
/**
|
|
165
|
-
* Reference to the mnemonic document
|
|
166
|
-
*/
|
|
167
|
-
mnemonicId: {
|
|
168
|
-
type: idType,
|
|
169
|
-
ref: enumerations_1.BaseModelName.Mnemonic,
|
|
170
|
-
required: false,
|
|
171
|
-
},
|
|
172
|
-
/**
|
|
173
|
-
* Copy of the mnemonic encrypted with the user's public key
|
|
174
|
-
*/
|
|
175
|
-
mnemonicRecovery: {
|
|
176
|
-
type: String,
|
|
177
|
-
required: false,
|
|
178
|
-
},
|
|
179
|
-
/**
|
|
180
|
-
* Password-wrapped ECIES private key (Option B)
|
|
181
|
-
*/
|
|
182
|
-
passwordWrappedPrivateKey: {
|
|
183
|
-
type: {
|
|
184
|
-
salt: { type: String, required: true },
|
|
185
|
-
iv: { type: String, required: true },
|
|
186
|
-
authTag: { type: String, required: true },
|
|
187
|
-
ciphertext: { type: String, required: true },
|
|
188
|
-
iterations: { type: Number, required: true },
|
|
189
|
-
},
|
|
190
|
-
required: false,
|
|
191
|
-
},
|
|
192
|
-
/**
|
|
193
|
-
* Array of backup codes to recover mnemonic/private key
|
|
194
|
-
*/
|
|
195
|
-
backupCodes: {
|
|
196
|
-
type: [
|
|
197
|
-
{
|
|
198
|
-
version: { type: String, required: true },
|
|
199
|
-
checksumSalt: { type: String, required: true },
|
|
200
|
-
checksum: { type: String, required: true },
|
|
201
|
-
encrypted: { type: String, required: true },
|
|
202
|
-
},
|
|
203
|
-
],
|
|
204
|
-
default: [],
|
|
205
|
-
},
|
|
206
|
-
};
|
|
207
|
-
return new mongoose_types_1.Schema(definition, { timestamps: true });
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Default user schema with base configuration.
|
|
211
|
-
* Pre-configured schema with standard validation and supported languages.
|
|
212
|
-
*/
|
|
213
|
-
exports.UserSchema = createUserSchema();
|
|
214
|
-
//# sourceMappingURL=user.js.map
|
package/src/schemas/user.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/schemas/user.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Backup code service for secure account recovery.
|
|
3
|
-
* Implements v1.0.0 backup code scheme with Argon2id KDF and HKDF-SHA256 checksums.
|
|
4
|
-
*
|
|
5
|
-
* Storage-agnostic: accepts an optional {@link IBackupCodeStore} for persistence.
|
|
6
|
-
* When no store is provided, falls back to direct UserDocument manipulation
|
|
7
|
-
* (backward-compatible Mongoose path).
|
|
8
|
-
*
|
|
9
|
-
* @module services/backup-code
|
|
10
|
-
*/
|
|
11
|
-
import { SecureString } from '@digitaldefiance/ecies-lib';
|
|
12
|
-
import { ClientSession } from '@digitaldefiance/mongoose-types';
|
|
13
|
-
import { Member as BackendMember, ECIESService, PlatformID } from '@digitaldefiance/node-ecies-lib';
|
|
14
|
-
import { IBackupCode, ITokenRole } from '@digitaldefiance/suite-core-lib';
|
|
15
|
-
import { UserDocument } from '../documents';
|
|
16
|
-
import { IApplication } from '../interfaces/application';
|
|
17
|
-
import type { IBackupCodeStore, IBackupCodeUserRecord } from '../interfaces/backup-code-store';
|
|
18
|
-
import { BaseService } from './base';
|
|
19
|
-
import { KeyWrappingService } from './index';
|
|
20
|
-
import { RoleService } from './role';
|
|
21
|
-
/**
|
|
22
|
-
* Service for backup code generation, validation, and key recovery.
|
|
23
|
-
* Implements secure backup code scheme with constant-time validation and key wrapping.
|
|
24
|
-
*
|
|
25
|
-
* Storage is abstracted via {@link IBackupCodeStore}. When a store is provided,
|
|
26
|
-
* all persistence goes through the store interface. When omitted, the service
|
|
27
|
-
* falls back to direct UserDocument manipulation for backward compatibility
|
|
28
|
-
* with existing Mongoose-based consumers.
|
|
29
|
-
*
|
|
30
|
-
* @template TID - Platform ID type (defaults to Buffer)
|
|
31
|
-
* @template TDate - Date type (defaults to Date)
|
|
32
|
-
* @template TTokenRole - Token role interface type
|
|
33
|
-
* @template TApplication - Application interface type
|
|
34
|
-
* @extends {BaseService<TID>}
|
|
35
|
-
*/
|
|
36
|
-
export declare class BackupCodeService<TID extends PlatformID = Buffer, TDate extends Date = Date, TTokenRole extends ITokenRole<TID, TDate> = ITokenRole<TID, TDate>, TApplication extends IApplication<TID> = IApplication<TID>> extends BaseService<TID> {
|
|
37
|
-
private readonly eciesService;
|
|
38
|
-
private systemUser?;
|
|
39
|
-
private readonly keyWrappingService;
|
|
40
|
-
private readonly roleService;
|
|
41
|
-
private readonly store?;
|
|
42
|
-
/**
|
|
43
|
-
* Construct a BackupCodeService.
|
|
44
|
-
* @param application - The application instance
|
|
45
|
-
* @param eciesService - ECIES cryptographic service
|
|
46
|
-
* @param keyWrappingService - Key wrapping service for password-based key protection
|
|
47
|
-
* @param roleService - Role service for member type resolution
|
|
48
|
-
* @param store - Optional storage adapter. When omitted, falls back to direct
|
|
49
|
-
* UserDocument manipulation (Mongoose). Provide an IBackupCodeStore implementation
|
|
50
|
-
* for non-Mongoose backends (e.g. BrightDB).
|
|
51
|
-
*/
|
|
52
|
-
constructor(application: TApplication, eciesService: ECIESService<TID>, keyWrappingService: KeyWrappingService, roleService: RoleService<TID, TDate, TTokenRole>, store?: IBackupCodeStore<TID>);
|
|
53
|
-
/**
|
|
54
|
-
* Get the lazily-initialized system user for key wrapping/unwrapping.
|
|
55
|
-
*/
|
|
56
|
-
private getSystemUser;
|
|
57
|
-
/**
|
|
58
|
-
* Forcibly set the system user (for database initialization)
|
|
59
|
-
* @param user
|
|
60
|
-
*/
|
|
61
|
-
setSystemUser(user: BackendMember<TID>): void;
|
|
62
|
-
/**
|
|
63
|
-
* v1: Consume (validate and remove) a backup code via constant-time checksum match.
|
|
64
|
-
*/
|
|
65
|
-
useBackupCodeV1(encryptedBackupCodes: Array<IBackupCode>, backupCode: string): {
|
|
66
|
-
newCodesArray: Array<IBackupCode>;
|
|
67
|
-
code: IBackupCode;
|
|
68
|
-
};
|
|
69
|
-
/**
|
|
70
|
-
* Consume a backup code by first detecting the version and then dispatching to the appropriate handler.
|
|
71
|
-
*/
|
|
72
|
-
useBackupCode(encryptedBackupCodes: Array<IBackupCode>, backupCode: string): {
|
|
73
|
-
newCodesArray: Array<IBackupCode>;
|
|
74
|
-
code: IBackupCode;
|
|
75
|
-
};
|
|
76
|
-
/**
|
|
77
|
-
* Recover a user's private key using a backup code.
|
|
78
|
-
* Storage-agnostic: uses IBackupCodeStore when available, otherwise
|
|
79
|
-
* falls back to the legacy UserDocument path.
|
|
80
|
-
*
|
|
81
|
-
* @param userOrId - Either a UserDocument (legacy) or a user ID (store-based)
|
|
82
|
-
* @param backupCode - The plaintext backup code
|
|
83
|
-
* @param newPassword - Optional new password to re-wrap the private key
|
|
84
|
-
* @param session - Optional database session for transactional consistency
|
|
85
|
-
*/
|
|
86
|
-
recoverKeyWithBackupCodeV1(userOrId: UserDocument<string, TID> | TID, backupCode: string, newPassword?: SecureString, session?: ClientSession): Promise<{
|
|
87
|
-
userDoc?: UserDocument<string, TID>;
|
|
88
|
-
userRecord?: IBackupCodeUserRecord<TID>;
|
|
89
|
-
user: BackendMember<TID>;
|
|
90
|
-
codeCount: number;
|
|
91
|
-
}>;
|
|
92
|
-
/**
|
|
93
|
-
* Recover a user's private key using a backup code (version-dispatched).
|
|
94
|
-
* Accepts either a UserDocument (legacy) or a user ID (store-based).
|
|
95
|
-
*/
|
|
96
|
-
recoverKeyWithBackupCode(userOrId: UserDocument<string, TID> | TID, backupCode: string, newPassword?: SecureString, session?: ClientSession): Promise<{
|
|
97
|
-
userDoc?: UserDocument<string, TID>;
|
|
98
|
-
userRecord?: IBackupCodeUserRecord<TID>;
|
|
99
|
-
user: BackendMember<TID>;
|
|
100
|
-
codeCount: number;
|
|
101
|
-
}>;
|
|
102
|
-
/**
|
|
103
|
-
* Rewrap system-wrapped AEAD blobs from old system key to new one.
|
|
104
|
-
*
|
|
105
|
-
* When a store is provided, uses the store's fetchBatch/updateUserRecord.
|
|
106
|
-
* Otherwise falls back to the legacy callback-based approach.
|
|
107
|
-
*/
|
|
108
|
-
rewrapAllUsersBackupCodes(fetchBatchOrOldSystem: ((afterId?: string, limit?: number) => Promise<UserDocument<string, TID>[]>) | BackendMember, saveUserOrNewSystem: ((user: UserDocument<string, TID>) => Promise<void>) | BackendMember, oldSystemOrOptions?: BackendMember | {
|
|
109
|
-
batchSize?: number;
|
|
110
|
-
onProgress?: (count: number) => void;
|
|
111
|
-
}, newSystemOrUndefined?: BackendMember, options?: {
|
|
112
|
-
batchSize?: number;
|
|
113
|
-
onProgress?: (count: number) => void;
|
|
114
|
-
}): Promise<number>;
|
|
115
|
-
private _recoverViaStore;
|
|
116
|
-
private _recoverViaUserDoc;
|
|
117
|
-
private _rewrapViaStore;
|
|
118
|
-
private _rewrapViaCallbacks;
|
|
119
|
-
}
|
|
120
|
-
//# sourceMappingURL=backup-code.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"backup-code.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/services/backup-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Backup code service for secure account recovery.
|
|
4
|
-
* Implements v1.0.0 backup code scheme with Argon2id KDF and HKDF-SHA256 checksums.
|
|
5
|
-
*
|
|
6
|
-
* Storage-agnostic: accepts an optional {@link IBackupCodeStore} for persistence.
|
|
7
|
-
* When no store is provided, falls back to direct UserDocument manipulation
|
|
8
|
-
* (backward-compatible Mongoose path).
|
|
9
|
-
*
|
|
10
|
-
* @module services/backup-code
|
|
11
|
-
*/
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.BackupCodeService = void 0;
|
|
14
|
-
const ecies_lib_1 = require("@digitaldefiance/ecies-lib");
|
|
15
|
-
const node_ecies_lib_1 = require("@digitaldefiance/node-ecies-lib");
|
|
16
|
-
const suite_core_lib_1 = require("@digitaldefiance/suite-core-lib");
|
|
17
|
-
const crypto_1 = require("crypto");
|
|
18
|
-
const backup_code_1 = require("../backup-code");
|
|
19
|
-
const constants_1 = require("../constants");
|
|
20
|
-
const invalid_backup_code_version_1 = require("../errors/invalid-backup-code-version");
|
|
21
|
-
const base_1 = require("./base");
|
|
22
|
-
const symmetric_1 = require("./symmetric");
|
|
23
|
-
const system_user_1 = require("./system-user");
|
|
24
|
-
/**
|
|
25
|
-
* Service for backup code generation, validation, and key recovery.
|
|
26
|
-
* Implements secure backup code scheme with constant-time validation and key wrapping.
|
|
27
|
-
*
|
|
28
|
-
* Storage is abstracted via {@link IBackupCodeStore}. When a store is provided,
|
|
29
|
-
* all persistence goes through the store interface. When omitted, the service
|
|
30
|
-
* falls back to direct UserDocument manipulation for backward compatibility
|
|
31
|
-
* with existing Mongoose-based consumers.
|
|
32
|
-
*
|
|
33
|
-
* @template TID - Platform ID type (defaults to Buffer)
|
|
34
|
-
* @template TDate - Date type (defaults to Date)
|
|
35
|
-
* @template TTokenRole - Token role interface type
|
|
36
|
-
* @template TApplication - Application interface type
|
|
37
|
-
* @extends {BaseService<TID>}
|
|
38
|
-
*/
|
|
39
|
-
class BackupCodeService extends base_1.BaseService {
|
|
40
|
-
eciesService;
|
|
41
|
-
systemUser;
|
|
42
|
-
keyWrappingService;
|
|
43
|
-
roleService;
|
|
44
|
-
store;
|
|
45
|
-
/**
|
|
46
|
-
* Construct a BackupCodeService.
|
|
47
|
-
* @param application - The application instance
|
|
48
|
-
* @param eciesService - ECIES cryptographic service
|
|
49
|
-
* @param keyWrappingService - Key wrapping service for password-based key protection
|
|
50
|
-
* @param roleService - Role service for member type resolution
|
|
51
|
-
* @param store - Optional storage adapter. When omitted, falls back to direct
|
|
52
|
-
* UserDocument manipulation (Mongoose). Provide an IBackupCodeStore implementation
|
|
53
|
-
* for non-Mongoose backends (e.g. BrightDB).
|
|
54
|
-
*/
|
|
55
|
-
constructor(application, eciesService, keyWrappingService, roleService, store) {
|
|
56
|
-
super(application);
|
|
57
|
-
this.eciesService = eciesService;
|
|
58
|
-
this.keyWrappingService = keyWrappingService;
|
|
59
|
-
this.roleService = roleService;
|
|
60
|
-
this.store = store;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Get the lazily-initialized system user for key wrapping/unwrapping.
|
|
64
|
-
*/
|
|
65
|
-
getSystemUser() {
|
|
66
|
-
if (!this.systemUser) {
|
|
67
|
-
this.systemUser = system_user_1.SystemUserService.getSystemUser(this.application.environment, this.application.constants);
|
|
68
|
-
}
|
|
69
|
-
return this.systemUser;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Forcibly set the system user (for database initialization)
|
|
73
|
-
* @param user
|
|
74
|
-
*/
|
|
75
|
-
setSystemUser(user) {
|
|
76
|
-
this.systemUser = user;
|
|
77
|
-
}
|
|
78
|
-
// ── Pure crypto operations (no storage dependency) ─────────────────────
|
|
79
|
-
/**
|
|
80
|
-
* v1: Consume (validate and remove) a backup code via constant-time checksum match.
|
|
81
|
-
*/
|
|
82
|
-
useBackupCodeV1(encryptedBackupCodes, backupCode) {
|
|
83
|
-
const normalizedCode = backup_code_1.BackupCode.normalizeCode(backupCode);
|
|
84
|
-
if (!constants_1.LocalhostConstants.BACKUP_CODES.NormalizedHexRegex.test(normalizedCode)) {
|
|
85
|
-
throw new suite_core_lib_1.InvalidBackupCodeError();
|
|
86
|
-
}
|
|
87
|
-
const codeBytes = Buffer.from(normalizedCode, 'utf8');
|
|
88
|
-
try {
|
|
89
|
-
for (const code of encryptedBackupCodes) {
|
|
90
|
-
if (code.version !== backup_code_1.BackupCode.BackupCodeVersion)
|
|
91
|
-
continue;
|
|
92
|
-
const checksumSalt = Buffer.from(code.checksumSalt, 'hex');
|
|
93
|
-
const expected = backup_code_1.BackupCode.hkdfSha256(codeBytes, checksumSalt, Buffer.from('backup-checksum'), 32);
|
|
94
|
-
if (code.checksum.length === expected.length * 2 &&
|
|
95
|
-
(0, crypto_1.timingSafeEqual)(Buffer.from(code.checksum, 'hex'), expected)) {
|
|
96
|
-
const checksumHex = expected.toString('hex');
|
|
97
|
-
return {
|
|
98
|
-
newCodesArray: encryptedBackupCodes.filter((c) => c.checksum !== checksumHex),
|
|
99
|
-
code,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
throw new suite_core_lib_1.InvalidBackupCodeError();
|
|
104
|
-
}
|
|
105
|
-
finally {
|
|
106
|
-
codeBytes.fill(0);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Consume a backup code by first detecting the version and then dispatching to the appropriate handler.
|
|
111
|
-
*/
|
|
112
|
-
useBackupCode(encryptedBackupCodes, backupCode) {
|
|
113
|
-
const version = backup_code_1.BackupCode.detectBackupCodeVersion(encryptedBackupCodes, backupCode);
|
|
114
|
-
switch (version) {
|
|
115
|
-
case backup_code_1.BackupCode.BackupCodeVersion:
|
|
116
|
-
return this.useBackupCodeV1(encryptedBackupCodes.filter((c) => c.version === backup_code_1.BackupCode.BackupCodeVersion), backupCode);
|
|
117
|
-
default:
|
|
118
|
-
throw new invalid_backup_code_version_1.InvalidBackupCodeVersionError(version);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
// ── Storage-agnostic recovery ──────────────────────────────────────────
|
|
122
|
-
/**
|
|
123
|
-
* Recover a user's private key using a backup code.
|
|
124
|
-
* Storage-agnostic: uses IBackupCodeStore when available, otherwise
|
|
125
|
-
* falls back to the legacy UserDocument path.
|
|
126
|
-
*
|
|
127
|
-
* @param userOrId - Either a UserDocument (legacy) or a user ID (store-based)
|
|
128
|
-
* @param backupCode - The plaintext backup code
|
|
129
|
-
* @param newPassword - Optional new password to re-wrap the private key
|
|
130
|
-
* @param session - Optional database session for transactional consistency
|
|
131
|
-
*/
|
|
132
|
-
async recoverKeyWithBackupCodeV1(userOrId, backupCode, newPassword, session) {
|
|
133
|
-
// Store-based path
|
|
134
|
-
if (this.store && !userOrId.save) {
|
|
135
|
-
return this._recoverViaStore(userOrId, backupCode, newPassword);
|
|
136
|
-
}
|
|
137
|
-
// Legacy Mongoose path
|
|
138
|
-
return this._recoverViaUserDoc(userOrId, backupCode, newPassword, session);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Recover a user's private key using a backup code (version-dispatched).
|
|
142
|
-
* Accepts either a UserDocument (legacy) or a user ID (store-based).
|
|
143
|
-
*/
|
|
144
|
-
async recoverKeyWithBackupCode(userOrId, backupCode, newPassword, session) {
|
|
145
|
-
// Determine backup codes source
|
|
146
|
-
let backupCodes;
|
|
147
|
-
if (this.store && !userOrId.save) {
|
|
148
|
-
const record = await this.store.getUserRecord(userOrId);
|
|
149
|
-
if (!record)
|
|
150
|
-
throw new suite_core_lib_1.InvalidBackupCodeError();
|
|
151
|
-
backupCodes = record.backupCodes;
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
backupCodes = userOrId.backupCodes;
|
|
155
|
-
}
|
|
156
|
-
const version = backup_code_1.BackupCode.detectBackupCodeVersion(backupCodes, backupCode);
|
|
157
|
-
switch (version) {
|
|
158
|
-
case backup_code_1.BackupCode.BackupCodeVersion:
|
|
159
|
-
return this.recoverKeyWithBackupCodeV1(userOrId, backupCode, newPassword, session);
|
|
160
|
-
default:
|
|
161
|
-
throw new invalid_backup_code_version_1.InvalidBackupCodeVersionError(version);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
// ── Rewrap (key rotation) ─────────────────────────────────────────────
|
|
165
|
-
/**
|
|
166
|
-
* Rewrap system-wrapped AEAD blobs from old system key to new one.
|
|
167
|
-
*
|
|
168
|
-
* When a store is provided, uses the store's fetchBatch/updateUserRecord.
|
|
169
|
-
* Otherwise falls back to the legacy callback-based approach.
|
|
170
|
-
*/
|
|
171
|
-
async rewrapAllUsersBackupCodes(fetchBatchOrOldSystem, saveUserOrNewSystem, oldSystemOrOptions, newSystemOrUndefined, options) {
|
|
172
|
-
// Detect which overload is being used
|
|
173
|
-
if (this.store && typeof fetchBatchOrOldSystem !== 'function') {
|
|
174
|
-
// Store-based: rewrapAllUsersBackupCodes(oldSystem, newSystem, options?)
|
|
175
|
-
return this._rewrapViaStore(fetchBatchOrOldSystem, saveUserOrNewSystem, oldSystemOrOptions);
|
|
176
|
-
}
|
|
177
|
-
// Legacy callback-based: rewrapAllUsersBackupCodes(fetchBatch, saveUser, oldSystem, newSystem, options?)
|
|
178
|
-
return this._rewrapViaCallbacks(fetchBatchOrOldSystem, saveUserOrNewSystem, oldSystemOrOptions, newSystemOrUndefined, options);
|
|
179
|
-
}
|
|
180
|
-
// ── Private: store-based recovery ─────────────────────────────────────
|
|
181
|
-
async _recoverViaStore(userId, backupCode, newPassword) {
|
|
182
|
-
const store = this.store;
|
|
183
|
-
const record = await store.getUserRecord(userId);
|
|
184
|
-
if (!record)
|
|
185
|
-
throw new suite_core_lib_1.InvalidBackupCodeError();
|
|
186
|
-
const normalizedCode = backup_code_1.BackupCode.normalizeCode(backupCode);
|
|
187
|
-
const { code, newCodesArray } = this.useBackupCodeV1(record.backupCodes, normalizedCode);
|
|
188
|
-
let decryptionKey;
|
|
189
|
-
try {
|
|
190
|
-
const adminMember = this.getSystemUser();
|
|
191
|
-
decryptionKey = await backup_code_1.BackupCode.getBackupKeyV1(code.checksumSalt, normalizedCode, this.application.constants);
|
|
192
|
-
const privateKeyUnwrapped = await adminMember.decryptData(Buffer.from(code.encrypted, 'hex'));
|
|
193
|
-
const decryptedPrivateKey = new ecies_lib_1.SecureBuffer(symmetric_1.SymmetricService.decryptBuffer(privateKeyUnwrapped, decryptionKey));
|
|
194
|
-
const memberType = await store.getMemberType(userId);
|
|
195
|
-
const user = new node_ecies_lib_1.Member(this.eciesService, memberType, record.username, new ecies_lib_1.EmailString(record.email), Buffer.from(record.publicKey, 'hex'), decryptedPrivateKey, undefined, record._id, new Date(record.createdAt), new Date(record.updatedAt));
|
|
196
|
-
const updates = {
|
|
197
|
-
backupCodes: newCodesArray,
|
|
198
|
-
};
|
|
199
|
-
if (newPassword) {
|
|
200
|
-
updates.passwordWrappedPrivateKey = this.keyWrappingService.wrapSecret(decryptedPrivateKey, newPassword, this.application.constants);
|
|
201
|
-
}
|
|
202
|
-
await store.updateUserRecord(userId, updates);
|
|
203
|
-
// Update the record in-place for the caller
|
|
204
|
-
record.backupCodes = newCodesArray;
|
|
205
|
-
if (updates.passwordWrappedPrivateKey) {
|
|
206
|
-
record.passwordWrappedPrivateKey = updates.passwordWrappedPrivateKey;
|
|
207
|
-
}
|
|
208
|
-
return { userRecord: record, user, codeCount: newCodesArray.length };
|
|
209
|
-
}
|
|
210
|
-
finally {
|
|
211
|
-
if (decryptionKey)
|
|
212
|
-
decryptionKey.fill(0);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
// ── Private: legacy Mongoose recovery ─────────────────────────────────
|
|
216
|
-
async _recoverViaUserDoc(userDoc, backupCode, newPassword, session) {
|
|
217
|
-
const normalizedCode = backup_code_1.BackupCode.normalizeCode(backupCode);
|
|
218
|
-
return await this.withTransaction(async (sess) => {
|
|
219
|
-
const { code, newCodesArray } = this.useBackupCodeV1(userDoc.backupCodes, normalizedCode);
|
|
220
|
-
userDoc.backupCodes = newCodesArray;
|
|
221
|
-
let decryptionKey;
|
|
222
|
-
try {
|
|
223
|
-
const adminMember = this.getSystemUser();
|
|
224
|
-
decryptionKey = await backup_code_1.BackupCode.getBackupKeyV1(code.checksumSalt, normalizedCode, this.application.constants);
|
|
225
|
-
const privateKeyUnwrapped = await adminMember.decryptData(Buffer.from(code.encrypted, 'hex'));
|
|
226
|
-
const decryptedPrivateKey = new ecies_lib_1.SecureBuffer(symmetric_1.SymmetricService.decryptBuffer(privateKeyUnwrapped, decryptionKey));
|
|
227
|
-
const memberType = await this.roleService.getMemberType(userDoc, session);
|
|
228
|
-
const user = new node_ecies_lib_1.Member(this.eciesService, memberType, userDoc.username, new ecies_lib_1.EmailString(userDoc.email), Buffer.from(userDoc.publicKey, 'hex'), decryptedPrivateKey, undefined, userDoc._id, new Date(userDoc.createdAt), new Date(userDoc.updatedAt));
|
|
229
|
-
if (!newPassword) {
|
|
230
|
-
await userDoc.save({ session: sess });
|
|
231
|
-
return {
|
|
232
|
-
userDoc,
|
|
233
|
-
user,
|
|
234
|
-
codeCount: newCodesArray.length,
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
const wrapped = this.keyWrappingService.wrapSecret(decryptedPrivateKey, newPassword, this.application.constants);
|
|
238
|
-
userDoc.passwordWrappedPrivateKey = wrapped;
|
|
239
|
-
await userDoc.save({ session: sess });
|
|
240
|
-
return { userDoc, user, codeCount: newCodesArray.length };
|
|
241
|
-
}
|
|
242
|
-
finally {
|
|
243
|
-
if (decryptionKey)
|
|
244
|
-
decryptionKey.fill(0);
|
|
245
|
-
}
|
|
246
|
-
}, session, {
|
|
247
|
-
timeoutMs: this.application.environment.mongo.transactionTimeout * 5,
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
// ── Private: store-based rewrap ───────────────────────────────────────
|
|
251
|
-
async _rewrapViaStore(oldSystem, newSystem, options) {
|
|
252
|
-
const store = this.store;
|
|
253
|
-
const batchSize = options?.batchSize ?? 500;
|
|
254
|
-
let processed = 0;
|
|
255
|
-
let afterId;
|
|
256
|
-
for (;;) {
|
|
257
|
-
const records = await store.fetchBatch(afterId, batchSize);
|
|
258
|
-
if (!records.length)
|
|
259
|
-
break;
|
|
260
|
-
for (const record of records) {
|
|
261
|
-
let modified = false;
|
|
262
|
-
for (const bc of record.backupCodes ?? []) {
|
|
263
|
-
try {
|
|
264
|
-
const sealed = await oldSystem.decryptData(Buffer.from(bc.encrypted, 'hex'));
|
|
265
|
-
const rewrapped = (await newSystem.encryptData(sealed)).toString('hex');
|
|
266
|
-
if (rewrapped !== bc.encrypted) {
|
|
267
|
-
bc.encrypted = rewrapped;
|
|
268
|
-
modified = true;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
catch (e) {
|
|
272
|
-
throw new Error(`Failed to rewrap backup code for user ${record._id}: ${e.message}`);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
if (modified) {
|
|
276
|
-
await store.updateUserRecord(record._id, {
|
|
277
|
-
backupCodes: record.backupCodes,
|
|
278
|
-
});
|
|
279
|
-
processed++;
|
|
280
|
-
options?.onProgress?.(processed);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
afterId = records[records.length - 1]?._id?.toString() ?? undefined;
|
|
284
|
-
}
|
|
285
|
-
return processed;
|
|
286
|
-
}
|
|
287
|
-
// ── Private: legacy callback-based rewrap ─────────────────────────────
|
|
288
|
-
async _rewrapViaCallbacks(fetchBatch, saveUser, oldSystem, newSystem, options) {
|
|
289
|
-
const batchSize = options?.batchSize ?? 500;
|
|
290
|
-
let processed = 0;
|
|
291
|
-
let afterId;
|
|
292
|
-
for (;;) {
|
|
293
|
-
const users = await fetchBatch(afterId, batchSize);
|
|
294
|
-
if (!users.length)
|
|
295
|
-
break;
|
|
296
|
-
for (const user of users) {
|
|
297
|
-
let modified = false;
|
|
298
|
-
for (const bc of user.backupCodes ?? []) {
|
|
299
|
-
try {
|
|
300
|
-
const sealed = await oldSystem.decryptData(Buffer.from(bc.encrypted, 'hex'));
|
|
301
|
-
const rewrapped = (await newSystem.encryptData(sealed)).toString('hex');
|
|
302
|
-
if (rewrapped !== bc.encrypted) {
|
|
303
|
-
bc.encrypted = rewrapped;
|
|
304
|
-
modified = true;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
catch (e) {
|
|
308
|
-
throw new Error(`Failed to rewrap backup code for user ${user._id}: ${e.message}`);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
if (modified) {
|
|
312
|
-
await saveUser(user);
|
|
313
|
-
processed++;
|
|
314
|
-
options?.onProgress?.(processed);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
afterId = users[users.length - 1]?._id?.toString() ?? undefined;
|
|
318
|
-
}
|
|
319
|
-
return processed;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
exports.BackupCodeService = BackupCodeService;
|
|
323
|
-
//# sourceMappingURL=backup-code.js.map
|