Skip to content

Commit

Permalink
Merge pull request #325 from mojaloop/MBP-604
Browse files Browse the repository at this point in the history
feat!: pull changes from mojaloop-connector
  • Loading branch information
kirgene authored Jul 1, 2022
2 parents 5d8f243 + b6bdae0 commit a7827a6
Show file tree
Hide file tree
Showing 43 changed files with 5,341 additions and 7,245 deletions.
585 changes: 43 additions & 542 deletions audit-resolve.json

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions docs/dfspInboundApi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,17 @@ components:
homeTransactionId:
type: string
description: Transaction ID from the DFSP backend, used to reconcile transactions between the Switch and DFSP backend systems.
fulfilment:
$ref: '#/components/schemas/IlpFulfilment'
description: Fulfilment from the DFSP backend, used for testing purposes to inject an invalid fulfilment via a rule.
transferState:
$ref: '#/components/schemas/transferState'
description: Transfer state from the DFSP backend, used for testing purposes to inject an desired transfer state via a rule.
example: ABORTED
completedTimestamp:
$ref: '#/components/schemas/timestamp'
description: Completed timestamp from the DFSP backend, used for testing purposes to inject a given completed timestamp via a rule.
example: "2020-05-19T08:38:08.699-04:00"

transferDetailsResponse:
type: object
Expand Down
10,593 changes: 4,741 additions & 5,852 deletions package-lock.json

Large diffs are not rendered by default.

47 changes: 24 additions & 23 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"Shashikant Hirugade <[email protected]>",
"Paweł Marzec <[email protected]>",
"Kevin Leyow <[email protected]",
"Miguel de Barros <[email protected]>"
"Miguel de Barros <[email protected]>",
"Yevhen Kyriukha <[email protected]>"
],
"license": "Apache-2.0",
"licenses": [
Expand All @@ -55,48 +56,48 @@
"dependencies": {
"@koa/cors": "^3.1.0",
"@mojaloop/central-services-shared": "17.0.2",
"@mojaloop/sdk-standard-components": "^17.0.1",
"@mojaloop/sdk-standard-components": "^17.0.4",
"ajv": "8.11.0",
"axios": "^0.21.4",
"axios": "^0.27.2",
"co-body": "^6.1.0",
"dotenv": "^10.0.0",
"dotenv": "^16.0.1",
"env-var": "^7.0.1",
"express": "^4.17.2",
"fast-json-patch": "^3.1.1",
"javascript-state-machine": "^3.1.0",
"js-yaml": "^4.1.0",
"json-schema-ref-parser": "^9.0.9",
"koa": "^2.13.1",
"koa-body": "^4.2.0",
"koa-body": "^5.0.0",
"lodash": "^4.17.21",
"module-alias": "^2.2.2",
"oauth2-server": "^4.0.0-dev.2",
"openapi-jsonschema-parameters": "^9.3.0",
"prom-client": "^12.0.0",
"openapi-jsonschema-parameters": "^12.0.0",
"prom-client": "^14.0.1",
"promise-timeout": "^1.3.0",
"random-word-slugs": "^0.1.6",
"redis": "^3.1.2",
"redis": "^4.1.1",
"uuidv4": "^6.2.12",
"ws": "^7.5.5"
"ws": "^8.8.0"
},
"devDependencies": {
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.6",
"@mojaloop/api-snippets": "^13.0.9",
"@babel/core": "^7.18.6",
"@babel/preset-env": "^7.18.6",
"@mojaloop/api-snippets": "^14.0.0",
"@redocly/openapi-cli": "^1.0.0-beta.59",
"@types/jest": "^27.0.1",
"babel-jest": "^27.2.0",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1",
"@types/jest": "^28.1.4",
"babel-jest": "^28.1.2",
"eslint": "^8.18.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-jest": "^24.4.0",
"jest": "^27.2.0",
"jest-junit": "^12.2.0",
"nock": "^13.1.3",
"eslint-plugin-jest": "^26.5.3",
"jest": "^28.1.2",
"jest-junit": "^14.0.0",
"nock": "^13.2.8",
"npm-audit-resolver": "^3.0.0-0",
"npm-check-updates": "^11.8.5",
"openapi-response-validator": "^9.3.0",
"openapi-typescript": "^4.0.2",
"npm-check-updates": "^15.0.1",
"openapi-response-validator": "^12.0.0",
"openapi-typescript": "^5.4.0",
"redis-mock": "^0.56.3",
"standard-version": "^9.3.1",
"supertest": "^6.1.6",
Expand Down
19 changes: 8 additions & 11 deletions src/ControlAgent/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
// It expects new configuration to be supplied as an array of JSON patches. It therefore exposes
// the current configuration to

const assert = require('assert').strict;
const ws = require('ws');
const jsonPatch = require('fast-json-patch');
const { generateSlug } = require('random-word-slugs');
const _ = require('lodash');

/**************************************************************************
* The message protocol messages, verbs, and errors
Expand Down Expand Up @@ -163,15 +163,6 @@ class Client extends ws {
this.close();
}

reconfigure({ logger = this._logger, port = 0, appConfig = this._appConfig }) {
assert(port === this._socket.remotePort, 'Cannot reconfigure running port');
return () => {
this._logger = logger;
this._appConfig = appConfig;
this._logger.log('restarted');
};
}

// Handle incoming message from the server.
_handle(data) {
// TODO: json-schema validation of received message- should be pretty straight-forward
Expand All @@ -187,7 +178,13 @@ class Client extends ws {
switch (msg.msg) {
case MESSAGE.CONFIGURATION:
switch (msg.verb) {
case VERB.NOTIFY:
case VERB.NOTIFY: {
const dup = JSON.parse(JSON.stringify(this._appConfig)); // fast-json-patch explicitly mutates
_.merge(dup, msg.data);
this._logger.push({ oldConf: this._appConfig, newConf: dup }).log('Emitting new configuration');
this.emit(EVENT.RECONFIGURE, dup);
break;
}
case VERB.PATCH: {
const dup = JSON.parse(JSON.stringify(this._appConfig)); // fast-json-patch explicitly mutates
jsonPatch.applyPatch(dup, msg.data);
Expand Down
26 changes: 13 additions & 13 deletions src/ControlServer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
// It expects new configuration to be supplied as an array of JSON patches. It therefore exposes
// the current configuration to

const assert = require('assert').strict;

const ws = require('ws');
const jsonPatch = require('fast-json-patch');
const { generateSlug } = require('random-word-slugs');
const _ = require('lodash');


/**************************************************************************
Expand Down Expand Up @@ -213,21 +213,14 @@ class Server extends ws.Server {

// Close the server then wait for all the client sockets to close
async stop() {
await new Promise(this.close.bind(this));
const closing = new Promise(resolve => this.close(resolve));
for (const client of this.clients) {
client.terminate();
}
await closing;
this._logger.log('Control server shutdown complete');
}

reconfigure({ logger = this._logger, port = 0, appConfig = this._appConfig }) {
assert(port === this._port, 'Cannot reconfigure running port');
return () => {
const reconfigureClientLogger =
({ logger: clientLogger }) => clientLogger.configure(logger);
this._clientData.values(reconfigureClientLogger);
this._logger = logger;
this._appConfig = appConfig;
this._logger.log('restarted');
};
}

async notifyClientsOfCurrentConfig() {
const updateConfMsg = build.CONFIGURATION.NOTIFY(this._appConfig);
Expand Down Expand Up @@ -261,6 +254,13 @@ class Server extends ws.Server {
case VERB.READ:
client.send(build.CONFIGURATION.NOTIFY(this._appConfig, msg.id));
break;
case VERB.NOTIFY: {
const dup = JSON.parse(JSON.stringify(this._appConfig)); // fast-json-patch explicitly mutates
_.merge(dup, msg.data);
this._logger.push({ oldConf: this._appConfig, newConf: dup }).log('Emitting new configuration');
this.emit(EVENT.RECONFIGURE, dup);
break;
}
case VERB.PATCH: {
// TODO: validate the incoming patch? Or assume clients have used the
// client library?
Expand Down
73 changes: 12 additions & 61 deletions src/InboundServer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,53 +18,38 @@ const fs = require('fs');
const path = require('path');
const EventEmitter = require('events');

const { WSO2Auth } = require('@mojaloop/sdk-standard-components');

const Validate = require('../lib/validate');
const router = require('../lib/router');
const handlers = require('./handlers');
const middlewares = require('./middlewares');
const check = require('../lib/check');

class InboundApi extends EventEmitter {
constructor(conf, logger, cache, validator) {
constructor(conf, logger, cache, validator, wso2) {
super({ captureExceptions: true });
this._conf = conf;
this._cache = cache;
this._wso2 = {
auth: new WSO2Auth({
...conf.wso2.auth,
logger,
tlsCreds: conf.inbound.tls.mutualTLS.enabled && conf.inbound.tls.creds,
}),
retryWso2AuthFailureTimes: conf.wso2.requestAuthFailureRetryTimes,
};
this._wso2.auth.on('error', (msg) => {
this.emit('error', 'WSO2 auth error in InboundApi', msg);
});

if (conf.validateInboundJws) {
this._jwsVerificationKeys = conf.pm4mlEnabled ? conf.peerJWSKeys : InboundApi._GetJwsKeys(conf.jwsVerificationKeysDirectory);
// peerJWSKey is a special config option specifically for Payment Manager for Mojaloop
// that is populated by a management api.
// This map supersedes local keys that would be loaded in by jwsVerificationKeysDirectory.
this._jwsVerificationKeys = conf.pm4mlEnabled ? conf.peerJWSKeys : InboundApi._GetJwsKeys(conf.jwsVerificationKeysDirectory);
}
this._api = InboundApi._SetupApi({
conf,
logger,
validator,
cache,
jwsVerificationKeys: this._jwsVerificationKeys,
wso2: this._wso2,
wso2,
});
}

async start() {
this._startJwsWatcher();
if (!this._conf.testingDisableWSO2AuthStart) {
await this._wso2.auth.start();
}
}

stop() {
this._wso2.auth.stop();
if (this._keyWatcher) {
this._keyWatcher.close();
this._keyWatcher = null;
Expand Down Expand Up @@ -145,7 +130,7 @@ class InboundApi extends EventEmitter {
}

class InboundServer extends EventEmitter {
constructor(conf, logger, cache) {
constructor(conf, logger, cache, wso2) {
super({ captureExceptions: true });
this._conf = conf;
this._validator = new Validate();
Expand All @@ -154,7 +139,8 @@ class InboundServer extends EventEmitter {
conf,
this._logger.push({ component: 'api' }),
cache,
this._validator
this._validator,
wso2,
);
this._api.on('error', (...args) => {
this.emit('error', ...args);
Expand All @@ -173,52 +159,17 @@ class InboundServer extends EventEmitter {
await this._validator.initialise(apiSpecs);
await this._api.start();
await new Promise((resolve) => this._server.listen(this._conf.inbound.port, resolve));
this._logger.log(`Serving outbound API on port ${this._conf.inbound.port}`);
this._logger.log(`Serving inbound API on port ${this._conf.inbound.port}`);
}

async stop() {
if (this._server) {
if (this._server.listening) {
await new Promise(resolve => this._server.close(resolve));
this._server = null;
}
if (this._api) {
await this._api.stop();
this._api = null;
}
await this._api.stop();
this._logger.log('inbound shut down complete');
}

async reconfigure(conf, logger, cache) {
// It may be possible to extract the socket from an existing HTTP/HTTPS server and replace
// it in a new server of the other type, as Node's HTTP and HTTPS servers both eventually
// are subclasses of net.Server. This wasn't considered as a requirement at the time of
// writing.
assert(
this._conf.inbound.tls.mutualTLS.enabled === conf.inbound.tls.mutualTLS.enabled,
'Cannot live-restart an HTTPS server as HTTP or vice versa',
);
const newApi = new InboundApi(conf, logger, cache, this._validator);
await newApi.start();
return () => {
this._logger = logger;
this._cache = cache;
// TODO: .tls might be undefined, causing an.. err.. undefined dereference..
const tlsCredsChanged = check.notDeepEqual(
conf.inbound.tls.creds,
this._conf.inbound.tls.creds
);
if (this._conf.inbound.tls.mutualTLS.enabled && tlsCredsChanged) {
this._server.setSecureContext(conf.inbound.tls.creds);
}
this._server.removeAllListeners('request');
this._server.on('request', newApi.callback());
this._api.stop();
this._api = newApi;
this._conf = conf;
this._logger.log('restarted');
};
}

_createServer(tlsEnabled, tlsCreds, handler) {
if (!tlsEnabled) {
return http.createServer(handler);
Expand Down
13 changes: 0 additions & 13 deletions src/OAuthTestServer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

'use strict';

const { assert } = require('assert');
const express = require('express');
const bodyParser = require('body-parser');
const OAuth2Server = require('oauth2-server');
Expand All @@ -28,7 +27,6 @@ class OAuthTestServer {
* @param {Logger} conf.logger Logger
*/
constructor({ port, clientKey, clientSecret, logger }) {
this._api = null;
this._port = port;
this._logger = logger;
this._clientKey = clientKey;
Expand Down Expand Up @@ -65,17 +63,6 @@ class OAuthTestServer {
this._logger.log('OAuth2 Test Server shut down complete');
}

async reconfigure({ port, clientKey, clientSecret, logger }) {
assert(port === this._port, 'Cannot reconfigure running port');
return () => {
this._port = port;
this._logger = logger;
this.stop().then(() => this.start());
this._api = OAuthTestServer._SetupApi({ clientKey, clientSecret });
this._logger.log('restarted');
};
}

handleResponse(req, res, response) {
if (response.status === 302) {
const location = response.headers.location;
Expand Down
Loading

0 comments on commit a7827a6

Please sign in to comment.