@nsshunt/stsappframework 3.0.94 → 3.0.95
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/package.json +1 -1
- package/src_new/authDefs.ts +37 -0
- package/src_new/authutilsnode.ts +375 -0
- package/src_new/commonTypes.ts +239 -0
- package/src_new/index.ts +22 -0
- package/src_new/influxdb/influxDBManager.ts +972 -0
- package/src_new/influxdb/influxDBManagerAgent.ts +316 -0
- package/src_new/influxdb/influxDBManagerBase.ts +111 -0
- package/src_new/influxdb/influxDBManagerService.ts +375 -0
- package/src_new/instrumentationsubscriber.ts +286 -0
- package/src_new/kafka/IMKafkaManager.ts +154 -0
- package/src_new/kafka/kafkaconsumer.ts +82 -0
- package/src_new/kafka/kafkamanager.ts +186 -0
- package/src_new/kafka/kafkaproducer.ts +58 -0
- package/src_new/kafkatesting/config.ts +10 -0
- package/src_new/kafkatesting/consume.ts +116 -0
- package/src_new/kafkatesting/produce.ts +155 -0
- package/src_new/masterprocessbase.ts +590 -0
- package/src_new/middleware/serverNetworkMiddleware.ts +240 -0
- package/src_new/network.ts +36 -0
- package/src_new/processbase.ts +413 -0
- package/src_new/processoptions.ts +164 -0
- package/src_new/publishertransports/publishTransportDirect.ts +45 -0
- package/src_new/publishertransports/publishTransportUtils.ts +53 -0
- package/src_new/server.ts +141 -0
- package/src_new/serverprocessbase.ts +393 -0
- package/src_new/singleprocessbase.ts +123 -0
- package/src_new/socketIoServerHelper.ts +177 -0
- package/src_new/stscontrollerbase.ts +15 -0
- package/src_new/stslatencycontroller.ts +27 -0
- package/src_new/stslatencyroute.ts +16 -0
- package/src_new/stsrouterbase.ts +22 -0
- package/src_new/tcpclient/app.ts +19 -0
- package/src_new/tcpclient/app2.ts +56 -0
- package/src_new/tcpserver/app.ts +11 -0
- package/src_new/tcpserver/appConfig.ts +65 -0
- package/src_new/tcpserver/appmaster.ts +522 -0
- package/src_new/validation/errors.ts +6 -0
- package/src_new/webworkertesting/app.ts +49 -0
- package/src_new/webworkertesting/worker.ts +24 -0
- package/src_new/workerprocessbase.test.ts +47 -0
- package/src_new/workerprocessbase.ts +187 -0
package/package.json
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export enum Permission {
|
|
2
|
+
STS_GLOBAL_ADMIN_PERMISSION = "STSGlobalAdminPermission",
|
|
3
|
+
|
|
4
|
+
STSREST01_CREATE_PERMISSION = "STSREST01CreatePermission",
|
|
5
|
+
STSREST01_READ_PERMISSION = "STSREST01ReadPermission",
|
|
6
|
+
STSREST01_UPDATE_PERMISSION = "STSREST01UpdatePermission",
|
|
7
|
+
STSREST01_DELETE_PERMISSION = "STSREST01DeletePermission",
|
|
8
|
+
|
|
9
|
+
STSAUTH_LOGIN_PERMISSION = "STSAuthLoginPermission",
|
|
10
|
+
STSAUTH_CREATE_PERMISSION = "STSAuthCreatePermission",
|
|
11
|
+
STSAUTH_READ_PERMISSION = "STSAuthReadPermission",
|
|
12
|
+
STSAUTH_UPDATE_PERMISSION = "STSAuthUpdatePermission",
|
|
13
|
+
STSAUTH_DELETE_PERMISSION = "STSAuthDeletePermission",
|
|
14
|
+
|
|
15
|
+
STSUITERMINAL_EXECUTE = "STSUITerminalExecute",
|
|
16
|
+
|
|
17
|
+
STSCLI_EXECUTE = "STSCLIExecute",
|
|
18
|
+
|
|
19
|
+
STSUIWEBAPP_EXECUTE = "STSUIWebAppExecute",
|
|
20
|
+
|
|
21
|
+
STSUSERAGENTRUNNER_EXECUTE = "STSUserAgentRunnerExecute",
|
|
22
|
+
|
|
23
|
+
STSINSTRUMENTMANAGER_CREATE_PERMISSION = "STSInstrumentManagerCreatePermission",
|
|
24
|
+
STSINSTRUMENTMANAGER_READ_PERMISSION = "STSInstrumentManagerReadPermission",
|
|
25
|
+
STSINSTRUMENTMANAGER_UPDATE_PERMISSION = "STSInstrumentManagerUpdatePermission",
|
|
26
|
+
STSINSTRUMENTMANAGER_DELETE_PERMISSION = "STSInstrumentManagerDeletePermission",
|
|
27
|
+
|
|
28
|
+
STSTESTORCHESTRATOR_CREATE_PERMISSION = "STSTestOrchestratorCreatePermission",
|
|
29
|
+
STSTESTORCHESTRATOR_READ_PERMISSION = "STSTestOrchestratorReadPermission",
|
|
30
|
+
STSTESTORCHESTRATOR_UPDATE_PERMISSION = "STSTestOrchestratorUpdatePermission",
|
|
31
|
+
STSTESTORCHESTRATOR_DELETE_PERMISSION = "STSTestOrchestratorDeletePermission",
|
|
32
|
+
|
|
33
|
+
STSTESTRUNNER_CREATE_PERMISSION = "STSTestRunnerCreatePermission",
|
|
34
|
+
STSTESTRUNNER_READ_PERMISSION = "STSTestRunnerReadPermission",
|
|
35
|
+
STSTESTRUNNER_UPDATE_PERMISSION = "STSTestRunnerUpdatePermission",
|
|
36
|
+
STSTESTRUNNER_DELETE_PERMISSION = "STSTestRunnerDeletePermission"
|
|
37
|
+
}
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import tough from 'tough-cookie';
|
|
2
|
+
import https from 'https'
|
|
3
|
+
import jwt from 'jsonwebtoken';
|
|
4
|
+
import { jwtDecode } from "jwt-decode";
|
|
5
|
+
import jwksClient from 'jwks-rsa';
|
|
6
|
+
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
|
|
9
|
+
import { $Options } from '@nsshunt/stsconfig'
|
|
10
|
+
const goptions = $Options()
|
|
11
|
+
|
|
12
|
+
import debugModule from 'debug'
|
|
13
|
+
|
|
14
|
+
import { GetErrorPayload, JSONObject } from '@nsshunt/stsutils'
|
|
15
|
+
|
|
16
|
+
import { AppFrameworkErrorCode } from './validation/errors'
|
|
17
|
+
|
|
18
|
+
import { StatusCodes } from 'http-status-codes';
|
|
19
|
+
|
|
20
|
+
import chalk from 'chalk';
|
|
21
|
+
|
|
22
|
+
export interface IAuthUtilsNodeOptions {
|
|
23
|
+
permissions: string[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
export enum STSClientID {
|
|
28
|
+
STSRest01Service = 'KgSyRECcvnJwwOZqf7GPqUw508sx7VBFEbDC0iP4oeY=',
|
|
29
|
+
STSAuthService = 'q6a9F0kksXDDcrsCUKRwHKDnTNh7yZfxCShAgIJqfGg=',
|
|
30
|
+
STSUITerminal = 'U0E4c4cuRKlBsGo7OhOl3qTkoNGFBXjORUS/T4R4xyA=',
|
|
31
|
+
STSCLI = 'EcCpnQOIQFizAnWphlFJ4tSylosgVnwKTSNtgwuL2tw=',
|
|
32
|
+
STSUIWebApp = 'lww8Je8n2P0OI/KEfJ+4p/bqsk8uE/noeq13tl4zlQ0=',
|
|
33
|
+
XXSTSUserAgentRunnerX = 'y1h2nNr1BzTVPIzNmP/f041uxbnyZYTJeF/5GcwRCtw=',
|
|
34
|
+
STSInstrumentManagerService = 'l8u2E912eR44ZYRHUkSBCCnDOXxQqYOPahDVQzYowrw=',
|
|
35
|
+
STSTestOrchestratorService = 'CU1sVlS6vsEe3O3VvNzKFdBnQd9pQ83w9RyVx/7tJfc=',
|
|
36
|
+
STSTestRunnerNode = 'aX9dJbsT06V1G4j06xEIQ/rZ2CDlpzggU58aLtZ8fzE=',
|
|
37
|
+
STSBrokerService = 'TRppBuvxcjL7jrY9lCASJ5st8JpU8WlhAUAWoX/KKQ4=',
|
|
38
|
+
STSTestingService = '4Mtb3ABdSzZvSz4T51HPJhT14znVnqVDRFiZsvDNAOg=',
|
|
39
|
+
XXSTSAuthenticateSPAXX = 'v4qBrds3Autl/i86xT+5z0K53kJ/2hHTfxNo0QO/0Jk=',
|
|
40
|
+
STSTestRunnerAgentSPA = 'yDbklCH3awzDNuHICuco9mjDqhdzCa8m7w/UE9Opexc=',
|
|
41
|
+
STSClientApp01SPA = 'FDX/CPyDb3m6d9G2k+wDX8Uvey+yCkllaT4EuEt4QyU=',
|
|
42
|
+
PowerPlatformCustomConnectorSPA = 'fcdcebb5-d154-4699-b99d-87d29e5e148f'
|
|
43
|
+
}
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
export class AuthUtilsNode
|
|
47
|
+
{
|
|
48
|
+
#cookiejar: tough.CookieJar;
|
|
49
|
+
#httpsAgent: https.Agent | null = null;
|
|
50
|
+
#debug = debugModule(`proc:${process.pid}:AuthUtilsNode`);
|
|
51
|
+
// Regular expression to match the origin
|
|
52
|
+
#originRegex = /^(api:\/\/\w+)/;
|
|
53
|
+
|
|
54
|
+
constructor() {
|
|
55
|
+
this.#cookiejar = new tough.CookieJar();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#GetHttpsAgent = () =>
|
|
59
|
+
{
|
|
60
|
+
if (this.#httpsAgent === null) {
|
|
61
|
+
// https://nodejs.org/api/http.html#class-httpagent
|
|
62
|
+
this.#httpsAgent = new https.Agent({
|
|
63
|
+
keepAlive: goptions.keepAlive,
|
|
64
|
+
maxSockets: goptions.maxSockets,
|
|
65
|
+
maxTotalSockets: goptions.maxTotalSockets,
|
|
66
|
+
maxFreeSockets: goptions.maxFreeSockets,
|
|
67
|
+
timeout: goptions.timeout,
|
|
68
|
+
rejectUnauthorized: false
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return this.#httpsAgent;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
VerifyRequestMiddlewareFactory(options: IAuthUtilsNodeOptions) {
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
|
+
return async function(req: any, res: any, next: any) {
|
|
77
|
+
if (options.permissions) {
|
|
78
|
+
const scopes = req.auth.scope.split(' ');
|
|
79
|
+
const requiredPermissions = [ ];
|
|
80
|
+
for (let i=0; i < options.permissions.length; i++) {
|
|
81
|
+
const permission = options.permissions[i];
|
|
82
|
+
if (!scopes.includes(permission)) {
|
|
83
|
+
requiredPermissions.push(permission);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (requiredPermissions.length > 0) {
|
|
87
|
+
const errorPayload = GetErrorPayload(AppFrameworkErrorCode.APPFRAMEWORK_MISSING_PERMISSION, requiredPermissions);
|
|
88
|
+
res.status(StatusCodes.UNAUTHORIZED).send( { status: StatusCodes.UNAUTHORIZED, error: errorPayload });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
next();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/*
|
|
96
|
+
let cookies = await this.GetCookiesFromJar();
|
|
97
|
+
const valid = this.#ValidateCookies(cookies);
|
|
98
|
+
if (valid) {
|
|
99
|
+
next();
|
|
100
|
+
} else {
|
|
101
|
+
const error = { }; //@@
|
|
102
|
+
const invalidToken = false; //@@
|
|
103
|
+
if (invalidToken)
|
|
104
|
+
{
|
|
105
|
+
res.status(StatusCodes.UNAUTHORIZED).send( { status: StatusCodes.UNAUTHORIZED, error: 'Invalid Token', detail: error } );
|
|
106
|
+
} else{
|
|
107
|
+
res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( { status: StatusCodes.INTERNAL_SERVER_ERROR, error: 'Operation was not successful', detail: error } );
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
113
|
+
async verifyRequestMiddleware(req: any, res: any, next: any)
|
|
114
|
+
{
|
|
115
|
+
next();
|
|
116
|
+
/*
|
|
117
|
+
|
|
118
|
+
let cookies = await this.GetCookiesFromJar();
|
|
119
|
+
|
|
120
|
+
const valid = this.#ValidateCookies(cookies);
|
|
121
|
+
|
|
122
|
+
if (valid) {
|
|
123
|
+
next();
|
|
124
|
+
} else {
|
|
125
|
+
const error = { }; //@@
|
|
126
|
+
const invalidToken = false; //@@
|
|
127
|
+
if (invalidToken)
|
|
128
|
+
{
|
|
129
|
+
res.status(StatusCodes.UNAUTHORIZED).send( { status: StatusCodes.UNAUTHORIZED, error: 'Invalid Token', detail: error } );
|
|
130
|
+
} else{
|
|
131
|
+
res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( { status: StatusCodes.INTERNAL_SERVER_ERROR, error: 'Operation was not successful', detail: error } );
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
*/
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
138
|
+
SetCookiesToJar = async (headers: Record<string, any>, endpoint: string): Promise<tough.Cookie[]> =>
|
|
139
|
+
{
|
|
140
|
+
if (headers['set-cookie']) {
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
142
|
+
headers['set-cookie'].map((headerCookie: any) => {
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
+
const cookie: any = tough.Cookie.parse(headerCookie);
|
|
145
|
+
this.#cookiejar.setCookieSync(cookie, endpoint);
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
149
|
+
const cookie: any = tough.Cookie.parse(headers['set-cookie']);
|
|
150
|
+
this.#cookiejar.setCookieSync(cookie, endpoint);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return this.#cookiejar.getCookies(endpoint);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
GetCookiesFromJar = async (endpoint: string): Promise<tough.Cookie[]> =>
|
|
157
|
+
{
|
|
158
|
+
return this.#cookiejar.getCookies(endpoint);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
ValidateJWT = async (token: string, audience: string, endpoint?: string): Promise<string> => {
|
|
162
|
+
const jwksClientUri = (endpoint
|
|
163
|
+
? `${endpoint}${goptions.asoauthapiroot}${goptions.asjwksjsonpath}`
|
|
164
|
+
: `${goptions.asendpoint}:${goptions.asport}${goptions.asoauthapiroot}${goptions.asjwksjsonpath}`);
|
|
165
|
+
|
|
166
|
+
const jwks = jwksClient({
|
|
167
|
+
cache: true, //@@ all config items
|
|
168
|
+
cacheMaxEntries: 5, // Default value
|
|
169
|
+
cacheMaxAge: 600000, // Defaults to 10m
|
|
170
|
+
rateLimit: true,
|
|
171
|
+
jwksRequestsPerMinute: 10, // Default value
|
|
172
|
+
jwksUri: jwksClientUri,
|
|
173
|
+
timeout: 30000, //@@ config
|
|
174
|
+
requestAgent: this.#GetHttpsAgent()
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Use decode to get the kid
|
|
178
|
+
const decodedRefreshToken = jwtDecode<JSONObject>(token, { header: true });
|
|
179
|
+
const kid = decodedRefreshToken.kid;
|
|
180
|
+
|
|
181
|
+
const key = await jwks.getSigningKey(kid);
|
|
182
|
+
const signingKey = key.getPublicKey();
|
|
183
|
+
|
|
184
|
+
const verifyOptions = {
|
|
185
|
+
issuer: 'https://stsmda.com.au/stsauth/',
|
|
186
|
+
//subject: s,
|
|
187
|
+
audience: audience,
|
|
188
|
+
//expiresIn: 600, // 10 minutes
|
|
189
|
+
algorithm: ["RS256"] // RSASSA [ "RS256", "RS384", "RS512" ]
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
return jwt.verify(token, signingKey, verifyOptions) as string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Function to extract the origin from a URI
|
|
196
|
+
ExtractOrigin = (uri: string) => {
|
|
197
|
+
const match = uri.match(this.#originRegex);
|
|
198
|
+
return match ? match[1] : null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
*
|
|
203
|
+
* @param clientId
|
|
204
|
+
* @param authClientSecret
|
|
205
|
+
* @param scope space seperate list of fully qualifed required scopes (i.e. api://<<api id>>/<<resource>>.<<permission>>). Note the scopes must all be for the same client api.
|
|
206
|
+
* @param endPoint
|
|
207
|
+
* @returns
|
|
208
|
+
*/
|
|
209
|
+
GetAPITokenFromAuthServerUsingScope = async (clientId: string, authClientSecret: string, scope: string, endPoint?: string): Promise<string> => {
|
|
210
|
+
try {
|
|
211
|
+
const scopes = scope.split(' ');
|
|
212
|
+
let origin: string | null = null;
|
|
213
|
+
scopes.forEach((s) => {
|
|
214
|
+
if (!origin) {
|
|
215
|
+
origin = this.ExtractOrigin(s);
|
|
216
|
+
if (!origin) {
|
|
217
|
+
throw new Error(`Scope: [${scope}] not in required format. Must use (space seperated) api://<client id>[/<resource>.<permission>].`);
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
const nextOrigin: string | null = this.ExtractOrigin(s);
|
|
221
|
+
if (!nextOrigin) {
|
|
222
|
+
throw new Error(`Scope: [${scope}] not in required format. Must use (space seperated) api://<client id>[/<resource>.<permission>].`);
|
|
223
|
+
} else {
|
|
224
|
+
if (origin.localeCompare(nextOrigin) !== 0) {
|
|
225
|
+
throw new Error(`Scope: [${scope}] not all from the same client API. All scopes must come from the same client API.`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const headers = { 'Content-Type': 'application/json'};
|
|
232
|
+
const payload = { //@@ make a type
|
|
233
|
+
client_id: clientId, // The service calling this method
|
|
234
|
+
client_secret: authClientSecret, // Auth service client secret
|
|
235
|
+
//client_secret: goptions.brokerclientsecret, // Broker service client secret
|
|
236
|
+
scope: scope, // required API
|
|
237
|
+
//@@ remove audience
|
|
238
|
+
//@@ need scope to be the API identifier
|
|
239
|
+
grant_type: "client_credentials"
|
|
240
|
+
}
|
|
241
|
+
const url = (endPoint
|
|
242
|
+
? `${endPoint}${goptions.asoauthapiroot}/token`
|
|
243
|
+
: `${goptions.asendpoint}:${goptions.asport}${goptions.asoauthapiroot}/token`);
|
|
244
|
+
const retVal = await axios({
|
|
245
|
+
url
|
|
246
|
+
,method: 'post'
|
|
247
|
+
,data: payload
|
|
248
|
+
,headers: headers
|
|
249
|
+
,httpsAgent: this.#GetHttpsAgent()
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
if (retVal.status) {
|
|
253
|
+
if (retVal.status !== 200) {
|
|
254
|
+
// Just provide a warning here
|
|
255
|
+
this.#debug(chalk.magenta(`Error (AuthUtilsNode:GetAPITokenFromServer): Invalid response from server: [${retVal.status}]`));
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
const msg = chalk.red(`Error (AuthUtilsNode:GetAPITokenFromServer:No retVal.status)`);
|
|
259
|
+
this.#debug(msg);
|
|
260
|
+
throw new Error(msg);
|
|
261
|
+
}
|
|
262
|
+
if (retVal.data) {
|
|
263
|
+
if (retVal.data.access_token) {
|
|
264
|
+
return retVal.data.access_token as string;
|
|
265
|
+
} else {
|
|
266
|
+
const msg = chalk.red(`Error (AuthUtilsNode:GetAPITokenFromServer:No retVal.data.access_token)`);
|
|
267
|
+
this.#debug(msg);
|
|
268
|
+
throw new Error(msg);
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
const msg = chalk.red(`Error (AuthUtilsNode:GetAPITokenFromServer:No retVal.data)`);
|
|
272
|
+
this.#debug(msg);
|
|
273
|
+
throw new Error(msg);
|
|
274
|
+
}
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
276
|
+
} catch (error: any) {
|
|
277
|
+
this.#debug(chalk.red(`Error (AuthUtilsNode:GetAPITokenFromServer:catch): ${error}`));
|
|
278
|
+
if (error.response && error.response.data) {
|
|
279
|
+
this.#debug(chalk.red(`Details: [${JSON.stringify(error.response.data)}]`));
|
|
280
|
+
}
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/*
|
|
286
|
+
#getHttpsAgent = () =>
|
|
287
|
+
{
|
|
288
|
+
if (this.#httpsAgent === null) {
|
|
289
|
+
// https://nodejs.org/api/http.html#class-httpagent
|
|
290
|
+
this.#httpsAgent = new https.Agent({
|
|
291
|
+
keepAlive: goptions.keepAlive,
|
|
292
|
+
maxSockets: goptions.maxSockets,
|
|
293
|
+
maxTotalSockets: goptions.maxTotalSockets,
|
|
294
|
+
maxFreeSockets: goptions.maxFreeSockets,
|
|
295
|
+
timeout: goptions.timeout,
|
|
296
|
+
rejectUnauthorized: goptions.isProduction // Allows self signed certs in non production mode(s)
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
return this.#httpsAgent;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
Login = async (opts) =>
|
|
303
|
+
{
|
|
304
|
+
const { authendpoint, authUserName, authUserEMail, authUserPassword, defaultTimeout, publishDebug } = opts;
|
|
305
|
+
try {
|
|
306
|
+
const processStart = performance.now();
|
|
307
|
+
let duration = '';
|
|
308
|
+
let loginData = null;
|
|
309
|
+
const payload = { name: authUserName, password: authUserPassword, email: authUserEMail }
|
|
310
|
+
const retVal = await axios({
|
|
311
|
+
url: `${authendpoint}/login`
|
|
312
|
+
,method: 'post'
|
|
313
|
+
,data: payload
|
|
314
|
+
,timeout: defaultTimeout
|
|
315
|
+
,httpsAgent: this.#getHttpsAgent()
|
|
316
|
+
// Use below if using a socket endpoint
|
|
317
|
+
//,socketPath: '/var/run/sts/stsrest01.sock'
|
|
318
|
+
});
|
|
319
|
+
duration = (performance.now() - processStart).toFixed(4);
|
|
320
|
+
if (publishDebug) debug(`AuthUtilsNode.LoginNode request duration: [${duration}]`);
|
|
321
|
+
loginData = retVal.data.detail;
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
if (retVal.headers['set-cookie'] instanceof Array) {
|
|
325
|
+
this.#cookies = retVal.headers['set-cookie'].map(cookie.parse);
|
|
326
|
+
} else {
|
|
327
|
+
this.#cookies = [cookie.parse(retVal.headers['set-cookie'])];
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
//await this.SetCookiesToJar(retVal.headers);
|
|
331
|
+
|
|
332
|
+
return loginData;
|
|
333
|
+
} catch (error)
|
|
334
|
+
{
|
|
335
|
+
if (publishDebug) debug(chalk.red(`Error (AuthUtilsNode:LoginNode): ${error}`));
|
|
336
|
+
throw error;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// https://stackoverflow.com/questions/43002444/make-axios-send-cookies-in-its-requests-automatically
|
|
341
|
+
// axios.get('some api url', {withCredentials: true});
|
|
342
|
+
// https://medium.com/@adityasrivast/handling-cookies-with-axios-872790241a9b
|
|
343
|
+
// https://www.codegrepper.com/code-examples/javascript/axios+send+cookies
|
|
344
|
+
// http only cookies
|
|
345
|
+
RefreshSessionToken = async (opts) =>
|
|
346
|
+
{
|
|
347
|
+
const { authendpoint, defaultTimeout, publishDebug } = opts;
|
|
348
|
+
try {
|
|
349
|
+
const processStart = performance.now();
|
|
350
|
+
let duration = '';
|
|
351
|
+
let loginData = null;
|
|
352
|
+
const cookies = await this.GetCookiesFromJar();
|
|
353
|
+
const retVal = await axios({
|
|
354
|
+
url: `${authendpoint}/refreshtoken`
|
|
355
|
+
,method: 'post'
|
|
356
|
+
,headers: {
|
|
357
|
+
Cookie: cookies
|
|
358
|
+
}
|
|
359
|
+
,timeout: defaultTimeout
|
|
360
|
+
,httpsAgent: this.#httpsAgent,
|
|
361
|
+
// Use below for socket connections
|
|
362
|
+
//,socketPath: '/var/run/sts/stsrest01.sock'
|
|
363
|
+
});
|
|
364
|
+
duration = (performance.now() - processStart).toFixed(4);
|
|
365
|
+
if (publishDebug) debug(`AuthUtilsNode.RefreshAuthTokenBrowser request duration: [${duration}]`);
|
|
366
|
+
loginData = retVal.data.detail;
|
|
367
|
+
await this.SetCookiesToJar(retVal.headers);
|
|
368
|
+
return loginData;
|
|
369
|
+
} catch (error) {
|
|
370
|
+
if (publishDebug) debug(chalk.red(`Error (AuthUtilsNode:RefreshAuthTokenBrowser): ${error}`));
|
|
371
|
+
throw error;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
*/
|
|
375
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
|
|
2
|
+
import { Server, Socket, Namespace } from "socket.io";
|
|
3
|
+
|
|
4
|
+
import { STSOptionsBase, JSONObject } from "@nsshunt/stsutils"
|
|
5
|
+
import { PublishInstrumentControllerV2, InstrumentDefinitions } from '@nsshunt/stspublisherserver'
|
|
6
|
+
import { InstrumentBaseTelemetry, Gauge, InstrumentBase } from '@nsshunt/stsinstrumentation'
|
|
7
|
+
import { PGAccessLayer } from '@nsshunt/stsdatamanagement'
|
|
8
|
+
import { STSDefaultClientToServerEvents, STSDefaultServerToClientEvents } from '@nsshunt/stssocketio-client'
|
|
9
|
+
import { Consumer, IHeaders } from 'kafkajs'
|
|
10
|
+
|
|
11
|
+
export enum IPCMessageCommand {
|
|
12
|
+
AddWorker = 'AddWorker',
|
|
13
|
+
DeleteWorker = 'DeleteWorker'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface IPCMessagePayload {
|
|
17
|
+
requestResponse: boolean,
|
|
18
|
+
id: string,
|
|
19
|
+
command: IPCMessageCommand,
|
|
20
|
+
requestDetail?: JSONObject,
|
|
21
|
+
responseDetail?: JSONObject
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface IPCMessage {
|
|
25
|
+
iPCMessagePayload: IPCMessagePayload
|
|
26
|
+
cb: () => void,
|
|
27
|
+
timeout: NodeJS.Timeout
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type IPCMessages = Record<string, IPCMessage>
|
|
31
|
+
|
|
32
|
+
//------------------------------------
|
|
33
|
+
|
|
34
|
+
export interface IProcessBase extends STSOptionsBase {
|
|
35
|
+
SetupInstrumentation(): void
|
|
36
|
+
GetAdditionalInstruments(): InstrumentDefinitions
|
|
37
|
+
CollectAdditionalTelemetry(): void
|
|
38
|
+
ProcessStartup: () => void
|
|
39
|
+
UpdateInstrument: (instrumentName: Gauge, telemetry: InstrumentBaseTelemetry) => void
|
|
40
|
+
get InstrumentController(): PublishInstrumentControllerV2 | null
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
+
LogEx: (message: any) => void
|
|
43
|
+
InstrumentExists(instrumentName: Gauge): boolean
|
|
44
|
+
ProcessTerminate: () => Promise<void>
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
GetUIController(): any
|
|
47
|
+
get socketIoServerHelper(): ISocketIoServerHelper<STSDefaultClientToServerEvents, STSDefaultServerToClientEvents> | null
|
|
48
|
+
set socketIoServerHelper(value: ISocketIoServerHelper<STSDefaultClientToServerEvents, STSDefaultServerToClientEvents> | null)
|
|
49
|
+
TerminateDatabase(): Promise<void>
|
|
50
|
+
get accessLayer(): PGAccessLayer | null
|
|
51
|
+
get shuttingDown(): boolean
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface IMasterProcessBase extends IProcessBase {
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
56
|
+
WorkerMessageEvent(msg: any): any
|
|
57
|
+
SetupServer: () => Promise<void>
|
|
58
|
+
SetupServerEx: () => Promise<void>
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
KillWorker: (id: string, signal: NodeJS.Signals, options: any, killProcess: boolean, allowKillAll: boolean) => boolean
|
|
61
|
+
KillWorkers: (signal: NodeJS.Signals) => void
|
|
62
|
+
IncWorkers: () => void
|
|
63
|
+
DecWorkers: () => void
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
65
|
+
AddWorker: (options: any) => number
|
|
66
|
+
MasterStarted(): void
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
+
BroadcastDataToWorkers: (command: any, data: any) => void
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
70
|
+
ProcessTerminating(): Promise<void>
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface ISingleProcessBase extends IProcessBase {
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
+
get httpServer(): any
|
|
76
|
+
CollectAdditionalTelemetry(): void
|
|
77
|
+
ProcessStarted(): any
|
|
78
|
+
get io(): any
|
|
79
|
+
ProcessTerminating(): Promise<void>
|
|
80
|
+
get expressServer(): any // STSExpressServer - need to put interface in common types - circular reference
|
|
81
|
+
SetupServer(): Promise<boolean>
|
|
82
|
+
SetupServerEx: () => Promise<void>
|
|
83
|
+
TerminateApplication(): Promise<void>
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface IWorkerProcessBase extends IProcessBase {
|
|
87
|
+
get httpServer(): any
|
|
88
|
+
WorkerStarted(): any
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
90
|
+
ReceivedMessageFromMaster(msg: any): void
|
|
91
|
+
CollectAdditionalTelemetry(): void
|
|
92
|
+
get io(): any
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
|
+
AddWorker: (options: any) => Promise<string>
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
|
+
DeleteWorker: (workerId: string, options: any) => Promise<JSONObject>
|
|
97
|
+
ProcessTerminating(): Promise<void>
|
|
98
|
+
get expressServer(): any
|
|
99
|
+
SetupServer: () => Promise<void>
|
|
100
|
+
SetupServerEx: () => Promise<void>
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// -----------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
export type ServerEventCb = (socket: any, data: any) => void
|
|
106
|
+
|
|
107
|
+
export interface ServerSocketEvent {
|
|
108
|
+
serverEventName: string,
|
|
109
|
+
serverEventCb: ServerEventCb
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export enum STSNamespace {
|
|
113
|
+
STSMonitor = 'stsmonitor',
|
|
114
|
+
STSControl = 'stscontrol'
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export enum STSRoom {
|
|
118
|
+
// STSMonitor rooms
|
|
119
|
+
STSInstrumentDataRoom = 'stsinstrumentdataroom', // This room is for all instrument data messages
|
|
120
|
+
STSInstrumentDataSubscriptionRoom = 'stsinstrumentdatasubscriptionroom', // This room is only for subscribed instrument data messages
|
|
121
|
+
|
|
122
|
+
// STSControl rooms
|
|
123
|
+
STSRunnerRoom = 'stsrunnerroom',
|
|
124
|
+
STSNodeRunnerRoom = 'stsnoderunnerroom'
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export enum STSEvent {
|
|
128
|
+
// STSInstrumentData
|
|
129
|
+
STSInstrumentData = 'stsinstrumentdata',
|
|
130
|
+
STSSubInstrumentData = 'stssubinstrumentdata', // sub-scribed instrument data. This only outputs the nodes that have been subscribed by the client(s).
|
|
131
|
+
STSResetInstrumentData = 'stsresetinstrumentdata',
|
|
132
|
+
|
|
133
|
+
STSStartLoggingInstrumentData = 'stsStartLoggingInstrumentData',
|
|
134
|
+
STSStopLoggingInstrumentData = 'stsStopLoggingInstrumentData',
|
|
135
|
+
|
|
136
|
+
// STSRunner events
|
|
137
|
+
STSStart = 'stsstart', // Start a test run with options as payload.
|
|
138
|
+
STSStop = 'stsstop', // Stop test run(s).
|
|
139
|
+
STSPause = 'stspause', // Pause test run(s).
|
|
140
|
+
STSResume = 'stsresume', // Resume test run(s).
|
|
141
|
+
STSTerminate = 'ststerminate', // Terminate runner instances and exit applications.
|
|
142
|
+
// This may also be uysed to force trigger self healing (i.e. auto re-start) when
|
|
143
|
+
// running within a container orchestrator such as K8, K3 or Docker Swarm.
|
|
144
|
+
STSUpdateStaticConfig = 'stsupdatestaticconfig', // Update base configuration. Options as payload.
|
|
145
|
+
STSUpdateDynamicConfig = 'stsupdatedynamicconfig', // Update running configuration. This is used
|
|
146
|
+
// to control the runnning behaviour of test(s) in-flight. Options as payload.
|
|
147
|
+
|
|
148
|
+
STSSendToRoom = 'sendToRoom',
|
|
149
|
+
|
|
150
|
+
// Standard socket events
|
|
151
|
+
connect = 'connect'
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// https://socket.io/docs/v4/typescript/
|
|
155
|
+
|
|
156
|
+
export interface InterServerEvents {
|
|
157
|
+
ping: () => void;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface STSSocketIONamespace {
|
|
161
|
+
namespace: string
|
|
162
|
+
pid: number
|
|
163
|
+
socketionamespace: Namespace<STSDefaultClientToServerEvents, STSDefaultServerToClientEvents, InterServerEvents>
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export type STSServerSocket = Socket<STSDefaultClientToServerEvents, STSDefaultServerToClientEvents, InterServerEvents>
|
|
167
|
+
export type STSClientSocket = Socket<STSDefaultServerToClientEvents, STSDefaultClientToServerEvents, InterServerEvents>
|
|
168
|
+
|
|
169
|
+
export interface ISocketIoServerHelper<ClientToServerEvents extends STSDefaultClientToServerEvents, ServerToClientEvents extends STSDefaultServerToClientEvents>
|
|
170
|
+
{
|
|
171
|
+
LogMessage: (namespace: STSSocketIONamespace, message: string) => void
|
|
172
|
+
LeaveRoom: (namespace: STSSocketIONamespace, socket: STSServerSocket, room: STSRoom) => void
|
|
173
|
+
JoinRoom: (namespace: STSSocketIONamespace, socket: STSServerSocket, room: STSRoom) => void
|
|
174
|
+
SetupNamespace: (io: Server, namespace: STSNamespace, rooms: string[], autoJoinRooms: boolean,
|
|
175
|
+
/* serverSocketEvents: ServerSocketEvent[], */
|
|
176
|
+
socketConnectCallBack: ((socket: Socket<ClientToServerEvents, ServerToClientEvents, InterServerEvents>) => void) | null,
|
|
177
|
+
socketEventsCallBack: ((socket: Socket<ClientToServerEvents, ServerToClientEvents, InterServerEvents>) => void) | null
|
|
178
|
+
) => Namespace<ClientToServerEvents, ServerToClientEvents, InterServerEvents>
|
|
179
|
+
GetSTSSocketIONamespace: (namespace: any) => STSSocketIONamespace
|
|
180
|
+
DisconnectSockets: () => void
|
|
181
|
+
SetupEvent(event: ClientToServerEvents, eventCb: ServerEventCb): ISocketIoServerHelper<ClientToServerEvents, ServerToClientEvents>
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface IInfluxDBManagerOptions {
|
|
185
|
+
token: string // API access token
|
|
186
|
+
url: string // end-pont for API
|
|
187
|
+
org: string // organisation
|
|
188
|
+
bucket: string // bucket to store results
|
|
189
|
+
agent?: {
|
|
190
|
+
influxDB_keepAlive: boolean
|
|
191
|
+
influxDB_maxSockets?: number
|
|
192
|
+
influxDB_maxTotalSockets?: number
|
|
193
|
+
influxDB_maxFreeSockets?: number
|
|
194
|
+
influxDB_timeout?: number
|
|
195
|
+
influxDB_rejectUnauthorized?: boolean
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export type Nid = string;
|
|
200
|
+
|
|
201
|
+
export interface ContextBase extends JSONObject {
|
|
202
|
+
nid?: Nid
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface ServiceProcessContext extends ContextBase {
|
|
206
|
+
serviceId?: string // Service name and the service version
|
|
207
|
+
|
|
208
|
+
serviceInstanceId?: string // Service unique id and the host name
|
|
209
|
+
sid?: string // Service unique id only, does not include host
|
|
210
|
+
hostName?: string // Service Instance Host Name
|
|
211
|
+
|
|
212
|
+
// Left level attributes
|
|
213
|
+
serviceInstanceProcessId?: string // Service Instance OS Process ID (parent process id)
|
|
214
|
+
pid?: number // Service Instance OS Process ID (parent process id)
|
|
215
|
+
ppid?: number// Service Instance OS Parent Process ID if worker. Will be pid if parent process.
|
|
216
|
+
isMaster?: boolean // True if is Master Process
|
|
217
|
+
isWorker?: boolean // True if is Worker Process
|
|
218
|
+
serviceName?: string // Defined in .env or environment variable
|
|
219
|
+
serviceVersion?: string // Defined in .env or environment variable
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface InstrumentPayload {
|
|
223
|
+
//nid: string
|
|
224
|
+
context: ServiceProcessContext
|
|
225
|
+
instruments: Record<string, InstrumentBase>
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface IKafkaConsumer {
|
|
229
|
+
get consumer(): Consumer
|
|
230
|
+
get id(): string
|
|
231
|
+
Connect(): Promise<void>
|
|
232
|
+
Disconnect(): Promise<void>
|
|
233
|
+
Subscribe: (topics: string[], fromBeginning: boolean) => Promise<void>
|
|
234
|
+
Stop: () => Promise<void>
|
|
235
|
+
StartConsumingMessages: (cb: (topic: string, key: string, partition: number, value: string, headers: IHeaders | undefined) => void) => Promise<void>
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export type logFunction = (msg: any) => void
|
|
239
|
+
|
package/src_new/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export * from './commonTypes'
|
|
2
|
+
export * from './processoptions'
|
|
3
|
+
export * from './authDefs'
|
|
4
|
+
export * from './authutilsnode'
|
|
5
|
+
export * from './stsrouterbase'
|
|
6
|
+
export * from './stscontrollerbase'
|
|
7
|
+
export * from './singleprocessbase'
|
|
8
|
+
export * from './masterprocessbase'
|
|
9
|
+
export * from './workerprocessbase'
|
|
10
|
+
export * from './socketIoServerHelper'
|
|
11
|
+
export * from './stslatencycontroller'
|
|
12
|
+
export * from './stslatencyroute'
|
|
13
|
+
export * from './kafka/kafkamanager'
|
|
14
|
+
export * from './kafka/kafkaproducer'
|
|
15
|
+
export * from './kafka/kafkaconsumer'
|
|
16
|
+
export * from './kafka/IMKafkaManager'
|
|
17
|
+
export * from './influxdb/influxDBManager'
|
|
18
|
+
export * from './influxdb/influxDBManagerBase'
|
|
19
|
+
export * from './influxdb/influxDBManagerService'
|
|
20
|
+
export * from './influxdb/influxDBManagerAgent'
|
|
21
|
+
export * from './publishertransports/publishTransportUtils'
|
|
22
|
+
export * from './instrumentationsubscriber'
|