@tstdl/base 0.93.86 → 0.93.89
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/ai/genkit/helpers.d.ts +3 -1
- package/ai/genkit/helpers.js +3 -3
- package/api/server/gateway.d.ts +3 -0
- package/api/server/gateway.js +15 -4
- package/api/server/middlewares/catch-error.middleware.js +2 -4
- package/api/server/middlewares/cors.middleware.js +2 -3
- package/api/server/middlewares/csrf.middleware.d.ts +41 -0
- package/api/server/middlewares/csrf.middleware.js +108 -0
- package/api/server/middlewares/index.d.ts +1 -0
- package/api/server/middlewares/index.js +1 -0
- package/api/server/module.d.ts +8 -2
- package/api/server/module.js +14 -8
- package/api/server/tests/csrf.middleware.test.js +91 -0
- package/audit/drizzle/{0000_bored_stick.sql → 0000_lumpy_thunderball.sql} +3 -3
- package/audit/drizzle/meta/0000_snapshot.json +4 -4
- package/audit/drizzle/meta/_journal.json +2 -9
- package/audit/module.d.ts +4 -1
- package/audit/module.js +3 -2
- package/audit/schemas.d.ts +1 -1
- package/audit/types.d.ts +1 -1
- package/audit/types.js +1 -1
- package/authentication/client/authentication.service.d.ts +14 -1
- package/authentication/client/authentication.service.js +82 -23
- package/authentication/client/http-client.middleware.d.ts +6 -0
- package/authentication/client/http-client.middleware.js +36 -0
- package/authentication/client/module.js +8 -2
- package/authentication/models/service-account.model.d.ts +2 -2
- package/authentication/models/service-account.model.js +10 -5
- package/authentication/models/subject.model.d.ts +19 -5
- package/authentication/models/subject.model.js +25 -29
- package/authentication/models/system-account.model.d.ts +3 -2
- package/authentication/models/system-account.model.js +11 -5
- package/authentication/models/user.model.d.ts +2 -11
- package/authentication/models/user.model.js +5 -16
- package/authentication/server/authentication-api-request-token.provider.d.ts +0 -2
- package/authentication/server/authentication-api-request-token.provider.js +3 -11
- package/authentication/server/authentication.api-controller.d.ts +1 -2
- package/authentication/server/authentication.api-controller.js +8 -9
- package/authentication/server/authentication.audit.d.ts +3 -2
- package/authentication/server/authentication.service.d.ts +27 -1
- package/authentication/server/authentication.service.js +67 -18
- package/authentication/server/drizzle/{0000_normal_paper_doll.sql → 0000_soft_tag.sql} +25 -32
- package/authentication/server/drizzle/meta/0000_snapshot.json +180 -205
- package/authentication/server/drizzle/meta/_journal.json +2 -2
- package/authentication/server/helper.js +9 -2
- package/authentication/server/module.d.ts +4 -1
- package/authentication/server/module.js +9 -5
- package/authentication/server/schemas.d.ts +2 -1
- package/authentication/server/schemas.js +2 -2
- package/authentication/server/subject.service.d.ts +14 -8
- package/authentication/server/subject.service.js +86 -84
- package/authentication/tests/authentication-ancillary.service.test.d.ts +1 -0
- package/authentication/tests/authentication-ancillary.service.test.js +13 -0
- package/authentication/tests/authentication-secret-requirements.validator.test.d.ts +1 -0
- package/authentication/tests/authentication-secret-requirements.validator.test.js +29 -0
- package/authentication/tests/authentication.api-controller.test.d.ts +1 -0
- package/authentication/tests/authentication.api-controller.test.js +88 -0
- package/authentication/tests/authentication.api-request-token.provider.test.d.ts +1 -0
- package/authentication/tests/authentication.api-request-token.provider.test.js +48 -0
- package/authentication/tests/authentication.client-middleware.test.d.ts +1 -0
- package/authentication/tests/authentication.client-middleware.test.js +23 -0
- package/authentication/tests/authentication.client-service.test.d.ts +1 -0
- package/authentication/tests/authentication.client-service.test.js +70 -0
- package/authentication/tests/authentication.service.test.d.ts +1 -0
- package/authentication/tests/authentication.service.test.js +186 -0
- package/authentication/tests/authentication.test-ancillary-service.d.ts +9 -0
- package/authentication/tests/authentication.test-ancillary-service.js +27 -0
- package/authentication/tests/helper.test.d.ts +1 -0
- package/authentication/tests/helper.test.js +107 -0
- package/authentication/tests/secret-requirements.error.test.d.ts +1 -0
- package/authentication/tests/secret-requirements.error.test.js +14 -0
- package/authentication/tests/subject.service.test.d.ts +1 -0
- package/authentication/tests/subject.service.test.js +140 -0
- package/circuit-breaker/postgres/drizzle/meta/0000_snapshot.json +1 -1
- package/circuit-breaker/postgres/drizzle/meta/_journal.json +2 -2
- package/circuit-breaker/postgres/module.d.ts +7 -1
- package/circuit-breaker/postgres/module.js +8 -6
- package/circuit-breaker/tests/circuit-breaker.test.js +2 -22
- package/document-management/api/document-management.api.js +2 -6
- package/document-management/server/services/document-validation.service.js +6 -5
- package/document-management/server/services/document-workflow.service.js +5 -5
- package/document-management/service-models/document-folders.view-model.d.ts +5 -2
- package/document-management/service-models/document-folders.view-model.js +42 -9
- package/document-management/service-models/enriched/enriched-document-management-data.view.js +1 -1
- package/examples/document-management/main.js +4 -4
- package/http/client/adapters/undici.adapter.d.ts +7 -5
- package/http/client/adapters/undici.adapter.js +13 -10
- package/http/client/module.d.ts +3 -1
- package/http/client/module.js +8 -9
- package/http/server/http-server.d.ts +2 -0
- package/http/server/node/module.d.ts +6 -2
- package/http/server/node/module.js +6 -4
- package/http/server/node/node-http-server.d.ts +2 -0
- package/http/server/node/node-http-server.js +7 -0
- package/http/types.d.ts +1 -1
- package/key-value-store/postgres/module.d.ts +7 -1
- package/key-value-store/postgres/module.js +7 -3
- package/lock/postgres/lock.js +0 -1
- package/lock/postgres/module.d.ts +7 -1
- package/lock/postgres/module.js +9 -5
- package/logger/formatter.d.ts +2 -0
- package/logger/formatters/json.js +2 -2
- package/logger/formatters/pretty-print.js +8 -10
- package/logger/logger.d.ts +1 -1
- package/logger/logger.js +15 -12
- package/message-bus/local/module.d.ts +5 -2
- package/message-bus/local/module.js +5 -4
- package/module/module.d.ts +2 -1
- package/module/module.js +3 -0
- package/module/modules/web-server.module.d.ts +11 -6
- package/module/modules/web-server.module.js +15 -10
- package/orm/decorators.d.ts +24 -1
- package/orm/decorators.js +40 -4
- package/orm/index.d.ts +1 -1
- package/orm/index.js +1 -1
- package/orm/query/base.d.ts +17 -17
- package/orm/query/base.js +1 -1
- package/orm/repository.types.d.ts +46 -2
- package/orm/schemas/tsvector.js +1 -1
- package/orm/server/drizzle/schema-converter.d.ts +3 -1
- package/orm/server/drizzle/schema-converter.js +120 -14
- package/orm/server/index.d.ts +1 -0
- package/orm/server/index.js +1 -0
- package/orm/server/module.d.ts +4 -2
- package/orm/server/module.js +6 -5
- package/orm/server/query-converter.d.ts +6 -3
- package/orm/server/query-converter.js +33 -21
- package/orm/server/repository-config.d.ts +8 -0
- package/orm/server/repository-config.js +8 -0
- package/orm/server/repository.d.ts +117 -43
- package/orm/server/repository.js +758 -254
- package/orm/server/transaction.d.ts +4 -2
- package/orm/server/transaction.js +14 -5
- package/orm/server/transactional.d.ts +6 -2
- package/orm/server/transactional.js +39 -9
- package/orm/server/types.d.ts +2 -0
- package/orm/sqls/case-when.d.ts +25 -0
- package/orm/sqls/case-when.js +54 -0
- package/orm/sqls/index.d.ts +2 -0
- package/orm/sqls/index.js +2 -0
- package/orm/{sqls.d.ts → sqls/sqls.d.ts} +67 -19
- package/orm/{sqls.js → sqls/sqls.js} +116 -22
- package/orm/tests/data-types.test.d.ts +1 -0
- package/orm/tests/data-types.test.js +39 -0
- package/orm/tests/decorators.test.d.ts +1 -0
- package/orm/tests/decorators.test.js +77 -0
- package/orm/tests/encryption.test.d.ts +1 -0
- package/orm/tests/encryption.test.js +34 -0
- package/orm/tests/query-complex.test.d.ts +1 -0
- package/orm/tests/query-complex.test.js +203 -0
- package/orm/tests/query-converter-complex.test.d.ts +1 -0
- package/orm/tests/query-converter-complex.test.js +126 -0
- package/orm/tests/query-converter.test.d.ts +1 -0
- package/orm/tests/query-converter.test.js +123 -0
- package/orm/tests/repository-advanced.test.d.ts +1 -0
- package/orm/tests/repository-advanced.test.js +232 -0
- package/orm/tests/repository-attributes.test.d.ts +1 -0
- package/orm/tests/repository-attributes.test.js +99 -0
- package/orm/tests/repository-comprehensive.test.d.ts +1 -0
- package/orm/tests/repository-comprehensive.test.js +187 -0
- package/orm/tests/repository-coverage.test.d.ts +1 -0
- package/orm/tests/repository-coverage.test.js +303 -0
- package/orm/tests/repository-cti-complex.test.d.ts +1 -0
- package/orm/tests/repository-cti-complex.test.js +170 -0
- package/orm/tests/repository-cti-embedded.test.d.ts +1 -0
- package/orm/tests/repository-cti-embedded.test.js +188 -0
- package/orm/tests/repository-cti-extensive.test.d.ts +1 -0
- package/orm/tests/repository-cti-extensive.test.js +308 -0
- package/orm/tests/repository-cti-mapping.test.d.ts +1 -0
- package/orm/tests/repository-cti-mapping.test.js +121 -0
- package/orm/tests/repository-cti-search.test.d.ts +1 -0
- package/orm/tests/repository-cti-search.test.js +152 -0
- package/orm/tests/repository-cti-soft-delete.test.d.ts +1 -0
- package/orm/tests/repository-cti-soft-delete.test.js +115 -0
- package/orm/tests/repository-cti-transactions.test.d.ts +1 -0
- package/orm/tests/repository-cti-transactions.test.js +126 -0
- package/orm/tests/repository-cti-upsert-many.test.d.ts +1 -0
- package/orm/tests/repository-cti-upsert-many.test.js +127 -0
- package/orm/tests/repository-cti.test.d.ts +1 -0
- package/orm/tests/repository-cti.test.js +456 -0
- package/orm/tests/repository-edge-cases.test.d.ts +1 -0
- package/orm/tests/repository-edge-cases.test.js +216 -0
- package/orm/tests/repository-expiration.test.d.ts +1 -0
- package/orm/tests/repository-expiration.test.js +153 -0
- package/orm/tests/repository-extra-coverage.test.d.ts +1 -0
- package/orm/tests/repository-extra-coverage.test.js +546 -0
- package/orm/tests/repository-mapping.test.d.ts +1 -0
- package/orm/tests/repository-mapping.test.js +71 -0
- package/orm/tests/repository-regression.test.d.ts +1 -0
- package/orm/tests/repository-regression.test.js +330 -0
- package/orm/tests/repository-search-coverage.test.d.ts +1 -0
- package/orm/tests/repository-search-coverage.test.js +129 -0
- package/orm/tests/repository-search.test.d.ts +1 -0
- package/orm/tests/repository-search.test.js +116 -0
- package/orm/tests/repository-soft-delete.test.d.ts +1 -0
- package/orm/tests/repository-soft-delete.test.js +143 -0
- package/orm/tests/repository-transactions-nested.test.d.ts +1 -0
- package/orm/tests/repository-transactions-nested.test.js +202 -0
- package/orm/tests/repository-types.test.d.ts +1 -0
- package/orm/tests/repository-types.test.js +218 -0
- package/orm/tests/schema-converter.test.d.ts +1 -0
- package/orm/tests/schema-converter.test.js +81 -0
- package/orm/tests/schema-generation.test.d.ts +1 -0
- package/orm/tests/schema-generation.test.js +127 -0
- package/orm/tests/sql-helpers.test.d.ts +1 -0
- package/orm/tests/sql-helpers.test.js +67 -0
- package/orm/tests/transaction-safety.test.d.ts +1 -0
- package/orm/tests/transaction-safety.test.js +81 -0
- package/orm/tests/transactional.test.d.ts +1 -0
- package/orm/tests/transactional.test.js +224 -0
- package/orm/tests/utils.test.d.ts +1 -0
- package/orm/tests/utils.test.js +70 -0
- package/orm/utils.d.ts +7 -0
- package/orm/utils.js +26 -6
- package/package.json +12 -7
- package/pool/pool.js +1 -1
- package/rate-limit/index.d.ts +2 -0
- package/rate-limit/index.js +2 -0
- package/rate-limit/postgres/drizzle/0000_watery_rage.sql +7 -0
- package/{queue → rate-limit}/postgres/drizzle/meta/0000_snapshot.json +14 -39
- package/rate-limit/postgres/drizzle/meta/_journal.json +13 -0
- package/{queue → rate-limit}/postgres/drizzle.config.js +1 -1
- package/rate-limit/postgres/index.d.ts +4 -0
- package/rate-limit/postgres/index.js +4 -0
- package/rate-limit/postgres/module.d.ts +12 -0
- package/rate-limit/postgres/module.js +28 -0
- package/rate-limit/postgres/postgres-rate-limiter.d.ts +9 -0
- package/rate-limit/postgres/postgres-rate-limiter.js +56 -0
- package/rate-limit/postgres/rate-limit.model.d.ts +8 -0
- package/rate-limit/postgres/rate-limit.model.js +35 -0
- package/rate-limit/postgres/rate-limiter.provider.d.ts +6 -0
- package/rate-limit/postgres/rate-limiter.provider.js +21 -0
- package/rate-limit/postgres/schemas.d.ts +3 -0
- package/rate-limit/postgres/schemas.js +4 -0
- package/rate-limit/provider.d.ts +9 -0
- package/rate-limit/provider.js +2 -0
- package/rate-limit/rate-limiter.d.ts +35 -0
- package/rate-limit/rate-limiter.js +3 -0
- package/rate-limit/tests/postgres-rate-limiter.test.d.ts +1 -0
- package/rate-limit/tests/postgres-rate-limiter.test.js +92 -0
- package/signals/implementation/configure.d.ts +3 -0
- package/signals/implementation/configure.js +3 -0
- package/sse/data-stream-source.d.ts +1 -1
- package/sse/data-stream-source.js +6 -6
- package/task-queue/enqueue-batch.d.ts +17 -0
- package/task-queue/enqueue-batch.js +24 -0
- package/{queue → task-queue}/index.d.ts +1 -1
- package/{queue → task-queue}/index.js +1 -1
- package/task-queue/postgres/drizzle/0000_thin_black_panther.sql +74 -0
- package/task-queue/postgres/drizzle/meta/0000_snapshot.json +592 -0
- package/task-queue/postgres/drizzle/meta/_journal.json +13 -0
- package/task-queue/postgres/drizzle.config.d.ts +2 -0
- package/task-queue/postgres/drizzle.config.js +11 -0
- package/task-queue/postgres/index.d.ts +4 -0
- package/task-queue/postgres/index.js +4 -0
- package/task-queue/postgres/module.d.ts +12 -0
- package/task-queue/postgres/module.js +28 -0
- package/task-queue/postgres/schemas.d.ts +16 -0
- package/task-queue/postgres/schemas.js +8 -0
- package/task-queue/postgres/task-queue.d.ts +83 -0
- package/task-queue/postgres/task-queue.js +1054 -0
- package/task-queue/postgres/task-queue.provider.d.ts +7 -0
- package/{queue/postgres/queue.provider.js → task-queue/postgres/task-queue.provider.js} +8 -8
- package/task-queue/postgres/task.model.d.ts +39 -0
- package/task-queue/postgres/task.model.js +178 -0
- package/{queue → task-queue}/provider.d.ts +3 -3
- package/task-queue/provider.js +2 -0
- package/{queue → task-queue}/task-context.d.ts +7 -7
- package/{queue → task-queue}/task-context.js +8 -8
- package/{queue/queue.d.ts → task-queue/task-queue.d.ts} +128 -59
- package/task-queue/task-queue.js +200 -0
- package/task-queue/tests/complex.test.d.ts +1 -0
- package/task-queue/tests/complex.test.js +299 -0
- package/task-queue/tests/dependencies.test.d.ts +1 -0
- package/task-queue/tests/dependencies.test.js +174 -0
- package/task-queue/tests/queue.test.d.ts +1 -0
- package/task-queue/tests/queue.test.js +334 -0
- package/task-queue/tests/worker.test.d.ts +1 -0
- package/task-queue/tests/worker.test.js +163 -0
- package/test1.js +1 -1
- package/test4.js +2 -2
- package/unit-test/index.d.ts +1 -0
- package/unit-test/index.js +1 -0
- package/unit-test/integration-setup.d.ts +55 -0
- package/unit-test/integration-setup.js +182 -0
- package/utils/patterns.d.ts +3 -0
- package/utils/patterns.js +6 -1
- package/audit/drizzle/0001_previous_network.sql +0 -2
- package/audit/drizzle/meta/0001_snapshot.json +0 -195
- package/queue/enqueue-batch.d.ts +0 -17
- package/queue/enqueue-batch.js +0 -18
- package/queue/postgres/drizzle/0000_zippy_moondragon.sql +0 -11
- package/queue/postgres/drizzle/0001_certain_wild_pack.sql +0 -2
- package/queue/postgres/drizzle/0002_dear_meggan.sql +0 -2
- package/queue/postgres/drizzle/0003_tricky_venom.sql +0 -30
- package/queue/postgres/drizzle/meta/0001_snapshot.json +0 -103
- package/queue/postgres/drizzle/meta/0002_snapshot.json +0 -90
- package/queue/postgres/drizzle/meta/0003_snapshot.json +0 -288
- package/queue/postgres/drizzle/meta/_journal.json +0 -34
- package/queue/postgres/index.d.ts +0 -4
- package/queue/postgres/index.js +0 -4
- package/queue/postgres/module.d.ts +0 -9
- package/queue/postgres/module.js +0 -29
- package/queue/postgres/queue.d.ts +0 -60
- package/queue/postgres/queue.js +0 -681
- package/queue/postgres/queue.provider.d.ts +0 -7
- package/queue/postgres/schemas.d.ts +0 -14
- package/queue/postgres/schemas.js +0 -6
- package/queue/postgres/task.model.d.ts +0 -24
- package/queue/postgres/task.model.js +0 -115
- package/queue/provider.js +0 -2
- package/queue/queue.js +0 -131
- package/queue/tests/queue.test.js +0 -623
- package/test3.d.ts +0 -1
- package/test3.js +0 -47
- /package/{queue/tests/queue.test.d.ts → api/server/tests/csrf.middleware.test.d.ts} +0 -0
- /package/circuit-breaker/postgres/drizzle/{0000_hard_shocker.sql → 0000_cooing_korath.sql} +0 -0
- /package/{queue → rate-limit}/postgres/drizzle.config.d.ts +0 -0
|
@@ -5,73 +5,55 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { BadRequestError } from '../../errors/bad-request.error.js';
|
|
8
|
-
import { formatPersonName } from '../../formats/formats.js';
|
|
9
8
|
import { Singleton } from '../../injector/index.js';
|
|
10
9
|
import { injectRepository } from '../../orm/server/index.js';
|
|
11
10
|
import { mailPattern } from '../../utils/patterns.js';
|
|
12
|
-
import {
|
|
13
|
-
import { ServiceAccount, Subject, SubjectType, SystemAccount, User
|
|
11
|
+
import { isDefined, isUndefined } from '../../utils/type-guards.js';
|
|
12
|
+
import { ServiceAccount, Subject, SubjectStatus, SubjectType, SystemAccount, User } from '../models/index.js';
|
|
14
13
|
let SubjectService = class SubjectService {
|
|
15
14
|
#subjectRepository = injectRepository(Subject);
|
|
16
15
|
#systemAccountRepository = injectRepository(SystemAccount);
|
|
17
16
|
#userRepository = injectRepository(User);
|
|
18
17
|
#serviceAccountRepository = injectRepository(ServiceAccount);
|
|
19
|
-
async getSubject(id) {
|
|
20
|
-
return await this.#subjectRepository.load(id);
|
|
18
|
+
async getSubject(id, options) {
|
|
19
|
+
return await this.#subjectRepository.load(id, options);
|
|
21
20
|
}
|
|
22
|
-
async tryGetSubject(id) {
|
|
23
|
-
return await this.#subjectRepository.tryLoad(id);
|
|
21
|
+
async tryGetSubject(id, options) {
|
|
22
|
+
return await this.#subjectRepository.tryLoad(id, options);
|
|
24
23
|
}
|
|
25
|
-
async
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
async getSystemAccount(tenantId, identifier) {
|
|
25
|
+
const systemAccount = await this.#systemAccountRepository.tryLoadByQuery({
|
|
26
|
+
tenantId,
|
|
27
|
+
identifier,
|
|
28
|
+
});
|
|
29
|
+
if (isUndefined(systemAccount)) {
|
|
30
|
+
return await this.#systemAccountRepository.insert({
|
|
31
|
+
type: SubjectType.System,
|
|
28
32
|
tenantId,
|
|
29
33
|
identifier,
|
|
34
|
+
status: SubjectStatus.Active,
|
|
35
|
+
displayName: `System: ${identifier}`,
|
|
36
|
+
lastActivityTimestamp: null,
|
|
30
37
|
});
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
tenantId,
|
|
34
|
-
identifier,
|
|
35
|
-
});
|
|
36
|
-
return await this.#subjectRepository.withTransaction(tx).insert({
|
|
37
|
-
type: SubjectType.System,
|
|
38
|
-
tenantId,
|
|
39
|
-
systemAccountId: systemAccount.id,
|
|
40
|
-
displayName: `System: ${identifier}`,
|
|
41
|
-
userId: null,
|
|
42
|
-
serviceAccountId: null,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return await this.#subjectRepository.withTransaction(tx).loadByQuery({
|
|
46
|
-
tenantId,
|
|
47
|
-
systemAccountId: systemAccount.id,
|
|
48
|
-
});
|
|
49
|
-
});
|
|
38
|
+
}
|
|
39
|
+
return systemAccount;
|
|
50
40
|
}
|
|
51
41
|
async createUser(data) {
|
|
52
42
|
const { tenantId, email, firstName, lastName, status } = data;
|
|
53
|
-
return await this.#userRepository.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
await this.#subjectRepository.withTransaction(tx).insert({
|
|
62
|
-
tenantId,
|
|
63
|
-
type: SubjectType.User,
|
|
64
|
-
displayName: `${firstName} ${lastName}`,
|
|
65
|
-
systemAccountId: null,
|
|
66
|
-
userId: user.id,
|
|
67
|
-
serviceAccountId: null,
|
|
68
|
-
});
|
|
69
|
-
return user;
|
|
43
|
+
return await this.#userRepository.insert({
|
|
44
|
+
type: SubjectType.User,
|
|
45
|
+
tenantId,
|
|
46
|
+
email,
|
|
47
|
+
firstName,
|
|
48
|
+
lastName,
|
|
49
|
+
status: status ?? SubjectStatus.Active,
|
|
50
|
+
lastActivityTimestamp: null,
|
|
70
51
|
});
|
|
71
52
|
}
|
|
72
53
|
async updateUser(tenantId, userId, data) {
|
|
73
54
|
const { firstName, lastName, status } = data;
|
|
74
55
|
await this.#userRepository.transaction(async (tx) => {
|
|
56
|
+
const userRepository = this.#userRepository.withTransaction(tx);
|
|
75
57
|
const updateData = {};
|
|
76
58
|
if (isDefined(firstName)) {
|
|
77
59
|
updateData.firstName = firstName;
|
|
@@ -83,10 +65,7 @@ let SubjectService = class SubjectService {
|
|
|
83
65
|
updateData.status = status;
|
|
84
66
|
}
|
|
85
67
|
if (Object.keys(updateData).length > 0) {
|
|
86
|
-
|
|
87
|
-
if (isDefined(firstName) || isDefined(lastName)) {
|
|
88
|
-
await this.#subjectRepository.withTransaction(tx).updateByQuery({ tenantId, userId }, { displayName: formatPersonName(updatedUser) });
|
|
89
|
-
}
|
|
68
|
+
await userRepository.updateByQuery({ tenantId, id: userId }, updateData);
|
|
90
69
|
}
|
|
91
70
|
});
|
|
92
71
|
}
|
|
@@ -95,10 +74,10 @@ let SubjectService = class SubjectService {
|
|
|
95
74
|
if (!mailPattern.test(email)) {
|
|
96
75
|
throw new BadRequestError(`Invalid email format.`);
|
|
97
76
|
}
|
|
98
|
-
await this.#userRepository.updateByQuery({ tenantId, userId }, { email });
|
|
77
|
+
await this.#userRepository.updateByQuery({ tenantId, id: userId }, { email });
|
|
99
78
|
}
|
|
100
|
-
async
|
|
101
|
-
return await this.#
|
|
79
|
+
async getUser(tenantId, userId) {
|
|
80
|
+
return await this.#userRepository.loadByQuery({ tenantId, id: userId });
|
|
102
81
|
}
|
|
103
82
|
async getUserByEmail(tenantId, email) {
|
|
104
83
|
return await this.#userRepository.loadByQuery({ tenantId, email });
|
|
@@ -111,48 +90,71 @@ let SubjectService = class SubjectService {
|
|
|
111
90
|
return isDefined(user);
|
|
112
91
|
}
|
|
113
92
|
async getUserBySubject(subject) {
|
|
114
|
-
|
|
115
|
-
|
|
93
|
+
if (subject instanceof User) {
|
|
94
|
+
return subject;
|
|
95
|
+
}
|
|
96
|
+
if (subject.type != SubjectType.User) {
|
|
97
|
+
throw new BadRequestError('Subject is not a user subject');
|
|
98
|
+
}
|
|
99
|
+
return await this.#userRepository.loadByQuery({ tenantId: subject.tenantId, id: subject.id });
|
|
116
100
|
}
|
|
117
101
|
async loadManyUsersByEmails(tenantId, emails) {
|
|
118
102
|
return await this.#userRepository.loadManyByQuery({ tenantId, email: { $in: emails } });
|
|
119
103
|
}
|
|
120
104
|
async createServiceAccount(data) {
|
|
121
|
-
const { tenantId, description, parent } = data;
|
|
122
|
-
return await this.#serviceAccountRepository.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
type: SubjectType.ServiceAccount,
|
|
131
|
-
displayName: description,
|
|
132
|
-
userId: null,
|
|
133
|
-
systemAccountId: null,
|
|
134
|
-
serviceAccountId: serviceAccount.id,
|
|
135
|
-
});
|
|
136
|
-
return serviceAccount;
|
|
105
|
+
const { tenantId, description, displayName, parent, status } = data;
|
|
106
|
+
return await this.#serviceAccountRepository.insert({
|
|
107
|
+
type: SubjectType.ServiceAccount,
|
|
108
|
+
tenantId,
|
|
109
|
+
description,
|
|
110
|
+
displayName,
|
|
111
|
+
parent,
|
|
112
|
+
status: status ?? SubjectStatus.Active,
|
|
113
|
+
lastActivityTimestamp: null,
|
|
137
114
|
});
|
|
138
115
|
}
|
|
139
116
|
async updateServiceAccount(tenantId, serviceAccountId, data) {
|
|
140
|
-
const { displayName, description } = data;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
117
|
+
const { displayName, description, status } = data;
|
|
118
|
+
const update = {};
|
|
119
|
+
if (isDefined(displayName)) {
|
|
120
|
+
update.displayName = displayName;
|
|
121
|
+
}
|
|
122
|
+
if (isDefined(description)) {
|
|
123
|
+
update.description = description;
|
|
124
|
+
}
|
|
125
|
+
if (isDefined(status)) {
|
|
126
|
+
update.status = status;
|
|
127
|
+
}
|
|
128
|
+
if (Object.keys(update).length > 0) {
|
|
129
|
+
await this.#serviceAccountRepository.updateByQuery({ tenantId, id: serviceAccountId }, update);
|
|
130
|
+
}
|
|
149
131
|
}
|
|
150
|
-
async
|
|
151
|
-
return await this.#
|
|
132
|
+
async getServiceAccount(tenantId, serviceAccountId) {
|
|
133
|
+
return await this.#serviceAccountRepository.loadByQuery({ tenantId, id: serviceAccountId });
|
|
152
134
|
}
|
|
153
135
|
async getServiceAccountBySubject(subject) {
|
|
154
|
-
|
|
155
|
-
|
|
136
|
+
if (subject instanceof ServiceAccount) {
|
|
137
|
+
return subject;
|
|
138
|
+
}
|
|
139
|
+
if (subject.type != SubjectType.ServiceAccount) {
|
|
140
|
+
throw new BadRequestError('Subject is not a service account subject');
|
|
141
|
+
}
|
|
142
|
+
return await this.#serviceAccountRepository.loadByQuery({ tenantId: subject.tenantId, id: subject.id });
|
|
143
|
+
}
|
|
144
|
+
async exists(tenantId, id) {
|
|
145
|
+
return await this.#subjectRepository.hasByQuery({ tenantId, id });
|
|
146
|
+
}
|
|
147
|
+
async deleteUser(tenantId, userId) {
|
|
148
|
+
await this.#userRepository.deleteByQuery({ tenantId, id: userId });
|
|
149
|
+
}
|
|
150
|
+
async deleteServiceAccount(tenantId, serviceAccountId) {
|
|
151
|
+
await this.#serviceAccountRepository.deleteByQuery({ tenantId, id: serviceAccountId });
|
|
152
|
+
}
|
|
153
|
+
async listUsers(tenantId) {
|
|
154
|
+
return await this.#userRepository.loadManyByQuery({ tenantId });
|
|
155
|
+
}
|
|
156
|
+
async listServiceAccounts(tenantId) {
|
|
157
|
+
return await this.#serviceAccountRepository.loadManyByQuery({ tenantId });
|
|
156
158
|
}
|
|
157
159
|
};
|
|
158
160
|
SubjectService = __decorate([
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { runInInjectionContext } from '../../injector/index.js';
|
|
3
|
+
import { setupIntegrationTest } from '../../unit-test/index.js';
|
|
4
|
+
import { DefaultAuthenticationAncillaryService } from './authentication.test-ancillary-service.js';
|
|
5
|
+
describe('AuthenticationAncillaryService', () => {
|
|
6
|
+
test('default implementation should be abstract or have defaults', async () => {
|
|
7
|
+
const { injector } = await setupIntegrationTest({ modules: { authentication: true } });
|
|
8
|
+
await runInInjectionContext(injector, async () => {
|
|
9
|
+
const service = await injector.resolveAsync(DefaultAuthenticationAncillaryService);
|
|
10
|
+
expect(await service.canImpersonate({}, {}, {})).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { SecretRequirementsError } from '../errors/secret-requirements.error.js';
|
|
3
|
+
import { DefaultAuthenticationSecretRequirementsValidator } from '../server/authentication-secret-requirements.validator.js';
|
|
4
|
+
describe('DefaultAuthenticationSecretRequirementsValidator', () => {
|
|
5
|
+
const validator = new DefaultAuthenticationSecretRequirementsValidator();
|
|
6
|
+
it('should return success when password is strong and not pwned', async () => {
|
|
7
|
+
// A very long random string is unlikely to be pwned and will be strong
|
|
8
|
+
const result = await validator.testSecretRequirements('Very-Strong-And-Long-Password-2026!@#$%^&*()');
|
|
9
|
+
expect(result.success).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
it('should return failure when password is pwned', async () => {
|
|
12
|
+
// "password" is definitely pwned
|
|
13
|
+
const result = await validator.testSecretRequirements('password');
|
|
14
|
+
expect(result.success).toBe(false);
|
|
15
|
+
expect(result.reason).toContain('exposed in data breach');
|
|
16
|
+
});
|
|
17
|
+
it('should return failure when password is too weak', async () => {
|
|
18
|
+
// "abc" is too weak (and likely pwned)
|
|
19
|
+
const result = await validator.testSecretRequirements('abc');
|
|
20
|
+
expect(result.success).toBe(false);
|
|
21
|
+
expect(result.reason).toBeDefined();
|
|
22
|
+
});
|
|
23
|
+
it('should throw SecretRequirementsError on validation failure', async () => {
|
|
24
|
+
await expect(validator.validateSecretRequirements('abc')).rejects.toThrow(SecretRequirementsError);
|
|
25
|
+
});
|
|
26
|
+
it('should not throw on validation success', async () => {
|
|
27
|
+
await expect(validator.validateSecretRequirements('Very-Strong-And-Long-Password-2026!@#$%^&*()')).resolves.not.toThrow();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from 'vitest';
|
|
2
|
+
import { AuthenticationClientService } from '../../authentication/client/index.js';
|
|
3
|
+
import { AuthenticationAncillaryService, AuthenticationService as AuthenticationServerService } from '../../authentication/server/index.js';
|
|
4
|
+
import { HttpClientOptions } from '../../http/client/index.js';
|
|
5
|
+
import { HttpServer } from '../../http/server/index.js';
|
|
6
|
+
import { runInInjectionContext } from '../../injector/index.js';
|
|
7
|
+
import { clearTenantData, setupIntegrationTest } from '../../unit-test/index.js';
|
|
8
|
+
import { SubjectService } from '../server/subject.service.js';
|
|
9
|
+
import { DefaultAuthenticationAncillaryService } from './authentication.test-ancillary-service.js';
|
|
10
|
+
describe('AuthenticationApiController Integration', () => {
|
|
11
|
+
let injector;
|
|
12
|
+
let database;
|
|
13
|
+
let service;
|
|
14
|
+
let serverService;
|
|
15
|
+
let subjectService;
|
|
16
|
+
let server;
|
|
17
|
+
const schema = 'authentication';
|
|
18
|
+
const tenantId = crypto.randomUUID();
|
|
19
|
+
beforeAll(async () => {
|
|
20
|
+
({ injector, database } = await setupIntegrationTest({
|
|
21
|
+
modules: { authentication: true, audit: true, keyValueStore: true, test: true, api: true, webServer: true },
|
|
22
|
+
authenticationAncillaryService: DefaultAuthenticationAncillaryService,
|
|
23
|
+
}));
|
|
24
|
+
await runInInjectionContext(injector, async () => {
|
|
25
|
+
server = injector.resolve(HttpServer);
|
|
26
|
+
const httpClientOptions = injector.resolve(HttpClientOptions);
|
|
27
|
+
httpClientOptions.baseUrl = `http://localhost:${server.port}`;
|
|
28
|
+
serverService = await injector.resolveAsync(AuthenticationServerService);
|
|
29
|
+
subjectService = await injector.resolveAsync(SubjectService);
|
|
30
|
+
service = await injector.resolveAsync(AuthenticationClientService);
|
|
31
|
+
service.initialize();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
afterAll(async () => {
|
|
35
|
+
await server?.close(1000);
|
|
36
|
+
await injector?.dispose();
|
|
37
|
+
});
|
|
38
|
+
beforeEach(async () => {
|
|
39
|
+
await clearTenantData(database, schema, ['credentials', 'session', 'user', 'service_account', 'system_account', 'subject'], tenantId);
|
|
40
|
+
});
|
|
41
|
+
test('login should work via API client', async () => {
|
|
42
|
+
await runInInjectionContext(injector, async () => {
|
|
43
|
+
const user = await subjectService.createUser({ tenantId, email: 'api-login@example.com', firstName: 'A', lastName: 'L' });
|
|
44
|
+
await serverService.setCredentials(user, 'Strong-Password-2026!');
|
|
45
|
+
await service.login({ tenantId, subject: user.id }, 'Strong-Password-2026!');
|
|
46
|
+
expect(service.isLoggedIn()).toBe(true);
|
|
47
|
+
expect(service.subjectId()).toBe(user.id);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
test('checkSecret should work via API client', async () => {
|
|
51
|
+
const result = await service.checkSecret('abc');
|
|
52
|
+
expect(result.strength).toBeLessThan(2);
|
|
53
|
+
});
|
|
54
|
+
test('refresh should work via API client', async () => {
|
|
55
|
+
await runInInjectionContext(injector, async () => {
|
|
56
|
+
const user = await subjectService.createUser({ tenantId, email: 'api-refresh@example.com', firstName: 'A', lastName: 'L' });
|
|
57
|
+
await serverService.setCredentials(user, 'Strong-Password-2026!');
|
|
58
|
+
await service.login({ tenantId, subject: user.id }, 'Strong-Password-2026!');
|
|
59
|
+
const initialToken = service.token()?.jti;
|
|
60
|
+
await service.refresh();
|
|
61
|
+
expect(service.token()?.jti).not.toBe(initialToken);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
test('impersonation should work via API client', async () => {
|
|
65
|
+
await runInInjectionContext(injector, async () => {
|
|
66
|
+
const admin = await subjectService.createUser({ tenantId, email: 'api-admin@example.com', firstName: 'A', lastName: 'D' });
|
|
67
|
+
const user = await subjectService.createUser({ tenantId, email: 'api-user@example.com', firstName: 'U', lastName: 'S' });
|
|
68
|
+
await serverService.setCredentials(admin, 'Admin-Pass-123!');
|
|
69
|
+
await service.login({ tenantId, subject: admin.id }, 'Admin-Pass-123!');
|
|
70
|
+
await service.impersonate(user.id);
|
|
71
|
+
expect(service.subjectId()).toBe(user.id);
|
|
72
|
+
expect(service.token()?.impersonator).toBe(admin.id);
|
|
73
|
+
await service.unimpersonate();
|
|
74
|
+
expect(service.subjectId()).toBe(admin.id);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
test('secret reset should work via API client', async () => {
|
|
78
|
+
await runInInjectionContext(injector, async () => {
|
|
79
|
+
const user = await subjectService.createUser({ tenantId, email: 'api-reset@example.com', firstName: 'A', lastName: 'L' });
|
|
80
|
+
const ancillaryService = injector.resolve(AuthenticationAncillaryService);
|
|
81
|
+
await service.initResetSecret({ tenantId, subject: user.id }, undefined);
|
|
82
|
+
expect(ancillaryService.lastResetData).toBeDefined();
|
|
83
|
+
await service.resetSecret(ancillaryService.lastResetData.token, 'New-API-Pass-123!');
|
|
84
|
+
await service.login({ tenantId, subject: user.id }, 'New-API-Pass-123!');
|
|
85
|
+
expect(service.isLoggedIn()).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, test } from 'vitest';
|
|
2
|
+
import { AuthenticationApiRequestTokenProvider } from '../../authentication/server/authentication-api-request-token.provider.js';
|
|
3
|
+
import { AuthenticationService } from '../../authentication/server/index.js';
|
|
4
|
+
import { runInInjectionContext } from '../../injector/index.js';
|
|
5
|
+
import { setupIntegrationTest } from '../../unit-test/index.js';
|
|
6
|
+
import { SubjectService } from '../server/subject.service.js';
|
|
7
|
+
describe('AuthenticationApiRequestTokenProvider', () => {
|
|
8
|
+
let injector;
|
|
9
|
+
let authenticationService;
|
|
10
|
+
let subjectService;
|
|
11
|
+
let tokenProvider;
|
|
12
|
+
const tenantId = crypto.randomUUID();
|
|
13
|
+
beforeAll(async () => {
|
|
14
|
+
({ injector } = await setupIntegrationTest({ modules: { authentication: true, test: true } }));
|
|
15
|
+
authenticationService = await injector.resolveAsync(AuthenticationService);
|
|
16
|
+
subjectService = await injector.resolveAsync(SubjectService);
|
|
17
|
+
tokenProvider = injector.resolve(AuthenticationApiRequestTokenProvider);
|
|
18
|
+
});
|
|
19
|
+
afterAll(async () => {
|
|
20
|
+
await injector?.dispose();
|
|
21
|
+
});
|
|
22
|
+
test('should extract and validate token', async () => {
|
|
23
|
+
await runInInjectionContext(injector, async () => {
|
|
24
|
+
const user = await subjectService.createUser({ tenantId, email: 'provider-test@example.com', firstName: 'P', lastName: 'T' });
|
|
25
|
+
const tokenResult = await authenticationService.getToken(user, undefined);
|
|
26
|
+
const request = {
|
|
27
|
+
headers: {
|
|
28
|
+
tryGet: (name) => name == 'Authorization' ? `Bearer ${tokenResult.token}` : undefined,
|
|
29
|
+
},
|
|
30
|
+
cookies: {
|
|
31
|
+
tryGet: () => undefined,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
const data = { request };
|
|
35
|
+
const token = await tokenProvider.tryGetToken(data);
|
|
36
|
+
expect(token.payload.subject).toBe(user.id);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
test('should return null if no token', async () => {
|
|
40
|
+
const request = {
|
|
41
|
+
headers: { tryGet: () => undefined },
|
|
42
|
+
cookies: { tryGet: () => undefined },
|
|
43
|
+
};
|
|
44
|
+
const data = { request };
|
|
45
|
+
const token = await tokenProvider.tryGetToken(data);
|
|
46
|
+
expect(token).toBeNull();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { of } from 'rxjs';
|
|
2
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
3
|
+
import { HttpClientRequest } from '../../http/client/index.js';
|
|
4
|
+
import { waitForAuthenticationCredentialsMiddleware } from '../client/http-client.middleware.js';
|
|
5
|
+
describe('waitForAuthenticationCredentialsMiddleware', () => {
|
|
6
|
+
test('should wait for token and call next', async () => {
|
|
7
|
+
const authenticationServiceMock = {
|
|
8
|
+
token: vi.fn().mockReturnValue({ jti: 'test-token' }),
|
|
9
|
+
validToken$: of({ jti: 'test-token' }),
|
|
10
|
+
hasValidToken: true,
|
|
11
|
+
};
|
|
12
|
+
const middleware = waitForAuthenticationCredentialsMiddleware(authenticationServiceMock);
|
|
13
|
+
const request = new HttpClientRequest('http://localhost');
|
|
14
|
+
request.context = {
|
|
15
|
+
endpoint: {
|
|
16
|
+
credentials: true,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
const next = vi.fn().mockResolvedValue(undefined);
|
|
20
|
+
await middleware({ request }, next);
|
|
21
|
+
expect(next).toHaveBeenCalled();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from 'vitest';
|
|
2
|
+
import { AuthenticationClientService } from '../../authentication/client/index.js';
|
|
3
|
+
import { AuthenticationService as AuthenticationServerService } from '../../authentication/server/index.js';
|
|
4
|
+
import { HttpClientOptions } from '../../http/client/index.js';
|
|
5
|
+
import { HttpServer } from '../../http/server/index.js';
|
|
6
|
+
import { runInInjectionContext } from '../../injector/index.js';
|
|
7
|
+
import { clearTenantData, setupIntegrationTest } from '../../unit-test/index.js';
|
|
8
|
+
import { SubjectService } from '../server/subject.service.js';
|
|
9
|
+
import { DefaultAuthenticationAncillaryService } from './authentication.test-ancillary-service.js';
|
|
10
|
+
describe('AuthenticationClientService Integration', () => {
|
|
11
|
+
let injector;
|
|
12
|
+
let database;
|
|
13
|
+
let service;
|
|
14
|
+
let serverService;
|
|
15
|
+
let subjectService;
|
|
16
|
+
let server;
|
|
17
|
+
const schema = 'authentication';
|
|
18
|
+
const tenantId = crypto.randomUUID();
|
|
19
|
+
beforeAll(async () => {
|
|
20
|
+
({ injector, database } = await setupIntegrationTest({
|
|
21
|
+
modules: { authentication: true, audit: true, keyValueStore: true, test: true, api: true, webServer: true },
|
|
22
|
+
authenticationAncillaryService: DefaultAuthenticationAncillaryService,
|
|
23
|
+
}));
|
|
24
|
+
await runInInjectionContext(injector, async () => {
|
|
25
|
+
server = injector.resolve(HttpServer);
|
|
26
|
+
const httpClientOptions = injector.resolve(HttpClientOptions);
|
|
27
|
+
httpClientOptions.baseUrl = `http://localhost:${server.port}`;
|
|
28
|
+
serverService = await injector.resolveAsync(AuthenticationServerService);
|
|
29
|
+
subjectService = await injector.resolveAsync(SubjectService);
|
|
30
|
+
service = await injector.resolveAsync(AuthenticationClientService);
|
|
31
|
+
service.initialize();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
afterAll(async () => {
|
|
35
|
+
await server?.close(1000);
|
|
36
|
+
await injector?.dispose();
|
|
37
|
+
});
|
|
38
|
+
beforeEach(async () => {
|
|
39
|
+
await clearTenantData(database, schema, ['credentials', 'session', 'user', 'service_account', 'system_account', 'subject'], tenantId);
|
|
40
|
+
});
|
|
41
|
+
test('login and logout should work', async () => {
|
|
42
|
+
await runInInjectionContext(injector, async () => {
|
|
43
|
+
const user = await subjectService.createUser({ tenantId, email: 'client-test@example.com', firstName: 'C', lastName: 'T' });
|
|
44
|
+
await serverService.setCredentials(user, 'Strong-Pass-2026!');
|
|
45
|
+
expect(service.isLoggedIn()).toBe(false);
|
|
46
|
+
await service.login({ tenantId, subject: user.id }, 'Strong-Pass-2026!');
|
|
47
|
+
expect(service.isLoggedIn()).toBe(true);
|
|
48
|
+
expect(service.subjectId()).toBe(user.id);
|
|
49
|
+
await service.logout();
|
|
50
|
+
expect(service.isLoggedIn()).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
test('refresh should work', async () => {
|
|
54
|
+
await runInInjectionContext(injector, async () => {
|
|
55
|
+
const user = await subjectService.createUser({ tenantId, email: 'refresh-test@example.com', firstName: 'R', lastName: 'T' });
|
|
56
|
+
await serverService.setCredentials(user, 'Strong-Pass-2026!');
|
|
57
|
+
await service.login({ tenantId, subject: user.id }, 'Strong-Pass-2026!');
|
|
58
|
+
const initialToken = service.token()?.jti;
|
|
59
|
+
await service.refresh();
|
|
60
|
+
expect(service.token()?.jti).not.toBe(initialToken);
|
|
61
|
+
expect(service.isLoggedIn()).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
test('checkSecret should work', async () => {
|
|
65
|
+
const result = await service.checkSecret('123');
|
|
66
|
+
expect(result.strength).toBeLessThan(2);
|
|
67
|
+
const strongResult = await service.checkSecret('Very-Strong-Password-2026-!@#$');
|
|
68
|
+
expect(strongResult.strength).toBeGreaterThanOrEqual(2);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|