@mojaloop/sdk-scheme-adapter 15.0.0 → 15.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/audit-resolve.json +43 -542
- package/docs/dfspInboundApi.yaml +11 -0
- package/package.json +25 -24
- package/src/ControlAgent/index.js +8 -11
- package/src/ControlServer/index.js +13 -13
- package/src/InboundServer/index.js +12 -61
- package/src/OAuthTestServer/index.js +0 -13
- package/src/OutboundServer/index.js +11 -54
- package/src/TestServer/index.js +6 -33
- package/src/config.js +1 -4
- package/src/index.js +163 -146
- package/src/lib/cache.js +93 -186
- package/src/lib/metrics.js +1 -1
- package/src/lib/model/InboundTransfersModel.js +10 -6
- package/src/lib/model/OutboundTransfersModel.js +1 -1
- package/test/__mocks__/redis.js +51 -26
- package/test/config/integration.env +1 -2
- package/test/integration/lib/cache.test.js +1 -2
- package/test/integration/testEnv.js +1 -4
- package/test/unit/ControlClient.test.js +1 -45
- package/test/unit/ControlServer/index.js +18 -22
- package/test/unit/ControlServer.test.js +0 -60
- package/test/unit/InboundServer.test.js +8 -8
- package/test/unit/TestServer.test.js +1 -1
- package/test/unit/api/accounts/accounts.test.js +2 -2
- package/test/unit/api/transfers/transfers.test.js +1 -1
- package/test/unit/api/utils.js +12 -4
- package/test/unit/config.test.js +1 -2
- package/test/unit/data/defaultConfig.json +1 -5
- package/test/unit/index.test.js +5 -64
- package/test/unit/lib/cache.test.js +5 -6
- package/test/unit/lib/model/AccountsModel.test.js +3 -4
- package/test/unit/lib/model/InboundTransfersModel.test.js +55 -16
- package/test/unit/lib/model/OutboundBulkQuotesModel.test.js +3 -4
- package/test/unit/lib/model/OutboundBulkTransfersModel.test.js +1 -2
- package/test/unit/lib/model/OutboundRequestToPayModel.test.js +3 -4
- package/test/unit/lib/model/OutboundRequestToPayTransferModel.test.js +3 -4
- package/test/unit/lib/model/OutboundTransfersModel.test.js +2 -3
- package/test/unit/lib/model/common/PersistentStateMachine.test.js +3 -4
- package/test/unit/lib/model/data/defaultConfig.json +1 -4
- package/test/unit/lib/model/data/notificationAbortedToPayee.json +10 -0
- package/test/unit/lib/model/data/notificationReservedToPayee.json +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mojaloop/sdk-scheme-adapter",
|
|
3
|
-
"version": "15.0.
|
|
3
|
+
"version": "15.0.1",
|
|
4
4
|
"description": "An adapter for connecting to Mojaloop API enabled switches.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"Shashikant Hirugade <shashikant.hirugade@modusbox.com>",
|
|
40
40
|
"Paweł Marzec <pawel.marzec@modusbox.com>",
|
|
41
41
|
"Kevin Leyow <kevin.leyow@modusbox.com",
|
|
42
|
-
"Miguel de Barros <miguel.debarros@modusbox.com>"
|
|
42
|
+
"Miguel de Barros <miguel.debarros@modusbox.com>",
|
|
43
|
+
"Yevhen Kyriukha <yevhen.kyriukha@modusbox.com>"
|
|
43
44
|
],
|
|
44
45
|
"license": "Apache-2.0",
|
|
45
46
|
"licenses": [
|
|
@@ -55,11 +56,11 @@
|
|
|
55
56
|
"dependencies": {
|
|
56
57
|
"@koa/cors": "^3.1.0",
|
|
57
58
|
"@mojaloop/central-services-shared": "17.0.2",
|
|
58
|
-
"@mojaloop/sdk-standard-components": "^17.0.
|
|
59
|
+
"@mojaloop/sdk-standard-components": "^17.0.4",
|
|
59
60
|
"ajv": "8.11.0",
|
|
60
|
-
"axios": "^0.
|
|
61
|
+
"axios": "^0.27.2",
|
|
61
62
|
"co-body": "^6.1.0",
|
|
62
|
-
"dotenv": "^
|
|
63
|
+
"dotenv": "^16.0.1",
|
|
63
64
|
"env-var": "^7.0.1",
|
|
64
65
|
"express": "^4.17.2",
|
|
65
66
|
"fast-json-patch": "^3.1.1",
|
|
@@ -67,36 +68,36 @@
|
|
|
67
68
|
"js-yaml": "^4.1.0",
|
|
68
69
|
"json-schema-ref-parser": "^9.0.9",
|
|
69
70
|
"koa": "^2.13.1",
|
|
70
|
-
"koa-body": "^
|
|
71
|
+
"koa-body": "^5.0.0",
|
|
71
72
|
"lodash": "^4.17.21",
|
|
72
73
|
"module-alias": "^2.2.2",
|
|
73
74
|
"oauth2-server": "^4.0.0-dev.2",
|
|
74
|
-
"openapi-jsonschema-parameters": "^
|
|
75
|
-
"prom-client": "^
|
|
75
|
+
"openapi-jsonschema-parameters": "^12.0.0",
|
|
76
|
+
"prom-client": "^14.0.1",
|
|
76
77
|
"promise-timeout": "^1.3.0",
|
|
77
78
|
"random-word-slugs": "^0.1.6",
|
|
78
|
-
"redis": "^
|
|
79
|
+
"redis": "^4.1.1",
|
|
79
80
|
"uuidv4": "^6.2.12",
|
|
80
|
-
"ws": "^
|
|
81
|
+
"ws": "^8.8.0"
|
|
81
82
|
},
|
|
82
83
|
"devDependencies": {
|
|
83
|
-
"@babel/core": "^7.
|
|
84
|
-
"@babel/preset-env": "^7.
|
|
85
|
-
"@mojaloop/api-snippets": "^
|
|
84
|
+
"@babel/core": "^7.18.6",
|
|
85
|
+
"@babel/preset-env": "^7.18.6",
|
|
86
|
+
"@mojaloop/api-snippets": "^14.0.0",
|
|
86
87
|
"@redocly/openapi-cli": "^1.0.0-beta.59",
|
|
87
|
-
"@types/jest": "^
|
|
88
|
-
"babel-jest": "^
|
|
89
|
-
"eslint": "^
|
|
90
|
-
"eslint-config-airbnb-base": "^
|
|
88
|
+
"@types/jest": "^28.1.4",
|
|
89
|
+
"babel-jest": "^28.1.2",
|
|
90
|
+
"eslint": "^8.18.0",
|
|
91
|
+
"eslint-config-airbnb-base": "^15.0.0",
|
|
91
92
|
"eslint-plugin-import": "^2.24.2",
|
|
92
|
-
"eslint-plugin-jest": "^
|
|
93
|
-
"jest": "^
|
|
94
|
-
"jest-junit": "^
|
|
95
|
-
"nock": "^13.
|
|
93
|
+
"eslint-plugin-jest": "^26.5.3",
|
|
94
|
+
"jest": "^28.1.2",
|
|
95
|
+
"jest-junit": "^14.0.0",
|
|
96
|
+
"nock": "^13.2.8",
|
|
96
97
|
"npm-audit-resolver": "^3.0.0-0",
|
|
97
|
-
"npm-check-updates": "^
|
|
98
|
-
"openapi-response-validator": "^
|
|
99
|
-
"openapi-typescript": "^4.0
|
|
98
|
+
"npm-check-updates": "^15.0.1",
|
|
99
|
+
"openapi-response-validator": "^12.0.0",
|
|
100
|
+
"openapi-typescript": "^5.4.0",
|
|
100
101
|
"redis-mock": "^0.56.3",
|
|
101
102
|
"standard-version": "^9.3.1",
|
|
102
103
|
"supertest": "^6.1.6",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
// It expects new configuration to be supplied as an array of JSON patches. It therefore exposes
|
|
23
23
|
// the current configuration to
|
|
24
24
|
|
|
25
|
-
const assert = require('assert').strict;
|
|
26
25
|
const ws = require('ws');
|
|
27
26
|
const jsonPatch = require('fast-json-patch');
|
|
28
27
|
const { generateSlug } = require('random-word-slugs');
|
|
28
|
+
const _ = require('lodash');
|
|
29
29
|
|
|
30
30
|
/**************************************************************************
|
|
31
31
|
* The message protocol messages, verbs, and errors
|
|
@@ -163,15 +163,6 @@ class Client extends ws {
|
|
|
163
163
|
this.close();
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
reconfigure({ logger = this._logger, port = 0, appConfig = this._appConfig }) {
|
|
167
|
-
assert(port === this._socket.remotePort, 'Cannot reconfigure running port');
|
|
168
|
-
return () => {
|
|
169
|
-
this._logger = logger;
|
|
170
|
-
this._appConfig = appConfig;
|
|
171
|
-
this._logger.log('restarted');
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
166
|
// Handle incoming message from the server.
|
|
176
167
|
_handle(data) {
|
|
177
168
|
// TODO: json-schema validation of received message- should be pretty straight-forward
|
|
@@ -187,7 +178,13 @@ class Client extends ws {
|
|
|
187
178
|
switch (msg.msg) {
|
|
188
179
|
case MESSAGE.CONFIGURATION:
|
|
189
180
|
switch (msg.verb) {
|
|
190
|
-
case VERB.NOTIFY:
|
|
181
|
+
case VERB.NOTIFY: {
|
|
182
|
+
const dup = JSON.parse(JSON.stringify(this._appConfig)); // fast-json-patch explicitly mutates
|
|
183
|
+
_.merge(dup, msg.data);
|
|
184
|
+
this._logger.push({ oldConf: this._appConfig, newConf: dup }).log('Emitting new configuration');
|
|
185
|
+
this.emit(EVENT.RECONFIGURE, dup);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
191
188
|
case VERB.PATCH: {
|
|
192
189
|
const dup = JSON.parse(JSON.stringify(this._appConfig)); // fast-json-patch explicitly mutates
|
|
193
190
|
jsonPatch.applyPatch(dup, msg.data);
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
// It expects new configuration to be supplied as an array of JSON patches. It therefore exposes
|
|
23
23
|
// the current configuration to
|
|
24
24
|
|
|
25
|
-
const assert = require('assert').strict;
|
|
26
25
|
|
|
27
26
|
const ws = require('ws');
|
|
28
27
|
const jsonPatch = require('fast-json-patch');
|
|
29
28
|
const { generateSlug } = require('random-word-slugs');
|
|
29
|
+
const _ = require('lodash');
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
/**************************************************************************
|
|
@@ -213,21 +213,14 @@ class Server extends ws.Server {
|
|
|
213
213
|
|
|
214
214
|
// Close the server then wait for all the client sockets to close
|
|
215
215
|
async stop() {
|
|
216
|
-
|
|
216
|
+
const closing = new Promise(resolve => this.close(resolve));
|
|
217
|
+
for (const client of this.clients) {
|
|
218
|
+
client.terminate();
|
|
219
|
+
}
|
|
220
|
+
await closing;
|
|
217
221
|
this._logger.log('Control server shutdown complete');
|
|
218
222
|
}
|
|
219
223
|
|
|
220
|
-
reconfigure({ logger = this._logger, port = 0, appConfig = this._appConfig }) {
|
|
221
|
-
assert(port === this._port, 'Cannot reconfigure running port');
|
|
222
|
-
return () => {
|
|
223
|
-
const reconfigureClientLogger =
|
|
224
|
-
({ logger: clientLogger }) => clientLogger.configure(logger);
|
|
225
|
-
this._clientData.values(reconfigureClientLogger);
|
|
226
|
-
this._logger = logger;
|
|
227
|
-
this._appConfig = appConfig;
|
|
228
|
-
this._logger.log('restarted');
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
224
|
|
|
232
225
|
async notifyClientsOfCurrentConfig() {
|
|
233
226
|
const updateConfMsg = build.CONFIGURATION.NOTIFY(this._appConfig);
|
|
@@ -261,6 +254,13 @@ class Server extends ws.Server {
|
|
|
261
254
|
case VERB.READ:
|
|
262
255
|
client.send(build.CONFIGURATION.NOTIFY(this._appConfig, msg.id));
|
|
263
256
|
break;
|
|
257
|
+
case VERB.NOTIFY: {
|
|
258
|
+
const dup = JSON.parse(JSON.stringify(this._appConfig)); // fast-json-patch explicitly mutates
|
|
259
|
+
_.merge(dup, msg.data);
|
|
260
|
+
this._logger.push({ oldConf: this._appConfig, newConf: dup }).log('Emitting new configuration');
|
|
261
|
+
this.emit(EVENT.RECONFIGURE, dup);
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
264
|
case VERB.PATCH: {
|
|
265
265
|
// TODO: validate the incoming patch? Or assume clients have used the
|
|
266
266
|
// client library?
|
|
@@ -18,33 +18,22 @@ const fs = require('fs');
|
|
|
18
18
|
const path = require('path');
|
|
19
19
|
const EventEmitter = require('events');
|
|
20
20
|
|
|
21
|
-
const { WSO2Auth } = require('@mojaloop/sdk-standard-components');
|
|
22
|
-
|
|
23
21
|
const Validate = require('../lib/validate');
|
|
24
22
|
const router = require('../lib/router');
|
|
25
23
|
const handlers = require('./handlers');
|
|
26
24
|
const middlewares = require('./middlewares');
|
|
27
|
-
const check = require('../lib/check');
|
|
28
25
|
|
|
29
26
|
class InboundApi extends EventEmitter {
|
|
30
|
-
constructor(conf, logger, cache, validator) {
|
|
27
|
+
constructor(conf, logger, cache, validator, wso2) {
|
|
31
28
|
super({ captureExceptions: true });
|
|
32
29
|
this._conf = conf;
|
|
33
30
|
this._cache = cache;
|
|
34
|
-
this._wso2 = {
|
|
35
|
-
auth: new WSO2Auth({
|
|
36
|
-
...conf.wso2.auth,
|
|
37
|
-
logger,
|
|
38
|
-
tlsCreds: conf.inbound.tls.mutualTLS.enabled && conf.inbound.tls.creds,
|
|
39
|
-
}),
|
|
40
|
-
retryWso2AuthFailureTimes: conf.wso2.requestAuthFailureRetryTimes,
|
|
41
|
-
};
|
|
42
|
-
this._wso2.auth.on('error', (msg) => {
|
|
43
|
-
this.emit('error', 'WSO2 auth error in InboundApi', msg);
|
|
44
|
-
});
|
|
45
31
|
|
|
46
32
|
if (conf.validateInboundJws) {
|
|
47
|
-
|
|
33
|
+
// peerJWSKey is a special config option specifically for Payment Manager for Mojaloop
|
|
34
|
+
// that is populated by a management api.
|
|
35
|
+
// This map supersedes local keys that would be loaded in by jwsVerificationKeysDirectory.
|
|
36
|
+
this._jwsVerificationKeys = conf.pm4mlEnabled ? conf.peerJWSKeys : InboundApi._GetJwsKeys(conf.jwsVerificationKeysDirectory);
|
|
48
37
|
}
|
|
49
38
|
this._api = InboundApi._SetupApi({
|
|
50
39
|
conf,
|
|
@@ -52,19 +41,15 @@ class InboundApi extends EventEmitter {
|
|
|
52
41
|
validator,
|
|
53
42
|
cache,
|
|
54
43
|
jwsVerificationKeys: this._jwsVerificationKeys,
|
|
55
|
-
wso2
|
|
44
|
+
wso2,
|
|
56
45
|
});
|
|
57
46
|
}
|
|
58
47
|
|
|
59
48
|
async start() {
|
|
60
49
|
this._startJwsWatcher();
|
|
61
|
-
if (!this._conf.testingDisableWSO2AuthStart) {
|
|
62
|
-
await this._wso2.auth.start();
|
|
63
|
-
}
|
|
64
50
|
}
|
|
65
51
|
|
|
66
52
|
stop() {
|
|
67
|
-
this._wso2.auth.stop();
|
|
68
53
|
if (this._keyWatcher) {
|
|
69
54
|
this._keyWatcher.close();
|
|
70
55
|
this._keyWatcher = null;
|
|
@@ -145,7 +130,7 @@ class InboundApi extends EventEmitter {
|
|
|
145
130
|
}
|
|
146
131
|
|
|
147
132
|
class InboundServer extends EventEmitter {
|
|
148
|
-
constructor(conf, logger, cache) {
|
|
133
|
+
constructor(conf, logger, cache, wso2) {
|
|
149
134
|
super({ captureExceptions: true });
|
|
150
135
|
this._conf = conf;
|
|
151
136
|
this._validator = new Validate();
|
|
@@ -154,7 +139,8 @@ class InboundServer extends EventEmitter {
|
|
|
154
139
|
conf,
|
|
155
140
|
this._logger.push({ component: 'api' }),
|
|
156
141
|
cache,
|
|
157
|
-
this._validator
|
|
142
|
+
this._validator,
|
|
143
|
+
wso2,
|
|
158
144
|
);
|
|
159
145
|
this._api.on('error', (...args) => {
|
|
160
146
|
this.emit('error', ...args);
|
|
@@ -173,52 +159,17 @@ class InboundServer extends EventEmitter {
|
|
|
173
159
|
await this._validator.initialise(apiSpecs);
|
|
174
160
|
await this._api.start();
|
|
175
161
|
await new Promise((resolve) => this._server.listen(this._conf.inbound.port, resolve));
|
|
176
|
-
this._logger.log(`Serving
|
|
162
|
+
this._logger.log(`Serving inbound API on port ${this._conf.inbound.port}`);
|
|
177
163
|
}
|
|
178
164
|
|
|
179
165
|
async stop() {
|
|
180
|
-
if (this._server) {
|
|
166
|
+
if (this._server.listening) {
|
|
181
167
|
await new Promise(resolve => this._server.close(resolve));
|
|
182
|
-
this._server = null;
|
|
183
|
-
}
|
|
184
|
-
if (this._api) {
|
|
185
|
-
await this._api.stop();
|
|
186
|
-
this._api = null;
|
|
187
168
|
}
|
|
169
|
+
await this._api.stop();
|
|
188
170
|
this._logger.log('inbound shut down complete');
|
|
189
171
|
}
|
|
190
172
|
|
|
191
|
-
async reconfigure(conf, logger, cache) {
|
|
192
|
-
// It may be possible to extract the socket from an existing HTTP/HTTPS server and replace
|
|
193
|
-
// it in a new server of the other type, as Node's HTTP and HTTPS servers both eventually
|
|
194
|
-
// are subclasses of net.Server. This wasn't considered as a requirement at the time of
|
|
195
|
-
// writing.
|
|
196
|
-
assert(
|
|
197
|
-
this._conf.inbound.tls.mutualTLS.enabled === conf.inbound.tls.mutualTLS.enabled,
|
|
198
|
-
'Cannot live-restart an HTTPS server as HTTP or vice versa',
|
|
199
|
-
);
|
|
200
|
-
const newApi = new InboundApi(conf, logger, cache, this._validator);
|
|
201
|
-
await newApi.start();
|
|
202
|
-
return () => {
|
|
203
|
-
this._logger = logger;
|
|
204
|
-
this._cache = cache;
|
|
205
|
-
// TODO: .tls might be undefined, causing an.. err.. undefined dereference..
|
|
206
|
-
const tlsCredsChanged = check.notDeepEqual(
|
|
207
|
-
conf.inbound.tls.creds,
|
|
208
|
-
this._conf.inbound.tls.creds
|
|
209
|
-
);
|
|
210
|
-
if (this._conf.inbound.tls.mutualTLS.enabled && tlsCredsChanged) {
|
|
211
|
-
this._server.setSecureContext(conf.inbound.tls.creds);
|
|
212
|
-
}
|
|
213
|
-
this._server.removeAllListeners('request');
|
|
214
|
-
this._server.on('request', newApi.callback());
|
|
215
|
-
this._api.stop();
|
|
216
|
-
this._api = newApi;
|
|
217
|
-
this._conf = conf;
|
|
218
|
-
this._logger.log('restarted');
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
173
|
_createServer(tlsEnabled, tlsCreds, handler) {
|
|
223
174
|
if (!tlsEnabled) {
|
|
224
175
|
return http.createServer(handler);
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
|
-
const { assert } = require('assert');
|
|
14
13
|
const express = require('express');
|
|
15
14
|
const bodyParser = require('body-parser');
|
|
16
15
|
const OAuth2Server = require('oauth2-server');
|
|
@@ -28,7 +27,6 @@ class OAuthTestServer {
|
|
|
28
27
|
* @param {Logger} conf.logger Logger
|
|
29
28
|
*/
|
|
30
29
|
constructor({ port, clientKey, clientSecret, logger }) {
|
|
31
|
-
this._api = null;
|
|
32
30
|
this._port = port;
|
|
33
31
|
this._logger = logger;
|
|
34
32
|
this._clientKey = clientKey;
|
|
@@ -65,17 +63,6 @@ class OAuthTestServer {
|
|
|
65
63
|
this._logger.log('OAuth2 Test Server shut down complete');
|
|
66
64
|
}
|
|
67
65
|
|
|
68
|
-
async reconfigure({ port, clientKey, clientSecret, logger }) {
|
|
69
|
-
assert(port === this._port, 'Cannot reconfigure running port');
|
|
70
|
-
return () => {
|
|
71
|
-
this._port = port;
|
|
72
|
-
this._logger = logger;
|
|
73
|
-
this.stop().then(() => this.start());
|
|
74
|
-
this._api = OAuthTestServer._SetupApi({ clientKey, clientSecret });
|
|
75
|
-
this._logger.log('restarted');
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
66
|
handleResponse(req, res, response) {
|
|
80
67
|
if (response.status === 302) {
|
|
81
68
|
const location = response.headers.location;
|
|
@@ -16,9 +16,6 @@ const yaml = require('js-yaml');
|
|
|
16
16
|
const fs = require('fs');
|
|
17
17
|
const path = require('path');
|
|
18
18
|
const EventEmitter = require('events');
|
|
19
|
-
const cors = require('@koa/cors');
|
|
20
|
-
|
|
21
|
-
const { WSO2Auth } = require('@mojaloop/sdk-standard-components');
|
|
22
19
|
|
|
23
20
|
const Validate = require('../lib/validate');
|
|
24
21
|
const router = require('../lib/router');
|
|
@@ -28,7 +25,7 @@ const middlewares = require('./middlewares');
|
|
|
28
25
|
const endpointRegex = /\/.*/g;
|
|
29
26
|
|
|
30
27
|
class OutboundApi extends EventEmitter {
|
|
31
|
-
constructor(conf, logger, cache, validator, metricsClient) {
|
|
28
|
+
constructor(conf, logger, cache, validator, metricsClient, wso2) {
|
|
32
29
|
super({ captureExceptions: true });
|
|
33
30
|
this._logger = logger;
|
|
34
31
|
this._api = new Koa();
|
|
@@ -36,26 +33,10 @@ class OutboundApi extends EventEmitter {
|
|
|
36
33
|
this._cache = cache;
|
|
37
34
|
this._metricsClient = metricsClient;
|
|
38
35
|
|
|
39
|
-
this._wso2 = {
|
|
40
|
-
auth: new WSO2Auth({
|
|
41
|
-
...this._conf.wso2.auth,
|
|
42
|
-
logger: this._logger,
|
|
43
|
-
tlsCreds: this._conf.outbound.tls.mutualTLS.enabled && this._conf.outbound.tls.creds,
|
|
44
|
-
}),
|
|
45
|
-
retryWso2AuthFailureTimes: conf.wso2.requestAuthFailureRetryTimes,
|
|
46
|
-
};
|
|
47
|
-
this._wso2.auth.on('error', (msg) => {
|
|
48
|
-
this.emit('error', 'WSO2 auth error in OutboundApi', msg);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// use CORS
|
|
52
|
-
// https://github.com/koajs/cors
|
|
53
|
-
this._api.use(cors());
|
|
54
|
-
|
|
55
36
|
this._api.use(middlewares.createErrorHandler(this._logger));
|
|
56
37
|
this._api.use(middlewares.createRequestIdGenerator());
|
|
57
38
|
this._api.use(koaBody()); // outbound always expects application/json
|
|
58
|
-
this._api.use(middlewares.applyState({ cache, wso2
|
|
39
|
+
this._api.use(middlewares.applyState({ cache, wso2, conf, metricsClient }));
|
|
59
40
|
this._api.use(middlewares.createLogger(this._logger));
|
|
60
41
|
|
|
61
42
|
//Note that we strip off any path on peerEndpoint config after the origin.
|
|
@@ -67,7 +48,7 @@ class OutboundApi extends EventEmitter {
|
|
|
67
48
|
peerEndpoint: conf.peerEndpoint.replace(endpointRegex, ''),
|
|
68
49
|
proxyConfig: conf.proxyConfig,
|
|
69
50
|
logger: this._logger,
|
|
70
|
-
wso2Auth:
|
|
51
|
+
wso2Auth: wso2.auth,
|
|
71
52
|
tls: conf.outbound.tls,
|
|
72
53
|
}));
|
|
73
54
|
}
|
|
@@ -76,15 +57,9 @@ class OutboundApi extends EventEmitter {
|
|
|
76
57
|
this._api.use(router(handlers));
|
|
77
58
|
}
|
|
78
59
|
|
|
79
|
-
|
|
80
|
-
if (!this._conf.testingDisableWSO2AuthStart) {
|
|
81
|
-
await this._wso2.auth.start();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
60
|
+
start() {}
|
|
84
61
|
|
|
85
|
-
|
|
86
|
-
this._wso2.auth.stop();
|
|
87
|
-
}
|
|
62
|
+
stop() {}
|
|
88
63
|
|
|
89
64
|
callback() {
|
|
90
65
|
return this._api.callback();
|
|
@@ -92,7 +67,7 @@ class OutboundApi extends EventEmitter {
|
|
|
92
67
|
}
|
|
93
68
|
|
|
94
69
|
class OutboundServer extends EventEmitter {
|
|
95
|
-
constructor(conf, logger, cache, metricsClient) {
|
|
70
|
+
constructor(conf, logger, cache, metricsClient, wso2) {
|
|
96
71
|
super({ captureExceptions: true });
|
|
97
72
|
this._validator = new Validate();
|
|
98
73
|
this._conf = conf;
|
|
@@ -103,7 +78,8 @@ class OutboundServer extends EventEmitter {
|
|
|
103
78
|
this._logger.push({ component: 'api' }),
|
|
104
79
|
cache,
|
|
105
80
|
this._validator,
|
|
106
|
-
metricsClient
|
|
81
|
+
metricsClient,
|
|
82
|
+
wso2,
|
|
107
83
|
);
|
|
108
84
|
this._api.on('error', (...args) => {
|
|
109
85
|
this.emit('error', ...args);
|
|
@@ -121,30 +97,11 @@ class OutboundServer extends EventEmitter {
|
|
|
121
97
|
}
|
|
122
98
|
|
|
123
99
|
async stop() {
|
|
124
|
-
if (this._server) {
|
|
100
|
+
if (this._server.listening) {
|
|
125
101
|
await new Promise(resolve => this._server.close(resolve));
|
|
126
|
-
this._server = null;
|
|
127
102
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
this._api = null;
|
|
131
|
-
}
|
|
132
|
-
this._logger.log('Shut down complete');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
async reconfigure(conf, logger, cache, metricsClient) {
|
|
136
|
-
const newApi = new OutboundApi(conf, logger, cache, this._validator, metricsClient);
|
|
137
|
-
await newApi.start();
|
|
138
|
-
return () => {
|
|
139
|
-
this._logger = logger;
|
|
140
|
-
this._cache = cache;
|
|
141
|
-
this._server.removeAllListeners('request');
|
|
142
|
-
this._server.on('request', newApi.callback());
|
|
143
|
-
this._api.stop();
|
|
144
|
-
this._api = newApi;
|
|
145
|
-
this._conf = conf;
|
|
146
|
-
this._logger.log('restarted');
|
|
147
|
-
};
|
|
103
|
+
await this._api.stop();
|
|
104
|
+
this._logger.log('outbound shut down complete');
|
|
148
105
|
}
|
|
149
106
|
}
|
|
150
107
|
|
package/src/TestServer/index.js
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
const Koa = require('koa');
|
|
12
12
|
const ws = require('ws');
|
|
13
13
|
|
|
14
|
-
const assert = require('assert').strict;
|
|
15
14
|
const http = require('http');
|
|
16
15
|
const yaml = require('js-yaml');
|
|
17
16
|
const fs = require('fs').promises;
|
|
@@ -84,7 +83,11 @@ class WsServer extends ws.Server {
|
|
|
84
83
|
|
|
85
84
|
// Close the server then wait for all the client sockets to close
|
|
86
85
|
async stop() {
|
|
87
|
-
|
|
86
|
+
const closing = new Promise(resolve => this.close(resolve));
|
|
87
|
+
for (const client of this.clients) {
|
|
88
|
+
client.terminate();
|
|
89
|
+
}
|
|
90
|
+
await closing;
|
|
88
91
|
// If we don't wait for all clients to close before shutting down, the socket close
|
|
89
92
|
// handlers will be called after we return from this function, resulting in behaviour
|
|
90
93
|
// occurring after the server tells the user it has shutdown.
|
|
@@ -201,7 +204,7 @@ class TestServer {
|
|
|
201
204
|
async stop() {
|
|
202
205
|
if (this._wsapi) {
|
|
203
206
|
this._logger.log('Shutting down websocket server');
|
|
204
|
-
this._wsapi.stop();
|
|
207
|
+
await this._wsapi.stop();
|
|
205
208
|
this._wsapi = null;
|
|
206
209
|
}
|
|
207
210
|
if (this._server) {
|
|
@@ -211,36 +214,6 @@ class TestServer {
|
|
|
211
214
|
}
|
|
212
215
|
this._logger.log('Test server shutdown complete');
|
|
213
216
|
}
|
|
214
|
-
|
|
215
|
-
async reconfigure({ port, logger, cache }) {
|
|
216
|
-
assert(port === this._port, 'Cannot reconfigure running port');
|
|
217
|
-
const newApi = new TestApi(logger, cache, this._validator);
|
|
218
|
-
const newWsApi = new WsServer(logger.push({ component: 'websocket-server' }), cache);
|
|
219
|
-
await newWsApi.start();
|
|
220
|
-
|
|
221
|
-
return () => {
|
|
222
|
-
const oldWsApi = this._wsapi;
|
|
223
|
-
this._logger = logger;
|
|
224
|
-
this._cache = cache;
|
|
225
|
-
this._wsapi = newWsApi;
|
|
226
|
-
this._api = newApi;
|
|
227
|
-
this._server.removeAllListeners('upgrade');
|
|
228
|
-
this._server.on('upgrade', (req, socket, head) => {
|
|
229
|
-
this._wsapi.handleUpgrade(req, socket, head, (ws) =>
|
|
230
|
-
this._wsapi.emit('connection', ws, req));
|
|
231
|
-
});
|
|
232
|
-
this._server.removeAllListeners('request');
|
|
233
|
-
this._server.on('request', newApi.callback());
|
|
234
|
-
// TODO: we can't guarantee client implementations. Therefore we can't guarantee
|
|
235
|
-
// reconnect logic/behaviour. Therefore instead of closing all websocket client
|
|
236
|
-
// connections as we do below, we should replace handlers.
|
|
237
|
-
oldWsApi.stop().catch((err) => {
|
|
238
|
-
this._logger.push({ err }).log('Error stopping websocket server during reconfigure');
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
this._logger.log('restarted');
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
217
|
}
|
|
245
218
|
|
|
246
219
|
module.exports = TestServer;
|
package/src/config.js
CHANGED
|
@@ -129,10 +129,7 @@ module.exports = {
|
|
|
129
129
|
jwsSignPutParties: env.get('JWS_SIGN_PUT_PARTIES').default('false').asBool(),
|
|
130
130
|
jwsSigningKey: env.get('JWS_SIGNING_KEY_PATH').asFileContent(),
|
|
131
131
|
jwsVerificationKeysDirectory: env.get('JWS_VERIFICATION_KEYS_DIRECTORY').asString(),
|
|
132
|
-
|
|
133
|
-
host: env.get('CACHE_HOST').required().asString(),
|
|
134
|
-
port: env.get('CACHE_PORT').required().asPortNumber(),
|
|
135
|
-
},
|
|
132
|
+
cacheUrl: env.get('CACHE_URL').default('redis://redis:6379').asUrlString(),
|
|
136
133
|
enableTestFeatures: env.get('ENABLE_TEST_FEATURES').default('false').asBool(),
|
|
137
134
|
oauthTestServer: {
|
|
138
135
|
enabled: env.get('ENABLE_OAUTH_TOKEN_ENDPOINT').default('false').asBool(),
|