@solidxai/core 0.1.15 → 0.1.16-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1293 -0
- package/dist/commands/run-tests.command.d.ts +3 -1
- package/dist/commands/run-tests.command.d.ts.map +1 -1
- package/dist/commands/run-tests.command.js +6 -2
- package/dist/commands/run-tests.command.js.map +1 -1
- package/dist/controllers/test-run.controller.d.ts +12 -0
- package/dist/controllers/test-run.controller.d.ts.map +1 -0
- package/dist/controllers/test-run.controller.js +54 -0
- package/dist/controllers/test-run.controller.js.map +1 -0
- package/dist/dtos/test-run-request.dto.d.ts +35 -0
- package/dist/dtos/test-run-request.dto.d.ts.map +1 -0
- package/dist/dtos/test-run-request.dto.js +120 -0
- package/dist/dtos/test-run-request.dto.js.map +1 -0
- package/dist/guards/access-token.guard.d.ts +5 -1
- package/dist/guards/access-token.guard.d.ts.map +1 -1
- package/dist/guards/access-token.guard.js +20 -1
- package/dist/guards/access-token.guard.js.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/active-user-data.interface.d.ts +1 -0
- package/dist/interfaces/active-user-data.interface.d.ts.map +1 -1
- package/dist/interfaces/active-user-data.interface.js.map +1 -1
- package/dist/jobs/database/test-run-queue-options-database.d.ts +8 -0
- package/dist/jobs/database/test-run-queue-options-database.d.ts.map +1 -0
- package/dist/jobs/database/test-run-queue-options-database.js +10 -0
- package/dist/jobs/database/test-run-queue-options-database.js.map +1 -0
- package/dist/jobs/database/test-run-queue-publisher-database.service.d.ts +12 -0
- package/dist/jobs/database/test-run-queue-publisher-database.service.d.ts.map +1 -0
- package/dist/jobs/database/test-run-queue-publisher-database.service.js +39 -0
- package/dist/jobs/database/test-run-queue-publisher-database.service.js.map +1 -0
- package/dist/jobs/database/test-run-queue-subscriber-database.service.d.ts +26 -0
- package/dist/jobs/database/test-run-queue-subscriber-database.service.d.ts.map +1 -0
- package/dist/jobs/database/test-run-queue-subscriber-database.service.js +120 -0
- package/dist/jobs/database/test-run-queue-subscriber-database.service.js.map +1 -0
- package/dist/resources/images/solid-core-menu-icon.png +0 -0
- package/dist/seeders/seed-data/solid-core-metadata.json +4 -2
- package/dist/services/access-token-denylist.service.d.ts +16 -0
- package/dist/services/access-token-denylist.service.d.ts.map +1 -0
- package/dist/services/access-token-denylist.service.js +74 -0
- package/dist/services/access-token-denylist.service.js.map +1 -0
- package/dist/services/authentication.service.d.ts +9 -1
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +39 -4
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/import-transaction.service.d.ts +1 -1
- package/dist/services/import-transaction.service.d.ts.map +1 -1
- package/dist/services/import-transaction.service.js +13 -23
- package/dist/services/import-transaction.service.js.map +1 -1
- package/dist/services/module-metadata.service.js +4 -4
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +20 -0
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +11 -0
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/services/workflow-secret.service.d.ts +3 -0
- package/dist/services/workflow-secret.service.d.ts.map +1 -1
- package/dist/services/workflow-secret.service.js +25 -0
- package/dist/services/workflow-secret.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +9 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist/testing/adapters/ui/browser-provisioner.d.ts +5 -0
- package/dist/testing/adapters/ui/browser-provisioner.d.ts.map +1 -0
- package/dist/testing/adapters/ui/browser-provisioner.js +102 -0
- package/dist/testing/adapters/ui/browser-provisioner.js.map +1 -0
- package/dist/testing/adapters/ui/playwright-adapter.d.ts +40 -1
- package/dist/testing/adapters/ui/playwright-adapter.d.ts.map +1 -1
- package/dist/testing/adapters/ui/playwright-adapter.js +185 -3
- package/dist/testing/adapters/ui/playwright-adapter.js.map +1 -1
- package/dist/testing/adapters/ui/ui.types.d.ts +6 -0
- package/dist/testing/adapters/ui/ui.types.d.ts.map +1 -1
- package/dist/testing/adapters/ui/ui.types.js.map +1 -1
- package/dist/testing/contracts/runtime-context.types.d.ts +2 -0
- package/dist/testing/contracts/runtime-context.types.d.ts.map +1 -1
- package/dist/testing/contracts/runtime-context.types.js.map +1 -1
- package/dist/testing/core/interpolation.d.ts +1 -0
- package/dist/testing/core/interpolation.d.ts.map +1 -1
- package/dist/testing/core/interpolation.js +28 -68
- package/dist/testing/core/interpolation.js.map +1 -1
- package/dist/testing/core/path-resolution.spec.d.ts +2 -0
- package/dist/testing/core/path-resolution.spec.d.ts.map +1 -0
- package/dist/testing/core/path-resolution.spec.js +106 -0
- package/dist/testing/core/path-resolution.spec.js.map +1 -0
- package/dist/testing/core/path-segments.d.ts +2 -0
- package/dist/testing/core/path-segments.d.ts.map +1 -0
- package/dist/testing/core/path-segments.js +70 -0
- package/dist/testing/core/path-segments.js.map +1 -0
- package/dist/testing/core/resource-store.d.ts.map +1 -1
- package/dist/testing/core/resource-store.js +5 -2
- package/dist/testing/core/resource-store.js.map +1 -1
- package/dist/testing/core/testing-engine.d.ts.map +1 -1
- package/dist/testing/core/testing-engine.js +16 -0
- package/dist/testing/core/testing-engine.js.map +1 -1
- package/dist/testing/reporter/artifact-sink.d.ts +14 -0
- package/dist/testing/reporter/artifact-sink.d.ts.map +1 -0
- package/dist/testing/reporter/artifact-sink.js +3 -0
- package/dist/testing/reporter/artifact-sink.js.map +1 -0
- package/dist/testing/reporter/console-reporter.d.ts.map +1 -1
- package/dist/testing/reporter/console-reporter.js +7 -0
- package/dist/testing/reporter/console-reporter.js.map +1 -1
- package/dist/testing/reporter/file-service-artifact-sink.d.ts +22 -0
- package/dist/testing/reporter/file-service-artifact-sink.d.ts.map +1 -0
- package/dist/testing/reporter/file-service-artifact-sink.js +31 -0
- package/dist/testing/reporter/file-service-artifact-sink.js.map +1 -0
- package/dist/testing/reporter/lifecycle-events.types.d.ts +67 -0
- package/dist/testing/reporter/lifecycle-events.types.d.ts.map +1 -0
- package/dist/testing/reporter/lifecycle-events.types.js +3 -0
- package/dist/testing/reporter/lifecycle-events.types.js.map +1 -0
- package/dist/testing/reporter/lifecycle-webhook-reporter.d.ts +77 -0
- package/dist/testing/reporter/lifecycle-webhook-reporter.d.ts.map +1 -0
- package/dist/testing/reporter/lifecycle-webhook-reporter.js +275 -0
- package/dist/testing/reporter/lifecycle-webhook-reporter.js.map +1 -0
- package/dist/testing/reporter/progress-reporter.d.ts +3 -3
- package/dist/testing/reporter/progress-reporter.d.ts.map +1 -1
- package/dist/testing/reporter/progress-reporter.js.map +1 -1
- package/dist/testing/reporter/reporter.types.d.ts +13 -1
- package/dist/testing/reporter/reporter.types.d.ts.map +1 -1
- package/dist/testing/reporter/reporter.types.js.map +1 -1
- package/dist/testing/runner/read-scenarios-file.d.ts +9 -0
- package/dist/testing/runner/read-scenarios-file.d.ts.map +1 -0
- package/dist/testing/runner/read-scenarios-file.js +56 -0
- package/dist/testing/runner/read-scenarios-file.js.map +1 -0
- package/dist/testing/runner/run-from-metadata.d.ts +7 -2
- package/dist/testing/runner/run-from-metadata.d.ts.map +1 -1
- package/dist/testing/runner/run-from-metadata.js +57 -6
- package/dist/testing/runner/run-from-metadata.js.map +1 -1
- package/dist/testing/steps/ui/navigation.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/navigation.step.js +12 -12
- package/dist/testing/steps/ui/navigation.step.js.map +1 -1
- package/package.json +4 -2
- package/postman/instant-logout.postman_collection.json +1493 -0
- package/resources/images/solid-core-menu-icon.png +0 -0
- package/src/commands/run-tests.command.ts +3 -0
- package/src/controllers/test-run.controller.ts +44 -0
- package/src/dtos/test-run-request.dto.ts +130 -0
- package/src/guards/access-token.guard.ts +48 -0
- package/src/index.ts +21 -1
- package/src/interfaces/active-user-data.interface.ts +8 -0
- package/src/jobs/database/test-run-queue-options-database.ts +9 -0
- package/src/jobs/database/test-run-queue-publisher-database.service.ts +24 -0
- package/src/jobs/database/test-run-queue-subscriber-database.service.ts +122 -0
- package/src/seeders/seed-data/solid-core-metadata.json +4 -2
- package/src/services/access-token-denylist.service.ts +145 -0
- package/src/services/authentication.service.ts +118 -2
- package/src/services/import-transaction.service.ts +19 -36
- package/src/services/module-metadata.service.ts +4 -4
- package/src/services/settings/default-settings-provider.service.ts +12 -0
- package/src/services/workflow-secret.service.ts +61 -2
- package/src/solid-core.module.ts +11 -0
- package/src/testing/README.md +44 -1
- package/src/testing/adapters/ui/browser-provisioner.ts +115 -0
- package/src/testing/adapters/ui/playwright-adapter.ts +255 -5
- package/src/testing/adapters/ui/ui.types.ts +14 -0
- package/src/testing/contracts/runtime-context.types.ts +6 -0
- package/src/testing/core/interpolation.ts +39 -69
- package/src/testing/core/path-resolution.spec.ts +133 -0
- package/src/testing/core/path-segments.ts +81 -0
- package/src/testing/core/resource-store.ts +8 -2
- package/src/testing/core/testing-engine.ts +22 -0
- package/src/testing/reporter/artifact-sink.ts +16 -0
- package/src/testing/reporter/console-reporter.ts +9 -0
- package/src/testing/reporter/file-service-artifact-sink.ts +46 -0
- package/src/testing/reporter/lifecycle-events.types.ts +103 -0
- package/src/testing/reporter/lifecycle-webhook-reporter.ts +385 -0
- package/src/testing/reporter/progress-reporter.ts +3 -1
- package/src/testing/reporter/reporter.types.ts +10 -1
- package/src/testing/runner/read-scenarios-file.ts +44 -0
- package/src/testing/runner/run-from-metadata.ts +102 -9
- package/src/testing/steps/ui/navigation.step.ts +24 -20
- package/dist/services/access-token-storage.service.d.ts +0 -1
- package/dist/services/access-token-storage.service.d.ts.map +0 -1
- package/dist/services/access-token-storage.service.js +0 -1
- package/dist/services/access-token-storage.service.js.map +0 -1
- package/src/services/access-token-storage.service.ts +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"displayName": "Solid Core",
|
|
5
5
|
"description": "Solid Core Module",
|
|
6
6
|
"defaultDataSource": "default",
|
|
7
|
-
"menuIconUrl":
|
|
7
|
+
"menuIconUrl": "media-files-storage/solid-core-menu-icon.png",
|
|
8
8
|
"menuSequenceNumber": 1,
|
|
9
9
|
"isSystem": true,
|
|
10
10
|
"models": [
|
|
@@ -14958,6 +14958,7 @@
|
|
|
14958
14958
|
"enableGlobalSearch": true,
|
|
14959
14959
|
"create": false,
|
|
14960
14960
|
"edit": false,
|
|
14961
|
+
"delete": false,
|
|
14961
14962
|
"import": false,
|
|
14962
14963
|
"export": false,
|
|
14963
14964
|
"allowedViews": [
|
|
@@ -15089,7 +15090,8 @@
|
|
|
15089
15090
|
"label": "User Activity History",
|
|
15090
15091
|
"className": "grid",
|
|
15091
15092
|
"showAddFormButton": false,
|
|
15092
|
-
"showEditFormButton": false
|
|
15093
|
+
"showEditFormButton": false,
|
|
15094
|
+
"showDeleteFormButton": false
|
|
15093
15095
|
},
|
|
15094
15096
|
"children": [
|
|
15095
15097
|
{
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Cache } from "cache-manager";
|
|
2
|
+
import { SettingService } from "./setting.service";
|
|
3
|
+
export declare class AccessTokenDenylistService {
|
|
4
|
+
private readonly cacheManager;
|
|
5
|
+
private readonly settingService;
|
|
6
|
+
constructor(cacheManager: Cache, settingService: SettingService);
|
|
7
|
+
isEnabled(): boolean;
|
|
8
|
+
revokeSession(userId: number, sessionKey?: string): Promise<void>;
|
|
9
|
+
revokeAllForUser(userId: number): Promise<void>;
|
|
10
|
+
isRevoked(userId: number, sessionKey: string, issuedAtSeconds?: number): Promise<boolean>;
|
|
11
|
+
private revokedAt;
|
|
12
|
+
private getSessionKey;
|
|
13
|
+
private getUserKey;
|
|
14
|
+
private getEntryTtlMs;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=access-token-denylist.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-token-denylist.service.d.ts","sourceRoot":"","sources":["../../src/services/access-token-denylist.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA6BnD,qBACa,0BAA0B;IAEZ,OAAO,CAAC,QAAQ,CAAC,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,cAAc;gBADS,YAAY,EAAE,KAAK,EAC1C,cAAc,EAAE,cAAc;IAGjD,SAAS,IAAI,OAAO;IAad,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBjE,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB/C,SAAS,CACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,OAAO,CAAC;IA8BnB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,aAAa;CAMtB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.AccessTokenDenylistService = void 0;
|
|
16
|
+
const cache_manager_1 = require("@nestjs/cache-manager");
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const setting_service_1 = require("./setting.service");
|
|
19
|
+
const ENTRY_TTL_BUFFER_SECONDS = 60;
|
|
20
|
+
let AccessTokenDenylistService = class AccessTokenDenylistService {
|
|
21
|
+
constructor(cacheManager, settingService) {
|
|
22
|
+
this.cacheManager = cacheManager;
|
|
23
|
+
this.settingService = settingService;
|
|
24
|
+
}
|
|
25
|
+
isEnabled() {
|
|
26
|
+
return (this.settingService.getConfigValue("invalidateAccessTokenOnLogout") === true);
|
|
27
|
+
}
|
|
28
|
+
async revokeSession(userId, sessionKey) {
|
|
29
|
+
if (!this.isEnabled() || !sessionKey) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
await this.cacheManager.set(this.getSessionKey(userId, sessionKey), this.revokedAt(), this.getEntryTtlMs());
|
|
33
|
+
}
|
|
34
|
+
async revokeAllForUser(userId) {
|
|
35
|
+
if (!this.isEnabled()) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
await this.cacheManager.set(this.getUserKey(userId), this.revokedAt(), this.getEntryTtlMs());
|
|
39
|
+
}
|
|
40
|
+
async isRevoked(userId, sessionKey, issuedAtSeconds) {
|
|
41
|
+
if (!this.isEnabled()) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (typeof issuedAtSeconds !== "number") {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
const [sessionRevokedAt, userRevokedAt] = await Promise.all([
|
|
48
|
+
this.cacheManager.get(this.getSessionKey(userId, sessionKey)),
|
|
49
|
+
this.cacheManager.get(this.getUserKey(userId)),
|
|
50
|
+
]);
|
|
51
|
+
const revokedAt = Math.max(sessionRevokedAt ?? 0, userRevokedAt ?? 0);
|
|
52
|
+
return issuedAtSeconds * 1000 < revokedAt;
|
|
53
|
+
}
|
|
54
|
+
revokedAt() {
|
|
55
|
+
return (Math.floor(Date.now() / 1000) + 1) * 1000;
|
|
56
|
+
}
|
|
57
|
+
getSessionKey(userId, sessionKey) {
|
|
58
|
+
return `revoked-session-${userId}-${sessionKey}`;
|
|
59
|
+
}
|
|
60
|
+
getUserKey(userId) {
|
|
61
|
+
return `revoked-user-${userId}`;
|
|
62
|
+
}
|
|
63
|
+
getEntryTtlMs() {
|
|
64
|
+
const accessTokenTtlSeconds = Number(this.settingService.getConfigValue("accessTokenTtl"));
|
|
65
|
+
return (accessTokenTtlSeconds + ENTRY_TTL_BUFFER_SECONDS) * 1000;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
exports.AccessTokenDenylistService = AccessTokenDenylistService;
|
|
69
|
+
exports.AccessTokenDenylistService = AccessTokenDenylistService = __decorate([
|
|
70
|
+
(0, common_1.Injectable)(),
|
|
71
|
+
__param(0, (0, common_1.Inject)(cache_manager_1.CACHE_MANAGER)),
|
|
72
|
+
__metadata("design:paramtypes", [Object, setting_service_1.SettingService])
|
|
73
|
+
], AccessTokenDenylistService);
|
|
74
|
+
//# sourceMappingURL=access-token-denylist.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-token-denylist.service.js","sourceRoot":"","sources":["../../src/services/access-token-denylist.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,yDAAsD;AACtD,2CAAoD;AAGpD,uDAAmD;AAOnD,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAuB7B,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IACrC,YAC0C,YAAmB,EAC1C,cAA8B;QADP,iBAAY,GAAZ,YAAY,CAAO;QAC1C,mBAAc,GAAd,cAAc,CAAgB;IAC9C,CAAC;IAEJ,SAAS;QACP,OAAO,CACL,IAAI,CAAC,cAAc,CAAC,cAAc,CAChC,+BAA+B,CAChC,KAAK,IAAI,CACX,CAAC;IACJ,CAAC;IAOD,KAAK,CAAC,aAAa,CAAC,MAAc,EAAE,UAAmB;QACrD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QACD,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CACzB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,EACtC,IAAI,CAAC,SAAS,EAAE,EAChB,IAAI,CAAC,aAAa,EAAE,CACrB,CAAC;IACJ,CAAC;IASD,KAAK,CAAC,gBAAgB,CAAC,MAAc;QACnC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CACzB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EACvB,IAAI,CAAC,SAAS,EAAE,EAChB,IAAI,CAAC,aAAa,EAAE,CACrB,CAAC;IACJ,CAAC;IASD,KAAK,CAAC,SAAS,CACb,MAAc,EACd,UAAkB,EAClB,eAAwB;QAExB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QAKD,IAAI,OAAO,eAAe,KAAK,QAAQ,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC1D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAS,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YACrE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAS,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;SACvD,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,EAAE,aAAa,IAAI,CAAC,CAAC,CAAC;QACtE,OAAO,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,CAAC;IAWO,SAAS;QACf,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;IACpD,CAAC;IAEO,aAAa,CAAC,MAAc,EAAE,UAAkB;QACtD,OAAO,mBAAmB,MAAM,IAAI,UAAU,EAAE,CAAC;IACnD,CAAC;IAEO,UAAU,CAAC,MAAc;QAC/B,OAAO,gBAAgB,MAAM,EAAE,CAAC;IAClC,CAAC;IAKO,aAAa;QACnB,MAAM,qBAAqB,GAAG,MAAM,CAClC,IAAI,CAAC,cAAc,CAAC,cAAc,CAAmB,gBAAgB,CAAC,CACvE,CAAC;QACF,OAAO,CAAC,qBAAqB,GAAG,wBAAwB,CAAC,GAAG,IAAI,CAAC;IACnE,CAAC;CACF,CAAA;AA9GY,gEAA0B;qCAA1B,0BAA0B;IADtC,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,6BAAa,CAAC,CAAA;6CACW,gCAAc;GAHtC,0BAA0B,CA8GtC","sourcesContent":["import { CACHE_MANAGER } from \"@nestjs/cache-manager\";\nimport { Inject, Injectable } from \"@nestjs/common\";\nimport { Cache } from \"cache-manager\";\nimport type { SolidCoreSetting } from \"src/services/settings/default-settings-provider.service\";\nimport { SettingService } from \"./setting.service\";\n\n// The denylist entry must outlive the longest-lived access token it could\n// match. Any token an entry rejects was issued before the revocation, so it\n// dies by revokedAt + accessTokenTtl at the latest; after that `exp` rejects it\n// and the entry is dead weight. Mirrors STATE_TTL_BUFFER_SECONDS in\n// refresh-token-ids-storage.service.ts.\nconst ENTRY_TTL_BUFFER_SECONDS = 60;\n\n/**\n * Immediate access-token revocation, opt-in via `invalidateAccessTokenOnLogout`.\n *\n * Entries record WHEN a session was revoked rather than merely that it was, and\n * the guard compares that instant against the token's own `iat`. The timestamp\n * is what makes a session-scoped key safe: some keys are reused across logins -\n * API-key auth passes a stable `apikey-<id>` deviceKey, and the per-user key\n * below is shared by every login that user will ever make - so a boolean entry\n * would have to either reject the newly minted token too, or be cleared on\n * re-issue and thereby revive the still-unexpired token the logout killed.\n * Comparing against `iat` needs neither: tokens minted after the revocation\n * pass, tokens minted before it fail, and nothing is ever cleared.\n *\n * This service owns the setting check - callers never branch on it. One source\n * of truth instead of three call sites that can drift, no `if (enabled)` nesting\n * in logout(), and a consuming project using the public seam cannot write\n * entries that nothing will ever read. `getConfigValue` is a synchronous\n * in-memory lookup, so a deployment that has not opted in pays nothing and\n * issues no I/O.\n */\n@Injectable()\nexport class AccessTokenDenylistService {\n constructor(\n @Inject(CACHE_MANAGER) private readonly cacheManager: Cache,\n private readonly settingService: SettingService,\n ) {}\n\n isEnabled(): boolean {\n return (\n this.settingService.getConfigValue<SolidCoreSetting>(\n \"invalidateAccessTokenOnLogout\",\n ) === true\n );\n }\n\n /**\n * Revoke every access token belonging to one session. A no-op when the\n * feature is off, and when no session key could be resolved - which spares\n * the caller a null check.\n */\n async revokeSession(userId: number, sessionKey?: string): Promise<void> {\n if (!this.isEnabled() || !sessionKey) {\n return;\n }\n await this.cacheManager.set(\n this.getSessionKey(userId, sessionKey),\n this.revokedAt(),\n this.getEntryTtlMs(),\n );\n }\n\n /**\n * Revoke every access token for a user, across all sessions - `allDevices`.\n *\n * Needs no claim on the token and no enumeration of buckets: every\n * outstanding token was necessarily issued before the logout that writes\n * this, so one entry sweeps them all.\n */\n async revokeAllForUser(userId: number): Promise<void> {\n if (!this.isEnabled()) {\n return;\n }\n await this.cacheManager.set(\n this.getUserKey(userId),\n this.revokedAt(),\n this.getEntryTtlMs(),\n );\n }\n\n /**\n * True when the token was issued before either revocation instant that could\n * apply to it - its own session's, or its user's.\n *\n * Returns false without touching the cache when the feature is off, which is\n * why the guard needs no setting check of its own.\n */\n async isRevoked(\n userId: number,\n sessionKey: string,\n issuedAtSeconds?: number,\n ): Promise<boolean> {\n if (!this.isEnabled()) {\n return false;\n }\n\n // A token with no `iat` cannot be placed relative to a revocation. Tokens\n // signed by @nestjs/jwt always carry one, so this is a malformed-payload\n // guard rather than a real case; refuse rather than fail open.\n if (typeof issuedAtSeconds !== \"number\") {\n return true;\n }\n\n const [sessionRevokedAt, userRevokedAt] = await Promise.all([\n this.cacheManager.get<number>(this.getSessionKey(userId, sessionKey)),\n this.cacheManager.get<number>(this.getUserKey(userId)),\n ]);\n\n const revokedAt = Math.max(sessionRevokedAt ?? 0, userRevokedAt ?? 0);\n return issuedAtSeconds * 1000 < revokedAt;\n }\n\n /**\n * `iat` has whole-second resolution, so a token minted in the same second as\n * the revocation is indistinguishable from one minted just before it.\n * Rounding up resolves that ambiguity toward revoking: an automated client\n * re-authenticating inside the window gets one 401 and succeeds on retry,\n * whereas rounding down would leave a genuinely revoked token valid for up to\n * a second. No human path can reach the window at all - logout invalidates\n * the refresh token, so the next access token only exists after a fresh login.\n */\n private revokedAt(): number {\n return (Math.floor(Date.now() / 1000) + 1) * 1000;\n }\n\n private getSessionKey(userId: number, sessionKey: string): string {\n return `revoked-session-${userId}-${sessionKey}`;\n }\n\n private getUserKey(userId: number): string {\n return `revoked-user-${userId}`;\n }\n\n // cache-manager v5 expects milliseconds; accessTokenTtl is configured in\n // seconds. Read from the setting rather than hardcoded so that raising\n // accessTokenTtl keeps entries long enough to outlive the tokens they match.\n private getEntryTtlMs(): number {\n const accessTokenTtlSeconds = Number(\n this.settingService.getConfigValue<SolidCoreSetting>(\"accessTokenTtl\"),\n );\n return (accessTokenTtlSeconds + ENTRY_TTL_BUFFER_SECONDS) * 1000;\n }\n}\n"]}
|
|
@@ -16,6 +16,7 @@ import { SignUpDto } from "../dtos/sign-up.dto";
|
|
|
16
16
|
import { User } from "../entities/user.entity";
|
|
17
17
|
import { ActiveUserData } from "../interfaces/active-user-data.interface";
|
|
18
18
|
import { ActiveSessionStorageService } from "./active-session-storage.service";
|
|
19
|
+
import { AccessTokenDenylistService } from "./access-token-denylist.service";
|
|
19
20
|
import { HashingService } from "./hashing.service";
|
|
20
21
|
import { RefreshTokenIdsStorageService } from "./refresh-token-ids-storage.service";
|
|
21
22
|
import { SsoCodeStorageService } from "./sso-code-storage.service";
|
|
@@ -33,6 +34,7 @@ export declare class AuthenticationService {
|
|
|
33
34
|
private readonly hashingService;
|
|
34
35
|
private readonly jwtService;
|
|
35
36
|
private readonly activeSessionStorage;
|
|
37
|
+
private readonly accessTokenDenylist;
|
|
36
38
|
private readonly refreshTokenIdsStorage;
|
|
37
39
|
private readonly httpService;
|
|
38
40
|
private readonly mailServiceFactory;
|
|
@@ -47,7 +49,7 @@ export declare class AuthenticationService {
|
|
|
47
49
|
private readonly dataSource;
|
|
48
50
|
private readonly solidRegistry;
|
|
49
51
|
private readonly logger;
|
|
50
|
-
constructor(userService: UserService, userRepository: UserRepository, hashingService: HashingService, jwtService: JwtService, activeSessionStorage: ActiveSessionStorageService, refreshTokenIdsStorage: RefreshTokenIdsStorageService, httpService: HttpService, mailServiceFactory: MailFactory, smsFactory: SmsFactory, whatsAppFactory: WhatsAppFactory, eventEmitter: EventEmitter2, settingService: SettingService, roleMetadataService: RoleMetadataService, userActivityHistoryService: UserActivityHistoryService, ssoCodeStorage: SsoCodeStorageService, metadataValidationService: MetadataValidationService, dataSource: DataSource, solidRegistry: SolidRegistry);
|
|
52
|
+
constructor(userService: UserService, userRepository: UserRepository, hashingService: HashingService, jwtService: JwtService, activeSessionStorage: ActiveSessionStorageService, accessTokenDenylist: AccessTokenDenylistService, refreshTokenIdsStorage: RefreshTokenIdsStorageService, httpService: HttpService, mailServiceFactory: MailFactory, smsFactory: SmsFactory, whatsAppFactory: WhatsAppFactory, eventEmitter: EventEmitter2, settingService: SettingService, roleMetadataService: RoleMetadataService, userActivityHistoryService: UserActivityHistoryService, ssoCodeStorage: SsoCodeStorageService, metadataValidationService: MetadataValidationService, dataSource: DataSource, solidRegistry: SolidRegistry);
|
|
51
53
|
private getCompanyLogo;
|
|
52
54
|
resolveUser(username: string, email: string): Promise<User>;
|
|
53
55
|
private resolveUserForPasswordSignIn;
|
|
@@ -238,6 +240,12 @@ export declare class AuthenticationService {
|
|
|
238
240
|
logout(refreshToken: string, allDevices?: boolean): Promise<{
|
|
239
241
|
message: string;
|
|
240
242
|
}>;
|
|
243
|
+
private ownsLiveSession;
|
|
244
|
+
private resolveRevocationKey;
|
|
245
|
+
resolveSessionRevocationKey(refreshToken: string): Promise<{
|
|
246
|
+
userId: number;
|
|
247
|
+
revocationKey?: string;
|
|
248
|
+
} | null>;
|
|
241
249
|
private verifyRefreshTokenForLogout;
|
|
242
250
|
activateUser(userId: number): Promise<void>;
|
|
243
251
|
me(activeUser: ActiveUserData): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authentication.service.d.ts","sourceRoot":"","sources":["../../src/services/authentication.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAY5C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAoB,UAAU,EAAE,MAAM,SAAS,CAAC;AAOhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAEL,6BAA6B,EAC9B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAa3D,qBACa,qBAAqB;IAI9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IACrC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAEnC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IACpC,OAAO,CAAC,QAAQ,CAAC,0BAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAG1C,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"authentication.service.d.ts","sourceRoot":"","sources":["../../src/services/authentication.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,7 @@ const constants_1 = require("../constants");
|
|
|
31
31
|
const user_entity_1 = require("../entities/user.entity");
|
|
32
32
|
const interfaces_1 = require("../interfaces");
|
|
33
33
|
const active_session_storage_service_1 = require("./active-session-storage.service");
|
|
34
|
+
const access_token_denylist_service_1 = require("./access-token-denylist.service");
|
|
34
35
|
const hashing_service_1 = require("./hashing.service");
|
|
35
36
|
const refresh_token_ids_storage_service_1 = require("./refresh-token-ids-storage.service");
|
|
36
37
|
const sso_code_storage_service_1 = require("./sso-code-storage.service");
|
|
@@ -49,12 +50,13 @@ var LoginProvider;
|
|
|
49
50
|
LoginProvider["OTP"] = "otp";
|
|
50
51
|
})(LoginProvider || (LoginProvider = {}));
|
|
51
52
|
let AuthenticationService = AuthenticationService_1 = class AuthenticationService {
|
|
52
|
-
constructor(userService, userRepository, hashingService, jwtService, activeSessionStorage, refreshTokenIdsStorage, httpService, mailServiceFactory, smsFactory, whatsAppFactory, eventEmitter, settingService, roleMetadataService, userActivityHistoryService, ssoCodeStorage, metadataValidationService, dataSource, solidRegistry) {
|
|
53
|
+
constructor(userService, userRepository, hashingService, jwtService, activeSessionStorage, accessTokenDenylist, refreshTokenIdsStorage, httpService, mailServiceFactory, smsFactory, whatsAppFactory, eventEmitter, settingService, roleMetadataService, userActivityHistoryService, ssoCodeStorage, metadataValidationService, dataSource, solidRegistry) {
|
|
53
54
|
this.userService = userService;
|
|
54
55
|
this.userRepository = userRepository;
|
|
55
56
|
this.hashingService = hashingService;
|
|
56
57
|
this.jwtService = jwtService;
|
|
57
58
|
this.activeSessionStorage = activeSessionStorage;
|
|
59
|
+
this.accessTokenDenylist = accessTokenDenylist;
|
|
58
60
|
this.refreshTokenIdsStorage = refreshTokenIdsStorage;
|
|
59
61
|
this.httpService = httpService;
|
|
60
62
|
this.mailServiceFactory = mailServiceFactory;
|
|
@@ -1490,11 +1492,16 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
|
|
|
1490
1492
|
const userId = payload.sub;
|
|
1491
1493
|
if (allDevices) {
|
|
1492
1494
|
await this.refreshTokenIdsStorage.invalidateAll(userId);
|
|
1495
|
+
await this.accessTokenDenylist.revokeAllForUser(userId);
|
|
1493
1496
|
}
|
|
1494
|
-
else {
|
|
1497
|
+
else if (await this.ownsLiveSession(userId, payload, refreshToken)) {
|
|
1495
1498
|
await this.refreshTokenIdsStorage.invalidate(userId, payload.deviceKey);
|
|
1499
|
+
await this.accessTokenDenylist.revokeSession(userId, await this.resolveRevocationKey(userId, payload));
|
|
1500
|
+
await this.activeSessionStorage.clearActiveSession(userId);
|
|
1501
|
+
}
|
|
1502
|
+
else {
|
|
1503
|
+
this.logger.warn(`logout: refresh token does not match the live session for user ${userId}; nothing invalidated`);
|
|
1496
1504
|
}
|
|
1497
|
-
await this.activeSessionStorage.clearActiveSession(userId);
|
|
1498
1505
|
const user = await this.userRepository.findOne({
|
|
1499
1506
|
where: {
|
|
1500
1507
|
id: userId,
|
|
@@ -1512,6 +1519,33 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
|
|
|
1512
1519
|
: new common_1.InternalServerErrorException(error_messages_1.ERROR_MESSAGES.LOGOUT_FAILED);
|
|
1513
1520
|
}
|
|
1514
1521
|
}
|
|
1522
|
+
async ownsLiveSession(userId, payload, refreshToken) {
|
|
1523
|
+
if (payload.deviceKey) {
|
|
1524
|
+
return true;
|
|
1525
|
+
}
|
|
1526
|
+
const state = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(userId);
|
|
1527
|
+
return (state?.currentRefreshToken === refreshToken ||
|
|
1528
|
+
(!!state?.previousRefreshToken &&
|
|
1529
|
+
state.previousRefreshToken === refreshToken));
|
|
1530
|
+
}
|
|
1531
|
+
async resolveRevocationKey(userId, payload) {
|
|
1532
|
+
return (payload.deviceKey ??
|
|
1533
|
+
(await this.activeSessionStorage.getActiveSession(userId)));
|
|
1534
|
+
}
|
|
1535
|
+
async resolveSessionRevocationKey(refreshToken) {
|
|
1536
|
+
const payload = await this.verifyRefreshTokenForLogout(refreshToken);
|
|
1537
|
+
if (!payload?.sub) {
|
|
1538
|
+
return null;
|
|
1539
|
+
}
|
|
1540
|
+
const userId = payload.sub;
|
|
1541
|
+
if (!(await this.ownsLiveSession(userId, payload, refreshToken))) {
|
|
1542
|
+
return { userId };
|
|
1543
|
+
}
|
|
1544
|
+
return {
|
|
1545
|
+
userId,
|
|
1546
|
+
revocationKey: await this.resolveRevocationKey(userId, payload),
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1515
1549
|
async verifyRefreshTokenForLogout(refreshToken) {
|
|
1516
1550
|
try {
|
|
1517
1551
|
const payload = await this.jwtService.verifyAsync(refreshToken, {
|
|
@@ -1590,12 +1624,13 @@ AuthenticationService.SIGNUP_DTO_KEYS = new Set([
|
|
|
1590
1624
|
]);
|
|
1591
1625
|
exports.AuthenticationService = AuthenticationService = AuthenticationService_1 = __decorate([
|
|
1592
1626
|
(0, common_1.Injectable)(),
|
|
1593
|
-
__param(
|
|
1627
|
+
__param(17, (0, typeorm_1.InjectDataSource)()),
|
|
1594
1628
|
__metadata("design:paramtypes", [user_service_1.UserService,
|
|
1595
1629
|
user_repository_1.UserRepository,
|
|
1596
1630
|
hashing_service_1.HashingService,
|
|
1597
1631
|
jwt_1.JwtService,
|
|
1598
1632
|
active_session_storage_service_1.ActiveSessionStorageService,
|
|
1633
|
+
access_token_denylist_service_1.AccessTokenDenylistService,
|
|
1599
1634
|
refresh_token_ids_storage_service_1.RefreshTokenIdsStorageService,
|
|
1600
1635
|
axios_1.HttpService,
|
|
1601
1636
|
mail_factory_1.MailFactory,
|