@nsshunt/stsappframework 3.0.104 → 3.0.106
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/influxdb/influxDBManager.js +16 -17
- package/dist/influxdb/influxDBManager.js.map +1 -1
- package/dist/influxdb/influxDBManagerAgent.js +9 -13
- package/dist/influxdb/influxDBManagerAgent.js.map +1 -1
- package/dist/influxdb/influxDBManagerBase.js +2 -6
- package/dist/influxdb/influxDBManagerBase.js.map +1 -1
- package/dist/influxdb/influxDBManagerService.js +10 -14
- package/dist/influxdb/influxDBManagerService.js.map +1 -1
- package/dist/instrumentationsubscriber.js +11 -15
- package/dist/instrumentationsubscriber.js.map +1 -1
- package/dist/kafka/IMKafkaManager.js +2 -6
- package/dist/kafka/IMKafkaManager.js.map +1 -1
- package/dist/kafkatesting/produce.js +1 -5
- package/dist/kafkatesting/produce.js.map +1 -1
- package/dist/processbase.js +7 -8
- package/dist/processbase.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/tcpclient/app2.js +2 -2
- package/dist/tcpserver/appmaster.js +39 -16
- package/dist/tcpserver/appmaster.js.map +1 -1
- package/package.json +7 -7
- package/src/influxdb/influxDBManager.ts +16 -18
- package/src/influxdb/influxDBManagerAgent.ts +9 -11
- package/src/influxdb/influxDBManagerBase.ts +2 -4
- package/src/influxdb/influxDBManagerService.ts +10 -12
- package/src/instrumentationsubscriber.ts +11 -14
- package/src/kafka/IMKafkaManager.ts +2 -4
- package/src/kafkatesting/produce.ts +1 -3
- package/src/processbase.ts +7 -9
- package/src/server.ts +1 -1
- package/src/tcpclient/app2.ts +2 -2
- package/src/tcpserver/appmaster.ts +39 -17
- package/types/influxdb/influxDBManager.d.ts.map +1 -1
- package/types/influxdb/influxDBManagerAgent.d.ts.map +1 -1
- package/types/influxdb/influxDBManagerBase.d.ts.map +1 -1
- package/types/influxdb/influxDBManagerService.d.ts.map +1 -1
- package/types/instrumentationsubscriber.d.ts.map +1 -1
- package/types/kafka/IMKafkaManager.d.ts.map +1 -1
- package/types/processbase.d.ts +2 -2
- package/types/processbase.d.ts.map +1 -1
- package/types/tcpserver/appmaster.d.ts.map +1 -1
- package/src_working/authDefs.ts +0 -37
- package/src_working/authutilsnode.ts +0 -373
- package/src_working/commonTypes.ts +0 -239
- package/src_working/index.ts +0 -22
- package/src_working/influxdb/influxDBManager.ts +0 -970
- package/src_working/influxdb/influxDBManagerAgent.ts +0 -314
- package/src_working/influxdb/influxDBManagerBase.ts +0 -109
- package/src_working/influxdb/influxDBManagerService.ts +0 -373
- package/src_working/instrumentationsubscriber.ts +0 -283
- package/src_working/kafka/IMKafkaManager.ts +0 -152
- package/src_working/kafka/kafkaconsumer.ts +0 -82
- package/src_working/kafka/kafkamanager.ts +0 -186
- package/src_working/kafka/kafkaproducer.ts +0 -58
- package/src_working/kafkatesting/config.ts +0 -10
- package/src_working/kafkatesting/consume.ts +0 -116
- package/src_working/kafkatesting/produce.ts +0 -153
- package/src_working/masterprocessbase.ts +0 -598
- package/src_working/middleware/serverNetworkMiddleware.ts +0 -240
- package/src_working/network.ts +0 -36
- package/src_working/processbase.ts +0 -411
- package/src_working/processoptions.ts +0 -164
- package/src_working/publishertransports/publishTransportDirect.ts +0 -45
- package/src_working/publishertransports/publishTransportUtils.ts +0 -53
- package/src_working/server.ts +0 -141
- package/src_working/serverprocessbase.ts +0 -393
- package/src_working/singleprocessbase.ts +0 -121
- package/src_working/socketIoServerHelper.ts +0 -177
- package/src_working/stscontrollerbase.ts +0 -15
- package/src_working/stslatencycontroller.ts +0 -27
- package/src_working/stslatencyroute.ts +0 -16
- package/src_working/stsrouterbase.ts +0 -22
- package/src_working/tcpclient/app.ts +0 -19
- package/src_working/tcpclient/app2.ts +0 -56
- package/src_working/tcpserver/app.ts +0 -11
- package/src_working/tcpserver/appConfig.ts +0 -65
- package/src_working/tcpserver/appmaster.ts +0 -544
- package/src_working/validation/errors.ts +0 -6
- package/src_working/webworkertesting/app.ts +0 -49
- package/src_working/webworkertesting/worker.ts +0 -24
- package/src_working/workerprocessbase.test.ts +0 -47
- package/src_working/workerprocessbase.ts +0 -185
- package/src_working2/authDefs.ts +0 -37
- package/src_working2/authutilsnode.ts +0 -375
- package/src_working2/commonTypes.ts +0 -239
- package/src_working2/index.ts +0 -22
- package/src_working2/influxdb/influxDBManager.ts +0 -972
- package/src_working2/influxdb/influxDBManagerAgent.ts +0 -316
- package/src_working2/influxdb/influxDBManagerBase.ts +0 -111
- package/src_working2/influxdb/influxDBManagerService.ts +0 -375
- package/src_working2/instrumentationsubscriber.ts +0 -286
- package/src_working2/kafka/IMKafkaManager.ts +0 -154
- package/src_working2/kafka/kafkaconsumer.ts +0 -82
- package/src_working2/kafka/kafkamanager.ts +0 -186
- package/src_working2/kafka/kafkaproducer.ts +0 -58
- package/src_working2/kafkatesting/config.ts +0 -10
- package/src_working2/kafkatesting/consume.ts +0 -116
- package/src_working2/kafkatesting/produce.ts +0 -155
- package/src_working2/masterprocessbase.ts +0 -590
- package/src_working2/middleware/serverNetworkMiddleware.ts +0 -240
- package/src_working2/network.ts +0 -36
- package/src_working2/processbase.ts +0 -415
- package/src_working2/processoptions.ts +0 -164
- package/src_working2/publishertransports/publishTransportDirect.ts +0 -45
- package/src_working2/publishertransports/publishTransportUtils.ts +0 -53
- package/src_working2/server.ts +0 -141
- package/src_working2/serverprocessbase.ts +0 -393
- package/src_working2/singleprocessbase.ts +0 -123
- package/src_working2/socketIoServerHelper.ts +0 -177
- package/src_working2/stscontrollerbase.ts +0 -15
- package/src_working2/stslatencycontroller.ts +0 -27
- package/src_working2/stslatencyroute.ts +0 -16
- package/src_working2/stsrouterbase.ts +0 -22
- package/src_working2/tcpclient/app.ts +0 -19
- package/src_working2/tcpclient/app2.ts +0 -56
- package/src_working2/tcpserver/app.ts +0 -11
- package/src_working2/tcpserver/appConfig.ts +0 -65
- package/src_working2/tcpserver/appmaster.ts +0 -522
- package/src_working2/validation/errors.ts +0 -6
- package/src_working2/webworkertesting/app.ts +0 -49
- package/src_working2/webworkertesting/worker.ts +0 -24
- package/src_working2/workerprocessbase.test.ts +0 -47
- package/src_working2/workerprocessbase.ts +0 -187
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
|
|
2
|
-
import debugModule from 'debug'
|
|
3
|
-
const debug = debugModule(`proc:${process.pid}`);
|
|
4
|
-
|
|
5
|
-
import { Gauge, InstrumentGaugeTelemetry } from '@nsshunt/stsinstrumentation'
|
|
6
|
-
import { JSONObject } from '@nsshunt/stsutils'
|
|
7
|
-
import { ProcessOptions } from './processoptions'
|
|
8
|
-
import { IPCMessage, IPCMessages, IPCMessagePayload, IPCMessageCommand, IWorkerProcessBase } from './commonTypes'
|
|
9
|
-
import { STSExpressServer } from './server';
|
|
10
|
-
import { ServerProcessBase } from './serverprocessbase'
|
|
11
|
-
|
|
12
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
13
|
-
|
|
14
|
-
import colors from 'colors'
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* todo
|
|
18
|
-
* @typedef {Object} options - todo
|
|
19
|
-
* @property {boolean} [wssServer=false] - Create a web socket server on this worker instance
|
|
20
|
-
*/
|
|
21
|
-
export class WorkerProcessBase extends ServerProcessBase implements IWorkerProcessBase
|
|
22
|
-
{
|
|
23
|
-
#inFlightMessage: IPCMessages = { }
|
|
24
|
-
#requestResponseMessageTimeout = 2000; //@@ config
|
|
25
|
-
|
|
26
|
-
constructor(options: ProcessOptions) {
|
|
27
|
-
super(options);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
WorkerStarted() {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
35
|
-
ReceivedMessageFromMaster(msg: any) {
|
|
36
|
-
// Override in subclass if required
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
override CollectAdditionalTelemetry(): void {
|
|
40
|
-
this.httpServer.getConnections((error: any, count: any) => {
|
|
41
|
-
//@@this.instruments[Gauge.CONNECTION_COUNT_GAUGE].val = count;
|
|
42
|
-
this.UpdateInstrument(Gauge.CONNECTION_COUNT_GAUGE, {
|
|
43
|
-
val: count
|
|
44
|
-
} as InstrumentGaugeTelemetry);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
#SendMessageToParentProcess = (message: IPCMessagePayload): Promise<JSONObject> => {
|
|
49
|
-
return new Promise((resolve, reject) => {
|
|
50
|
-
if (this.#inFlightMessage[message.id]) {
|
|
51
|
-
reject(`Message with id: [${message.id}] already exists within the Request/Response record structure`);
|
|
52
|
-
} else {
|
|
53
|
-
this.#inFlightMessage[message.id] = {
|
|
54
|
-
iPCMessagePayload: { ...message },
|
|
55
|
-
cb: () => {
|
|
56
|
-
const detail: JSONObject = this.#inFlightMessage[message.id].iPCMessagePayload.responseDetail as JSONObject
|
|
57
|
-
clearTimeout(this.#inFlightMessage[message.id].timeout);
|
|
58
|
-
setTimeout(() => {
|
|
59
|
-
delete this.#inFlightMessage[message.id];
|
|
60
|
-
}, 0).unref();
|
|
61
|
-
debug(`Resolving response message with id: [${message.id}] from parent process via IPC. Details: [${JSON.stringify(this.#inFlightMessage[message.id].iPCMessagePayload)}]`.green);
|
|
62
|
-
resolve(detail);
|
|
63
|
-
},
|
|
64
|
-
timeout: setTimeout(() => {
|
|
65
|
-
setTimeout(() => {
|
|
66
|
-
delete this.#inFlightMessage[message.id];
|
|
67
|
-
}, 0).unref();
|
|
68
|
-
debug(`Timeout has occurred after: [${this.#requestResponseMessageTimeout}]ms with message id: [${message.id}]. Details: [${JSON.stringify(this.#inFlightMessage[message.id].iPCMessagePayload)}]`.red);
|
|
69
|
-
reject('Did not receive response form parent process.');
|
|
70
|
-
}, this.#requestResponseMessageTimeout) // max message timeout allowed
|
|
71
|
-
}
|
|
72
|
-
debug(`Sending message with id: [${message.id}] to parent process via IPC. Details: [${JSON.stringify(this.#inFlightMessage[message.id].iPCMessagePayload)}]`.yellow);
|
|
73
|
-
(process as any).send(message);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
-
AddWorker = async (options: any): Promise<string> => {
|
|
80
|
-
const workerResponse: JSONObject = await this.#SendMessageToParentProcess({
|
|
81
|
-
requestResponse: true,
|
|
82
|
-
id: uuidv4(),
|
|
83
|
-
command: IPCMessageCommand.AddWorker,
|
|
84
|
-
requestDetail: {
|
|
85
|
-
options
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
return workerResponse.workerId;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
92
|
-
DeleteWorker = async (workerId: string, options: any): Promise<JSONObject> => {
|
|
93
|
-
const workerResponse: JSONObject = await this.#SendMessageToParentProcess({
|
|
94
|
-
requestResponse: true,
|
|
95
|
-
id: uuidv4(),
|
|
96
|
-
command: IPCMessageCommand.DeleteWorker,
|
|
97
|
-
requestDetail: {
|
|
98
|
-
options,
|
|
99
|
-
workerId
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
return workerResponse;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
ProcessTerminating = async (): Promise<void> => {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
SetupServer = async () =>
|
|
110
|
-
{
|
|
111
|
-
this.SetupInstrumentation();
|
|
112
|
-
setTimeout(() => {
|
|
113
|
-
this.SetupServerEx();
|
|
114
|
-
}, 100);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
SetupServerEx = async () => {
|
|
118
|
-
this.ProcessStartup();
|
|
119
|
-
|
|
120
|
-
if (this.options.expressServerRouteFactory || this.options.expressServerRouteStaticFactory) {
|
|
121
|
-
this.expressServer = new STSExpressServer(this.options, this);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
this.LogEx(`Worker instance starting. Service instance Id: [${this.options.serviceInstanceId}]`);
|
|
125
|
-
|
|
126
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
127
|
-
process.on('message', async (msg: any) => {
|
|
128
|
-
if (msg.requestResponse) {
|
|
129
|
-
const iPCMessagePayload: IPCMessagePayload = msg as IPCMessagePayload;
|
|
130
|
-
if (iPCMessagePayload.id) {
|
|
131
|
-
if (this.#inFlightMessage[iPCMessagePayload.id]) {
|
|
132
|
-
const responseMessage: IPCMessage = this.#inFlightMessage[iPCMessagePayload.id];
|
|
133
|
-
responseMessage.iPCMessagePayload.responseDetail = { ...iPCMessagePayload.responseDetail }
|
|
134
|
-
responseMessage.cb();
|
|
135
|
-
} else {
|
|
136
|
-
throw new Error(`Could not find Request/Response message with id: [${iPCMessagePayload.id}]`);
|
|
137
|
-
}
|
|
138
|
-
} else {
|
|
139
|
-
throw new Error(`Message does not have id attribute. [${JSON.stringify(iPCMessagePayload)}]`);
|
|
140
|
-
}
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (msg.command) //@@ constants
|
|
144
|
-
{
|
|
145
|
-
switch (msg.command)
|
|
146
|
-
{
|
|
147
|
-
case 'Terminate' :
|
|
148
|
-
this.LogEx((`Received ` + colors.bold(`Terminate`.italic) + ` message from master thread`).gray);
|
|
149
|
-
await this.Terminate(true, false); // Don't kill the child process here, the master will take care of that ...
|
|
150
|
-
break;
|
|
151
|
-
case 'TerminateAndKill' :
|
|
152
|
-
this.LogEx((`Received ` + colors.bold(`Terminate`.italic) + ` message from master thread`).gray);
|
|
153
|
-
await this.Terminate(true, true);
|
|
154
|
-
break;
|
|
155
|
-
case 'Message' :
|
|
156
|
-
//this.LogEx((`Received ` + colors.bold(`Message`.italic) + ` message from master thread`).gray);
|
|
157
|
-
this.ReceivedMessageFromMaster(msg.data);
|
|
158
|
-
break;
|
|
159
|
-
case 'Response' : // General response to a req/response interaction
|
|
160
|
-
msg.details
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
// Signal Codes
|
|
166
|
-
// https://en.wikipedia.org/wiki/Signal_(IPC)
|
|
167
|
-
process.on('SIGTERM', async () =>
|
|
168
|
-
{
|
|
169
|
-
this.LogEx(`SIGTERM signal received for worker: ${process.pid}`);
|
|
170
|
-
await this.Terminate(true, true);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
process.on('SIGINT', async () =>
|
|
174
|
-
{
|
|
175
|
-
this.LogEx(`SIGINT signal received for worker: ${process.pid}`);
|
|
176
|
-
await this.Terminate(true, true);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
await this.SetupSTSServer();
|
|
180
|
-
|
|
181
|
-
this.WorkerStarted();
|
|
182
|
-
|
|
183
|
-
this.LogEx(`Worker process:${process.pid} started`.green);
|
|
184
|
-
};
|
|
185
|
-
}
|
package/src_working2/authDefs.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,375 +0,0 @@
|
|
|
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
|
-
}
|