@nsshunt/stsappframework 3.1.110 → 3.1.112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -41,4 +41,5 @@ __exportStar(require("./stsTransportLoggerWinston"), exports);
41
41
  __exportStar(require("./ipcMessageProcessorPrimary"), exports);
42
42
  __exportStar(require("./ipcMessageProcessorWorker"), exports);
43
43
  __exportStar(require("./ipcMessageManager"), exports);
44
+ __exportStar(require("./testHelpers"), exports);
44
45
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B;AAC7B,mDAAgC;AAChC,6CAA0B;AAC1B,kDAA+B;AAC/B,kDAA+B;AAC/B,sDAAmC;AACnC,sDAAmC;AACnC,sDAAmC;AACnC,sDAAmC;AACnC,yDAAsC;AACtC,yDAAsC;AACtC,oDAAiC;AACjC,uDAAoC;AACpC,wDAAqC;AACrC,wDAAqC;AACrC,yDAAsC;AACtC,6DAA0C;AAC1C,iEAA8C;AAC9C,oEAAiD;AACjD,kEAA+C;AAC/C,mEAAgD;AAChD,8EAA2D;AAC3D,wDAAqC;AACrC,8DAA2C;AAC3C,+DAA4C;AAC5C,8DAA2C;AAC3C,sDAAmC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B;AAC7B,mDAAgC;AAChC,6CAA0B;AAC1B,kDAA+B;AAC/B,kDAA+B;AAC/B,sDAAmC;AACnC,sDAAmC;AACnC,sDAAmC;AACnC,sDAAmC;AACnC,yDAAsC;AACtC,yDAAsC;AACtC,oDAAiC;AACjC,uDAAoC;AACpC,wDAAqC;AACrC,wDAAqC;AACrC,yDAAsC;AACtC,6DAA0C;AAC1C,iEAA8C;AAC9C,oEAAiD;AACjD,kEAA+C;AAC/C,mEAAgD;AAChD,8EAA2D;AAC3D,wDAAqC;AACrC,8DAA2C;AAC3C,+DAA4C;AAC5C,8DAA2C;AAC3C,sDAAmC;AACnC,gDAA6B"}
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.TestHelper = void 0;
30
+ /* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
31
+ const chalk_1 = __importDefault(require("chalk"));
32
+ const tough = __importStar(require("tough-cookie"));
33
+ const https_1 = __importDefault(require("https"));
34
+ const crypto_1 = __importDefault(require("crypto"));
35
+ const axios_1 = __importDefault(require("axios"));
36
+ const testcontainers_1 = require("testcontainers");
37
+ const stsconfig_1 = require("@nsshunt/stsconfig");
38
+ let goptions = (0, stsconfig_1.$Options)();
39
+ const stsutils_1 = require("@nsshunt/stsutils");
40
+ const authutilsnode_1 = require("./authutilsnode");
41
+ class TestHelper {
42
+ //#regexBase64URL = /^[A-Za-z0-9_-]+$/ // Base64URL - https://base64.guru/standards/base64url
43
+ #regexURLSafeStringComponent = /[-a-zA-Z0-9@:%._+~#=]{1,256}/; // URL safe string component
44
+ //#regexBase64 = /(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?/ // Base64 - https://stackoverflow.com/questions/475074/regex-to-parse-or-validate-base64-data
45
+ #regexSTSBase64 = /SES_(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?/; // Base64
46
+ #regexJWT = /[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+/; // JWT (Base64URL.Base64URL.Base64URL)
47
+ #authUtilsNode = new authutilsnode_1.AuthUtilsNode(stsutils_1.defaultLogger);
48
+ #databaseContainer;
49
+ #stsAuthContainer;
50
+ #network;
51
+ #authEndpoint = '';
52
+ #authPort = '';
53
+ #authHost = '';
54
+ #httpsAgent = null;
55
+ constructor() {
56
+ this.#authEndpoint = 'https://localhost:3002'; //@@
57
+ }
58
+ LogDebugMessage(message) {
59
+ stsutils_1.defaultLogger.debug(message);
60
+ }
61
+ #GetHttpsAgent = () => {
62
+ if (this.#httpsAgent === null) {
63
+ // https://nodejs.org/api/http.html#class-httpagent
64
+ this.#httpsAgent = new https_1.default.Agent({
65
+ keepAlive: goptions.keepAlive,
66
+ maxSockets: goptions.maxSockets,
67
+ maxTotalSockets: goptions.maxTotalSockets,
68
+ maxFreeSockets: goptions.maxFreeSockets,
69
+ timeout: goptions.timeout,
70
+ rejectUnauthorized: false
71
+ });
72
+ }
73
+ return this.#httpsAgent;
74
+ };
75
+ StartNetwork = async () => {
76
+ this.#network = await new testcontainers_1.Network().start();
77
+ };
78
+ StopNetwork = async () => {
79
+ await this.#network.stop();
80
+ };
81
+ get network() {
82
+ return this.#network;
83
+ }
84
+ get authPort() {
85
+ return this.#authPort;
86
+ }
87
+ get authHost() {
88
+ return this.#authHost;
89
+ }
90
+ get authEndpoint() {
91
+ return this.#authEndpoint;
92
+ }
93
+ get getHttpsAgent() {
94
+ return this.#GetHttpsAgent();
95
+ }
96
+ CreateRandomString = () => {
97
+ const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~.'; // /[0-9A-Za-z\-_~.]/
98
+ let random = '';
99
+ const randomValues = Array.from(crypto_1.default.getRandomValues(new Uint8Array(43)));
100
+ randomValues.forEach(v => (random += charset[v % charset.length]));
101
+ return random;
102
+ };
103
+ Login = async (username, password) => {
104
+ const client_id = process.env.CLIENT_ID;
105
+ const nonce = crypto_1.default.randomBytes(43).toString('base64'); //CreateRandomString();
106
+ const response_type = 'code';
107
+ const redirect_uri = process.env.REDIRECT_URI;
108
+ const response_mode = 'query';
109
+ const scope = process.env.SCOPE;
110
+ const state = crypto_1.default.randomBytes(43).toString('base64'); // CreateRandomString();
111
+ const code_verifier = this.CreateRandomString();
112
+ const code_challenge = crypto_1.default.createHash('sha256').update(code_verifier).digest('base64');
113
+ const code_challenge_method = 'S256';
114
+ const authoriseOptions = {
115
+ email: username,
116
+ password,
117
+ client_id,
118
+ nonce,
119
+ response_type,
120
+ redirect_uri,
121
+ response_mode,
122
+ scope,
123
+ state,
124
+ code_challenge,
125
+ code_challenge_method
126
+ };
127
+ const url = `${this.#authEndpoint}${goptions.asapiroot}/login`;
128
+ const headers = { 'Content-Type': 'application/json' };
129
+ const retVal = await (0, axios_1.default)({
130
+ url,
131
+ method: 'post',
132
+ data: authoriseOptions,
133
+ headers: headers,
134
+ httpsAgent: this.#GetHttpsAgent()
135
+ });
136
+ //const cookieString = retVal.headers['set-cookie'];
137
+ /*
138
+ const api = request(this.#endpoint);
139
+ const retVal: any = await (api as any)
140
+ .post(`${goptions.asapiroot}/login`)
141
+ .send(authoriseOptions)
142
+ //.expect('set-cookie', /consent_cookie=.*; Max-Age=86; Path=\/; Expires=.*; HttpOnly; Secure; SameSite=Strict/);
143
+
144
+ const cookieString = retVal.header['set-cookie'];
145
+
146
+ if (cookieString) {
147
+ retVal.cookie = new Cookie(cookieString[0]);
148
+ }
149
+ */
150
+ return retVal;
151
+ };
152
+ /*
153
+ GetAuthServerAPITokenFromServer = async (): Promise<string> => {
154
+ return await this.#authUtilsNode.GetAPITokenFromAuthServer(STSClientID.STSTestingService,
155
+ "eN9u0mHZLGWZrdnE1zit2vL6xwUFW466sTZcbkXDml5KWxlvKaZ1uiOZmA==",
156
+ goptions.asapiidentifier, this.#authEndpoint)
157
+ }
158
+ */
159
+ ValidateJWT = async (token) => {
160
+ return await this.#authUtilsNode.ValidateJWT(token, goptions.asapiidentifier, this.#authEndpoint);
161
+ };
162
+ StartDatabase = async () => {
163
+ this.#databaseContainer = await new testcontainers_1.GenericContainer("postgres")
164
+ .withExposedPorts(5432)
165
+ .withEnvironment({
166
+ POSTGRES_PASSWORD: "postgres",
167
+ //UV_THREADPOOL_SIZE: "64"
168
+ })
169
+ .withNetwork(this.#network)
170
+ .withNetworkAliases("database")
171
+ .start();
172
+ const httpPort = this.#databaseContainer.getMappedPort(5432);
173
+ const host = this.#databaseContainer.getHost();
174
+ const networkIpAddress = this.#databaseContainer.getIpAddress(this.#network.getName());
175
+ process.env.DB_HOST = `${host}:${httpPort}`;
176
+ (0, stsconfig_1.$ResetOptions)();
177
+ goptions = (0, stsconfig_1.$Options)();
178
+ this.LogDebugMessage(chalk_1.default.green(`httpPort: [${httpPort}]`));
179
+ this.LogDebugMessage(chalk_1.default.green(`host: [${host}]`));
180
+ this.LogDebugMessage(chalk_1.default.green(`networkIpAddress: [${networkIpAddress}]`));
181
+ this.LogDebugMessage(chalk_1.default.green(`connectionString: [${goptions.connectionString}]`));
182
+ this.LogDebugMessage(chalk_1.default.green(`defaultDatabaseConnectionString: [${goptions.defaultDatabaseConnectionString}]`));
183
+ };
184
+ StopDatabase = async () => {
185
+ if (this.#databaseContainer) {
186
+ await this.#databaseContainer.stop();
187
+ this.LogDebugMessage(chalk_1.default.yellow(`Used the following parameters for the database during testing:`));
188
+ this.LogDebugMessage(chalk_1.default.yellow(`connectionString: [${goptions.connectionString}]`));
189
+ this.LogDebugMessage(chalk_1.default.yellow(`defaultDatabaseConnectionString: [${goptions.defaultDatabaseConnectionString}]`));
190
+ }
191
+ };
192
+ // Note: .withCopyFilesToContainer and .withCopyContentToContainer have a defect in that Jest will not close. A file handle/stream is left open
193
+ // within the underlying code.
194
+ InitializeDatabase = async () => {
195
+ const stsAuthContainerInit = await new testcontainers_1.GenericContainer("serza/stsauth:latest")
196
+ .withEnvironment({
197
+ DB_USER: "postgres",
198
+ DB_PASSWORD: "postgres",
199
+ DB_HOST: "database:5432", // "192.168.14.101",
200
+ POOL_SIZE: "50",
201
+ MAX_CPU: "2",
202
+ DEBUG: "proc*",
203
+ HTTPS_SERVER_KEY_PATH: "/var/lib/sts/stsglobalresources/keys-tmp/server.key",
204
+ HTTPS_SERVER_CERT_PATH: "/var/lib/sts/stsglobalresources/keys-tmp/server.cert",
205
+ AS_ENDPOINT: "https://stscore.stsmda.org"
206
+ })
207
+ .withCommand(["node", "dist/app", "create"])
208
+ .withNetwork(this.#network)
209
+ .withNetworkAliases("stsauthrunnerinit")
210
+ .withWaitStrategy(testcontainers_1.Wait.forLogMessage(`User registered: {"status":200,"detail":{"id":"USR_STSGlobalAdminUser@stsmda.com","name":"STSGlobalAdminUser@stsmda.com","email":"STSGlobalAdminUser@stsmda.com","roles":[]}}`))
211
+ .start();
212
+ await (0, stsutils_1.Sleep)(500);
213
+ await stsAuthContainerInit.stop();
214
+ };
215
+ StartAuthService = async () => {
216
+ this.#stsAuthContainer = await new testcontainers_1.GenericContainer("serza/stsauth:latest")
217
+ .withExposedPorts(3002)
218
+ .withEnvironment({
219
+ DB_USER: "postgres",
220
+ DB_PASSWORD: "postgres",
221
+ DB_HOST: "database:5432",
222
+ POOL_SIZE: "50",
223
+ MAX_CPU: "2",
224
+ DEBUG: "proc*",
225
+ HTTPS_SERVER_KEY_PATH: "/var/lib/sts/stsglobalresources/keys-tmp/server.key",
226
+ HTTPS_SERVER_CERT_PATH: "/var/lib/sts/stsglobalresources/keys-tmp/server.cert",
227
+ AS_ENDPOINT: "https://stscore.stsmda.org"
228
+ })
229
+ .withNetwork(this.#network)
230
+ .withNetworkAliases("stsauthrunner")
231
+ .withWaitStrategy(testcontainers_1.Wait.forHttp("/stsauth/v1.0/latency", 3002).usingTls().allowInsecure())
232
+ .start();
233
+ const httpAuthPort = this.#stsAuthContainer.getMappedPort(3002);
234
+ await (0, stsutils_1.Sleep)(200);
235
+ this.LogDebugMessage(chalk_1.default.green(`-------------------------------------------------------------------------------------------`));
236
+ this.LogDebugMessage(chalk_1.default.green(` *** STSAuth Started ***: [${httpAuthPort}]`));
237
+ this.LogDebugMessage(chalk_1.default.green(`-------------------------------------------------------------------------------------------`));
238
+ this.#authHost = 'https://localhost';
239
+ this.#authPort = httpAuthPort;
240
+ this.#authEndpoint = `${this.#authHost}:${this.#authPort}`;
241
+ };
242
+ StopAuthService = async () => {
243
+ if (this.#stsAuthContainer) {
244
+ await this.#stsAuthContainer.stop();
245
+ await (0, stsutils_1.Sleep)(200);
246
+ }
247
+ };
248
+ TestLoginAndVerify = async () => {
249
+ expect.assertions(4);
250
+ const retVal = await this.Login('user01@stsmda.com.au', 'user01password');
251
+ expect(retVal.status).toEqual(200);
252
+ this.LogDebugMessage(chalk_1.default.red(`${JSON.stringify(retVal.data)}`));
253
+ this.LogDebugMessage(chalk_1.default.magenta(`${JSON.stringify(retVal.headers)}`));
254
+ this.LogDebugMessage(chalk_1.default.yellow(`${JSON.stringify(retVal.headers['set-cookie'])}`));
255
+ const cookies = retVal.headers['set-cookie'];
256
+ this.LogDebugMessage(chalk_1.default.yellow(`${cookies[0]}`));
257
+ this.LogDebugMessage(chalk_1.default.green(`${JSON.stringify(tough.Cookie.parse(cookies[0]))}`));
258
+ const cookie = tough.Cookie.parse(cookies[0]);
259
+ const desiredCookieResultAxios = {
260
+ key: 'consent_cookie',
261
+ value: expect.stringMatching(this.#regexURLSafeStringComponent),
262
+ path: '/',
263
+ secure: true,
264
+ httpOnly: true,
265
+ sameSite: 'strict',
266
+ };
267
+ const cookieResult = JSON.parse(JSON.stringify(cookie));
268
+ expect(cookieResult).toMatchObject(desiredCookieResultAxios);
269
+ const cookieExpireDate = new Date(cookie.expires);
270
+ expect(cookieExpireDate.getTime()).toBeGreaterThan(new Date().getTime());
271
+ const desiredResult = {
272
+ sessionId: expect.stringMatching(this.#regexSTSBase64),
273
+ id_token: expect.stringMatching(this.#regexJWT),
274
+ consentRequired: [
275
+ 'api://d8277fce-bb48-44c2-bbf1-257fe13a444b/res01.create',
276
+ 'api://d8277fce-bb48-44c2-bbf1-257fe13a444b/res01.read',
277
+ 'api://d8277fce-bb48-44c2-bbf1-257fe13a444b/res01.update',
278
+ 'api://d8277fce-bb48-44c2-bbf1-257fe13a444b/res01.delete'
279
+ ]
280
+ };
281
+ expect(retVal.data.detail).toMatchObject(desiredResult);
282
+ };
283
+ }
284
+ exports.TestHelper = TestHelper;
285
+ //# sourceMappingURL=testHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testHelpers.js","sourceRoot":"","sources":["../src/testHelpers.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nsshunt/stsappframework",
3
- "version": "3.1.110",
3
+ "version": "3.1.112",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "./types/index.d.ts",
@@ -31,14 +31,17 @@
31
31
  "@types/cookie-parser": "^1.4.7",
32
32
  "@types/debug": "^4.1.12",
33
33
  "@types/express": "^4.17.21",
34
+ "@types/jest": "^29.5.12",
34
35
  "@types/jsonwebtoken": "^9.0.6",
35
36
  "@types/uuid": "^9.0.8",
36
37
  "@typescript-eslint/eslint-plugin": "^7.8.0",
37
38
  "@typescript-eslint/parser": "^7.8.0",
38
39
  "eslint": "^8.57.0",
39
40
  "jest": "^29.7.0",
41
+ "testcontainers": "^10.9.0",
40
42
  "typescript": "^5.4.5",
41
- "vite": "^5.2.11"
43
+ "vite": "^5.2.11",
44
+ "vitest": "^1.6.0"
42
45
  },
43
46
  "dependencies": {
44
47
  "@grpc/grpc-js": "^1.10.7",
@@ -46,7 +49,7 @@
46
49
  "@influxdata/influxdb-client": "^1.33.2",
47
50
  "@influxdata/influxdb-client-apis": "^1.33.2",
48
51
  "@nsshunt/stsconfig": "^1.25.127",
49
- "@nsshunt/stsdatamanagement": "^1.18.34",
52
+ "@nsshunt/stsdatamanagement": "^1.18.37",
50
53
  "@nsshunt/stsobservability": "^1.0.28",
51
54
  "@nsshunt/stsutils": "^1.16.59",
52
55
  "@socket.io/cluster-adapter": "^0.2.2",
@@ -77,7 +80,6 @@
77
80
  "tiny-emitter": "^2.1.0",
78
81
  "tough-cookie": "^4.1.4",
79
82
  "uuid": "^9.0.1",
80
- "vitest": "^1.5.3",
81
83
  "winston": "^3.13.0"
82
84
  }
83
85
  }
package/src/index.ts CHANGED
@@ -25,3 +25,4 @@ export * from './stsTransportLoggerWinston'
25
25
  export * from './ipcMessageProcessorPrimary'
26
26
  export * from './ipcMessageProcessorWorker'
27
27
  export * from './ipcMessageManager'
28
+ export * from './testHelpers'
@@ -0,0 +1,329 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
2
+ import chalk from 'chalk'
3
+
4
+ import * as tough from 'tough-cookie'
5
+
6
+ import https from 'https'
7
+ import crypto from 'crypto';
8
+
9
+ import axios from 'axios';
10
+
11
+ import { GenericContainer, Network, Wait } from "testcontainers";
12
+
13
+ import { $Options, $ResetOptions } from '@nsshunt/stsconfig'
14
+ let goptions = $Options()
15
+
16
+ import { Sleep, defaultLogger } from '@nsshunt/stsutils'
17
+
18
+ import { AuthUtilsNode } from './authutilsnode'
19
+
20
+ export class TestHelper {
21
+ //#regexBase64URL = /^[A-Za-z0-9_-]+$/ // Base64URL - https://base64.guru/standards/base64url
22
+ #regexURLSafeStringComponent = /[-a-zA-Z0-9@:%._+~#=]{1,256}/ // URL safe string component
23
+ //#regexBase64 = /(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?/ // Base64 - https://stackoverflow.com/questions/475074/regex-to-parse-or-validate-base64-data
24
+ #regexSTSBase64 = /SES_(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?/ // Base64
25
+ #regexJWT = /[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+/ // JWT (Base64URL.Base64URL.Base64URL)
26
+
27
+ #authUtilsNode = new AuthUtilsNode(defaultLogger);
28
+
29
+ #databaseContainer: any;
30
+ #stsAuthContainer: any;
31
+ #network: any;
32
+ #authEndpoint = '';
33
+ #authPort = '';
34
+ #authHost = '';
35
+ #httpsAgent: https.Agent | null = null;
36
+
37
+ constructor() {
38
+ this.#authEndpoint = 'https://localhost:3002'; //@@
39
+ }
40
+
41
+ LogDebugMessage(message: any) {
42
+ defaultLogger.debug(message);
43
+ }
44
+
45
+ #GetHttpsAgent = () =>
46
+ {
47
+ if (this.#httpsAgent === null) {
48
+ // https://nodejs.org/api/http.html#class-httpagent
49
+ this.#httpsAgent = new https.Agent({
50
+ keepAlive: goptions.keepAlive,
51
+ maxSockets: goptions.maxSockets,
52
+ maxTotalSockets: goptions.maxTotalSockets,
53
+ maxFreeSockets: goptions.maxFreeSockets,
54
+ timeout: goptions.timeout,
55
+ rejectUnauthorized: false
56
+ });
57
+ }
58
+ return this.#httpsAgent;
59
+ }
60
+
61
+ StartNetwork = async () => {
62
+ this.#network = await new Network().start();
63
+ }
64
+
65
+ StopNetwork = async () => {
66
+ await this.#network.stop();
67
+ }
68
+
69
+ get network() {
70
+ return this.#network;
71
+ }
72
+
73
+ get authPort() {
74
+ return this.#authPort;
75
+ }
76
+
77
+ get authHost() {
78
+ return this.#authHost;
79
+ }
80
+
81
+ get authEndpoint() {
82
+ return this.#authEndpoint;
83
+ }
84
+
85
+ get getHttpsAgent() {
86
+ return this.#GetHttpsAgent();
87
+ }
88
+
89
+ CreateRandomString = () => {
90
+ const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~.'; // /[0-9A-Za-z\-_~.]/
91
+ let random = '';
92
+ const randomValues: number[] = Array.from(crypto.getRandomValues(new Uint8Array(43)));
93
+ randomValues.forEach(v => (random += charset[v % charset.length]));
94
+ return random;
95
+ }
96
+
97
+ Login = async (username: string, password: string) => {
98
+ const client_id = process.env.CLIENT_ID as string;
99
+ const nonce = crypto.randomBytes(43).toString('base64'); //CreateRandomString();
100
+ const response_type = 'code';
101
+ const redirect_uri = process.env.REDIRECT_URI as string;
102
+ const response_mode = 'query';
103
+ const scope = process.env.SCOPE as string;
104
+ const state = crypto.randomBytes(43).toString('base64'); // CreateRandomString();
105
+ const code_verifier = this.CreateRandomString();
106
+ const code_challenge = crypto.createHash('sha256').update(code_verifier).digest('base64');
107
+ const code_challenge_method = 'S256';
108
+
109
+ const authoriseOptions: any = {
110
+ email: username,
111
+ password,
112
+ client_id,
113
+ nonce,
114
+ response_type,
115
+ redirect_uri,
116
+ response_mode,
117
+ scope,
118
+ state,
119
+ code_challenge,
120
+ code_challenge_method
121
+ }
122
+
123
+ const url = `${this.#authEndpoint}${goptions.asapiroot}/login`;
124
+ const headers = { 'Content-Type': 'application/json'};
125
+
126
+ const retVal = await axios({
127
+ url
128
+ ,method: 'post'
129
+ ,data: authoriseOptions
130
+ ,headers: headers
131
+ ,httpsAgent: this.#GetHttpsAgent()
132
+ });
133
+
134
+ //const cookieString = retVal.headers['set-cookie'];
135
+
136
+ /*
137
+ const api = request(this.#endpoint);
138
+ const retVal: any = await (api as any)
139
+ .post(`${goptions.asapiroot}/login`)
140
+ .send(authoriseOptions)
141
+ //.expect('set-cookie', /consent_cookie=.*; Max-Age=86; Path=\/; Expires=.*; HttpOnly; Secure; SameSite=Strict/);
142
+
143
+ const cookieString = retVal.header['set-cookie'];
144
+
145
+ if (cookieString) {
146
+ retVal.cookie = new Cookie(cookieString[0]);
147
+ }
148
+ */
149
+
150
+ return retVal;
151
+ }
152
+
153
+ /*
154
+ GetAuthServerAPITokenFromServer = async (): Promise<string> => {
155
+ return await this.#authUtilsNode.GetAPITokenFromAuthServer(STSClientID.STSTestingService,
156
+ "eN9u0mHZLGWZrdnE1zit2vL6xwUFW466sTZcbkXDml5KWxlvKaZ1uiOZmA==",
157
+ goptions.asapiidentifier, this.#authEndpoint)
158
+ }
159
+ */
160
+
161
+ ValidateJWT = async (token: string): Promise<string> => {
162
+ return await this.#authUtilsNode.ValidateJWT(token, goptions.asapiidentifier, this.#authEndpoint);
163
+ }
164
+
165
+ StartDatabase = async () => {
166
+ this.#databaseContainer = await new GenericContainer("postgres")
167
+ .withExposedPorts(5432)
168
+ .withEnvironment({
169
+ POSTGRES_PASSWORD: "postgres",
170
+ //UV_THREADPOOL_SIZE: "64"
171
+ })
172
+ .withNetwork(this.#network)
173
+ .withNetworkAliases("database")
174
+ .start();
175
+
176
+ const httpPort = this.#databaseContainer.getMappedPort(5432);
177
+ const host = this.#databaseContainer.getHost();
178
+ const networkIpAddress = this.#databaseContainer.getIpAddress(this.#network.getName());
179
+
180
+ process.env.DB_HOST = `${host}:${httpPort}`;
181
+
182
+ $ResetOptions();
183
+ goptions = $Options()
184
+
185
+ this.LogDebugMessage(chalk.green(`httpPort: [${httpPort}]`));
186
+ this.LogDebugMessage(chalk.green(`host: [${host}]`));
187
+ this.LogDebugMessage(chalk.green(`networkIpAddress: [${networkIpAddress}]`));
188
+ this.LogDebugMessage(chalk.green(`connectionString: [${goptions.connectionString}]`));
189
+ this.LogDebugMessage(chalk.green(`defaultDatabaseConnectionString: [${goptions.defaultDatabaseConnectionString }]`));
190
+ }
191
+
192
+ StopDatabase = async () => {
193
+ if (this.#databaseContainer) {
194
+ await this.#databaseContainer.stop();
195
+
196
+ this.LogDebugMessage(chalk.yellow(`Used the following parameters for the database during testing:`));
197
+ this.LogDebugMessage(chalk.yellow(`connectionString: [${goptions.connectionString}]`));
198
+ this.LogDebugMessage(chalk.yellow(`defaultDatabaseConnectionString: [${goptions.defaultDatabaseConnectionString }]`));
199
+ }
200
+ }
201
+
202
+ // Note: .withCopyFilesToContainer and .withCopyContentToContainer have a defect in that Jest will not close. A file handle/stream is left open
203
+ // within the underlying code.
204
+ InitializeDatabase = async () => {
205
+ const stsAuthContainerInit = await new GenericContainer("serza/stsauth:latest")
206
+ .withEnvironment({
207
+ DB_USER: "postgres",
208
+ DB_PASSWORD: "postgres",
209
+ DB_HOST: "database:5432", // "192.168.14.101",
210
+ POOL_SIZE: "50",
211
+ MAX_CPU: "2",
212
+ DEBUG: "proc*",
213
+ HTTPS_SERVER_KEY_PATH: "/var/lib/sts/stsglobalresources/keys-tmp/server.key",
214
+ HTTPS_SERVER_CERT_PATH: "/var/lib/sts/stsglobalresources/keys-tmp/server.cert",
215
+ AS_ENDPOINT: "https://stscore.stsmda.org"
216
+ })
217
+ .withCommand(["node", "dist/app", "create"])
218
+ .withNetwork(this.#network)
219
+ .withNetworkAliases("stsauthrunnerinit")
220
+ .withWaitStrategy(Wait.forLogMessage(`User registered: {"status":200,"detail":{"id":"USR_STSGlobalAdminUser@stsmda.com","name":"STSGlobalAdminUser@stsmda.com","email":"STSGlobalAdminUser@stsmda.com","roles":[]}}`))
221
+ .start();
222
+
223
+ await Sleep(500);
224
+
225
+ await stsAuthContainerInit.stop();
226
+ }
227
+
228
+ StartAuthService = async () => {
229
+ this.#stsAuthContainer = await new GenericContainer("serza/stsauth:latest")
230
+ .withExposedPorts(3002)
231
+ .withEnvironment({
232
+ DB_USER: "postgres",
233
+ DB_PASSWORD: "postgres",
234
+ DB_HOST: "database:5432",
235
+ POOL_SIZE: "50",
236
+ MAX_CPU: "2",
237
+ DEBUG: "proc*",
238
+ HTTPS_SERVER_KEY_PATH: "/var/lib/sts/stsglobalresources/keys-tmp/server.key",
239
+ HTTPS_SERVER_CERT_PATH: "/var/lib/sts/stsglobalresources/keys-tmp/server.cert",
240
+ AS_ENDPOINT: "https://stscore.stsmda.org"
241
+ })
242
+ .withNetwork(this.#network)
243
+ .withNetworkAliases("stsauthrunner")
244
+ .withWaitStrategy(Wait.forHttp("/stsauth/v1.0/latency", 3002).usingTls().allowInsecure())
245
+ .start();
246
+
247
+ const httpAuthPort = this.#stsAuthContainer.getMappedPort(3002);
248
+
249
+ await Sleep(200);
250
+ this.LogDebugMessage(chalk.green(`-------------------------------------------------------------------------------------------`));
251
+ this.LogDebugMessage(chalk.green(` *** STSAuth Started ***: [${httpAuthPort}]`));
252
+ this.LogDebugMessage(chalk.green(`-------------------------------------------------------------------------------------------`));
253
+
254
+ this.#authHost = 'https://localhost'
255
+ this.#authPort = httpAuthPort;
256
+ this.#authEndpoint = `${this.#authHost}:${this.#authPort}`;
257
+ }
258
+
259
+ StopAuthService = async () => {
260
+ if (this.#stsAuthContainer) {
261
+ await this.#stsAuthContainer.stop();
262
+ await Sleep(200);
263
+ }
264
+ }
265
+
266
+ TestLoginAndVerify = async () => {
267
+ expect.assertions(4);
268
+
269
+ const retVal = await this.Login('user01@stsmda.com.au', 'user01password');
270
+ expect(retVal.status).toEqual(200);
271
+
272
+ this.LogDebugMessage(chalk.red(`${JSON.stringify(retVal.data)}`));
273
+ this.LogDebugMessage(chalk.magenta(`${JSON.stringify(retVal.headers)}`));
274
+ this.LogDebugMessage(chalk.yellow(`${JSON.stringify(retVal.headers['set-cookie'])}`));
275
+
276
+ const cookies = retVal.headers['set-cookie'] as string[];
277
+ this.LogDebugMessage(chalk.yellow(`${cookies[0]}`));
278
+ this.LogDebugMessage(chalk.green(`${JSON.stringify(tough.Cookie.parse(cookies[0]))}`));
279
+
280
+ const cookie = tough.Cookie.parse(cookies[0]) as tough.Cookie;
281
+
282
+ const desiredCookieResultAxios = {
283
+ key: 'consent_cookie',
284
+ value: expect.stringMatching(this.#regexURLSafeStringComponent),
285
+ path: '/',
286
+ secure: true,
287
+ httpOnly: true,
288
+ sameSite: 'strict',
289
+ }
290
+
291
+ const cookieResult = JSON.parse(JSON.stringify(cookie));
292
+ expect(cookieResult).toMatchObject(desiredCookieResultAxios);
293
+
294
+ const cookieExpireDate = new Date(cookie.expires);
295
+ expect(cookieExpireDate.getTime()).toBeGreaterThan(new Date().getTime());
296
+
297
+ const desiredResult = {
298
+ sessionId: expect.stringMatching(this.#regexSTSBase64),
299
+ id_token: expect.stringMatching(this.#regexJWT),
300
+ consentRequired: [
301
+ 'api://d8277fce-bb48-44c2-bbf1-257fe13a444b/res01.create',
302
+ 'api://d8277fce-bb48-44c2-bbf1-257fe13a444b/res01.read',
303
+ 'api://d8277fce-bb48-44c2-bbf1-257fe13a444b/res01.update',
304
+ 'api://d8277fce-bb48-44c2-bbf1-257fe13a444b/res01.delete'
305
+ ]
306
+ }
307
+ expect(retVal.data.detail).toMatchObject(desiredResult);
308
+ }
309
+
310
+ /*
311
+ TestValidateJWT = async () => {
312
+ expect.assertions(1);
313
+
314
+ const access_token = await this.GetAuthServerAPITokenFromServer();
315
+ this.LogDebugMessage(chalk.green(`access_token: [${access_token}]`));
316
+
317
+ const retVal = await this.ValidateJWT(access_token);
318
+ // https://jestjs.io/docs/expect#tomatchobjectobject
319
+ const desiredJWT = {
320
+ scope: 'offline_access session.read session.update',
321
+ iss: 'https://stsmda.com.au/stsauth/',
322
+ aud: 'https://stsmda.com.au/stsauthapi/v1.0/',
323
+ sub: 'session'
324
+ };
325
+
326
+ expect(retVal).toMatchObject(desiredJWT);
327
+ }
328
+ */
329
+ }
package/types/index.d.ts CHANGED
@@ -25,4 +25,5 @@ export * from './stsTransportLoggerWinston';
25
25
  export * from './ipcMessageProcessorPrimary';
26
26
  export * from './ipcMessageProcessorWorker';
27
27
  export * from './ipcMessageManager';
28
+ export * from './testHelpers';
28
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mCAAmC,CAAA;AACjD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,kCAAkC,CAAA;AAChD,cAAc,6CAA6C,CAAA;AAC3D,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mCAAmC,CAAA;AACjD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,kCAAkC,CAAA;AAChD,cAAc,6CAA6C,CAAA;AAC3D,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA"}
@@ -0,0 +1,24 @@
1
+ /// <reference types="node" />
2
+ import https from 'https';
3
+ export declare class TestHelper {
4
+ #private;
5
+ constructor();
6
+ LogDebugMessage(message: any): void;
7
+ StartNetwork: () => Promise<void>;
8
+ StopNetwork: () => Promise<void>;
9
+ get network(): any;
10
+ get authPort(): string;
11
+ get authHost(): string;
12
+ get authEndpoint(): string;
13
+ get getHttpsAgent(): https.Agent;
14
+ CreateRandomString: () => string;
15
+ Login: (username: string, password: string) => Promise<import("axios").AxiosResponse<any, any>>;
16
+ ValidateJWT: (token: string) => Promise<string>;
17
+ StartDatabase: () => Promise<void>;
18
+ StopDatabase: () => Promise<void>;
19
+ InitializeDatabase: () => Promise<void>;
20
+ StartAuthService: () => Promise<void>;
21
+ StopAuthService: () => Promise<void>;
22
+ TestLoginAndVerify: () => Promise<void>;
23
+ }
24
+ //# sourceMappingURL=testHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testHelpers.d.ts","sourceRoot":"","sources":["../src/testHelpers.ts"],"names":[],"mappings":";AAKA,OAAO,KAAK,MAAM,OAAO,CAAA;AAczB,qBAAa,UAAU;;;IAqBnB,eAAe,CAAC,OAAO,EAAE,GAAG;IAoB5B,YAAY,sBAEX;IAED,WAAW,sBAEV;IAED,IAAI,OAAO,QAEV;IAED,IAAI,QAAQ,WAEX;IAED,IAAI,QAAQ,WAEX;IAED,IAAI,YAAY,WAEf;IAED,IAAI,aAAa,gBAEhB;IAED,kBAAkB,eAMjB;IAED,KAAK,aAAoB,MAAM,YAAY,MAAM,sDAsDhD;IAUD,WAAW,UAAiB,MAAM,KAAG,QAAQ,MAAM,CAAC,CAEnD;IAED,aAAa,sBAyBZ;IAED,YAAY,sBAQX;IAID,kBAAkB,sBAsBjB;IAED,gBAAgB,sBA6Bf;IAED,eAAe,sBAKd;IAED,kBAAkB,sBA0CjB;CAqBJ"}