@nsshunt/stsappframework 3.1.111 → 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAkD,CAAE,UAAU;AAC9D,kDAAyB;AAEzB,oDAAqC;AAErC,kDAAyB;AACzB,oDAA4B;AAE5B,kDAA0B;AAE1B,mDAAiE;AAEjE,kDAA4D;AAC5D,IAAI,QAAQ,GAAG,IAAA,oBAAQ,GAAE,CAAA;AAEzB,gDAAwD;AAExD,mDAA+C;AAE/C,MAAa,UAAU;IACnB,8FAA8F;IAC9F,4BAA4B,GAAG,8BAA8B,CAAA,CAAC,4BAA4B;IAC1F,+KAA+K;IAC/K,eAAe,GAAG,oEAAoE,CAAA,CAAC,SAAS;IAChG,SAAS,GAAG,gDAAgD,CAAA,CAAC,sCAAsC;IAEnG,cAAc,GAAG,IAAI,6BAAa,CAAC,wBAAa,CAAC,CAAC;IAElD,kBAAkB,CAAM;IACxB,iBAAiB,CAAM;IACvB,QAAQ,CAAM;IACd,aAAa,GAAG,EAAE,CAAC;IACnB,SAAS,GAAG,EAAE,CAAC;IACf,SAAS,GAAG,EAAE,CAAC;IACf,WAAW,GAAuB,IAAI,CAAC;IAEvC;QACI,IAAI,CAAC,aAAa,GAAG,wBAAwB,CAAC,CAAC,IAAI;IACvD,CAAC;IAED,eAAe,CAAC,OAAY;QACxB,wBAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,cAAc,GAAG,GAAG,EAAE;QAElB,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YAC5B,mDAAmD;YACnD,IAAI,CAAC,WAAW,GAAG,IAAI,eAAK,CAAC,KAAK,CAAC;gBAC/B,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,eAAe,EAAE,QAAQ,CAAC,eAAe;gBACzC,cAAc,EAAE,QAAQ,CAAC,cAAc;gBACvC,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,kBAAkB,EAAE,KAAK;aAC5B,CAAC,CAAC;QACP,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC,CAAA;IAED,YAAY,GAAG,KAAK,IAAI,EAAE;QACtB,IAAI,CAAC,QAAQ,GAAG,MAAM,IAAI,wBAAO,EAAE,CAAC,KAAK,EAAE,CAAC;IAChD,CAAC,CAAA;IAED,WAAW,GAAG,KAAK,IAAI,EAAE;QACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC,CAAA;IAED,IAAI,OAAO;QACP,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED,IAAI,aAAa;QACb,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;IACjC,CAAC;IAED,kBAAkB,GAAG,GAAG,EAAE;QACtB,MAAM,OAAO,GAAG,oEAAoE,CAAC,CAAC,wBAAwB;QAC9G,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,YAAY,GAAa,KAAK,CAAC,IAAI,CAAC,gBAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACtF,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnE,OAAO,MAAM,CAAC;IAClB,CAAC,CAAA;IAED,KAAK,GAAG,KAAK,EAAE,QAAgB,EAAE,QAAgB,EAAE,EAAE;QACjD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAmB,CAAC;QAClD,MAAM,KAAK,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,uBAAuB;QAChF,MAAM,aAAa,GAAG,MAAM,CAAC;QAC7B,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAsB,CAAC;QACxD,MAAM,aAAa,GAAG,OAAO,CAAC;QAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAe,CAAC;QAC1C,MAAM,KAAK,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,wBAAwB;QACjF,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAChD,MAAM,cAAc,GAAG,gBAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1F,MAAM,qBAAqB,GAAG,MAAM,CAAC;QAErC,MAAM,gBAAgB,GAAQ;YAC1B,KAAK,EAAE,QAAQ;YACf,QAAQ;YACR,SAAS;YACT,KAAK;YACL,aAAa;YACb,YAAY;YACZ,aAAa;YACb,KAAK;YACL,KAAK;YACL,cAAc;YACd,qBAAqB;SACxB,CAAA;QAED,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,SAAS,QAAQ,CAAC;QAC/D,MAAM,OAAO,GAAG,EAAE,cAAc,EAAE,kBAAkB,EAAC,CAAC;QAEtD,MAAM,MAAM,GAAG,MAAM,IAAA,eAAK,EAAC;YACvB,GAAG;YACF,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,OAAO;YAChB,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE;SACrC,CAAC,CAAC;QAEH,oDAAoD;QAEpD;;;;;;;;;;;;UAYE;QAEF,OAAO,MAAM,CAAC;IAClB,CAAC,CAAA;IAED;;;;;;MAME;IAEF,WAAW,GAAG,KAAK,EAAE,KAAa,EAAmB,EAAE;QACnD,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACtG,CAAC,CAAA;IAED,aAAa,GAAG,KAAK,IAAI,EAAE;QACvB,IAAI,CAAC,kBAAkB,GAAG,MAAM,IAAI,iCAAgB,CAAC,UAAU,CAAC;aAC3D,gBAAgB,CAAC,IAAI,CAAC;aACtB,eAAe,CAAC;YACb,iBAAiB,EAAE,UAAU;YAC7B,0BAA0B;SAC7B,CAAC;aACD,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;aAC1B,kBAAkB,CAAC,UAAU,CAAC;aAC9B,KAAK,EAAE,CAAC;QAEb,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC;QAC/C,MAAM,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QAEvF,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC;QAE5C,IAAA,yBAAa,GAAE,CAAC;QAChB,QAAQ,GAAG,IAAA,oBAAQ,GAAE,CAAA;QAErB,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,cAAc,QAAQ,GAAG,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,sBAAsB,gBAAgB,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,sBAAsB,QAAQ,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;QACtF,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,qCAAqC,QAAQ,CAAC,+BAAgC,GAAG,CAAC,CAAC,CAAC;IACzH,CAAC,CAAA;IAED,YAAY,GAAG,KAAK,IAAI,EAAE;QACtB,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;YAErC,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,MAAM,CAAC,gEAAgE,CAAC,CAAC,CAAC;YACrG,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,MAAM,CAAC,sBAAsB,QAAQ,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;YACvF,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,MAAM,CAAC,qCAAqC,QAAQ,CAAC,+BAAgC,GAAG,CAAC,CAAC,CAAC;QAC1H,CAAC;IACL,CAAC,CAAA;IAED,+IAA+I;IAC/I,8BAA8B;IAC9B,kBAAkB,GAAG,KAAK,IAAI,EAAE;QAC5B,MAAM,oBAAoB,GAAG,MAAM,IAAI,iCAAgB,CAAC,sBAAsB,CAAC;aAC1E,eAAe,CAAC;YACb,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE,UAAU;YACvB,OAAO,EAAE,eAAe,EAAE,oBAAoB;YAC9C,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,GAAG;YACZ,KAAK,EAAE,OAAO;YACd,qBAAqB,EAAE,qDAAqD;YAC5E,sBAAsB,EAAE,sDAAsD;YAC9E,WAAW,EAAE,4BAA4B;SAC5C,CAAC;aACD,WAAW,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;aAC3C,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;aAC1B,kBAAkB,CAAC,mBAAmB,CAAC;aACvC,gBAAgB,CAAC,qBAAI,CAAC,aAAa,CAAC,+KAA+K,CAAC,CAAC;aACrN,KAAK,EAAE,CAAC;QAEb,MAAM,IAAA,gBAAK,EAAC,GAAG,CAAC,CAAC;QAEjB,MAAM,oBAAoB,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC,CAAA;IAED,gBAAgB,GAAG,KAAK,IAAI,EAAE;QAC1B,IAAI,CAAC,iBAAiB,GAAG,MAAM,IAAI,iCAAgB,CAAC,sBAAsB,CAAC;aACtE,gBAAgB,CAAC,IAAI,CAAC;aACtB,eAAe,CAAC;YACb,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE,UAAU;YACvB,OAAO,EAAE,eAAe;YACxB,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,GAAG;YACZ,KAAK,EAAE,OAAO;YACd,qBAAqB,EAAE,qDAAqD;YAC5E,sBAAsB,EAAE,sDAAsD;YAC9E,WAAW,EAAE,4BAA4B;SAC5C,CAAC;aACD,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;aAC1B,kBAAkB,CAAC,eAAe,CAAC;aACnC,gBAAgB,CAAC,qBAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,aAAa,EAAE,CAAC;aACxF,KAAK,EAAE,CAAC;QAEb,MAAM,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAEhE,MAAM,IAAA,gBAAK,EAAC,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,6FAA6F,CAAC,CAAC,CAAC;QACjI,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,8DAA8D,YAAY,GAAG,CAAC,CAAC,CAAC;QACjH,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,6FAA6F,CAAC,CAAC,CAAC;QAEjI,IAAI,CAAC,SAAS,GAAG,mBAAmB,CAAA;QACpC,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC;QAC9B,IAAI,CAAC,aAAa,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;IAC/D,CAAC,CAAA;IAED,eAAe,GAAG,KAAK,IAAI,EAAE;QACzB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAA,gBAAK,EAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACL,CAAC,CAAA;IAED,kBAAkB,GAAG,KAAK,IAAI,EAAE;QAC5B,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAErB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,gBAAgB,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEnC,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEtF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAa,CAAC;QACzD,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,eAAe,CAAC,eAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEvF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAiB,CAAC;QAE9D,MAAM,wBAAwB,GAAG;YAC7B,GAAG,EAAE,gBAAgB;YACrB,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,4BAA4B,CAAC;YAC/D,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,IAAI;YACZ,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,QAAQ;SACrB,CAAA;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,YAAY,CAAC,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC;QAE7D,MAAM,gBAAgB,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAEzE,MAAM,aAAa,GAAG;YAClB,SAAS,EAAE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,CAAC;YACtD,QAAQ,EAAE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC;YAC/C,eAAe,EAAE;gBACb,yDAAyD;gBACzD,uDAAuD;gBACvD,yDAAyD;gBACzD,yDAAyD;aAC5D;SACJ,CAAA;QACD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IAC5D,CAAC,CAAA;CAqBJ;AArTD,gCAqTC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nsshunt/stsappframework",
3
- "version": "3.1.111",
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",
@@ -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"}