diff --git a/packages/cactus-cmd-socketio-server/package.json b/packages/cactus-cmd-socketio-server/package.json index e45fc12686..f0b32fc3e6 100644 --- a/packages/cactus-cmd-socketio-server/package.json +++ b/packages/cactus-cmd-socketio-server/package.json @@ -8,6 +8,12 @@ "copy-static-assets": "ts-node copyStaticAssets.ts", "test": "jest" }, + "workspaces": { + "nohoist": [ + "@types/socket.io", + "@types/socket.io-client" + ] + }, "dependencies": { "@types/node": "^14.0.24", "body-parser": "^1.19.0", @@ -33,6 +39,8 @@ "@types/jest": "^26.0.19", "@typescript-eslint/eslint-plugin": "^4.31.1", "@typescript-eslint/parser": "^4.31.1", + "@types/socket.io": "^2.0.4", + "@types/socket.io-client": "^1.4.36", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts index 3d16f70f9e..764d2dbb2f 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts @@ -33,17 +33,15 @@ export class ConfigUtil { * @return {object} Merged objects */ private static mergeObjects(target: object, source: object): object { - const isObject = (obj) => + const isObject = (obj: unknown) => obj && typeof obj === "object" && !Array.isArray(obj); const mergeObject = Object.assign({}, target); if (isObject(target) && isObject(source)) { for (const [sourceKey, sourceValue] of Object.entries(source)) { - const targetValue = target[sourceKey]; + const targetValue = (target as { [key: string]: any })[sourceKey]; if (isObject(sourceValue) && target.hasOwnProperty(sourceKey)) { - mergeObject[sourceKey] = ConfigUtil.mergeObjects( - targetValue, - sourceValue - ); + (mergeObject as { [key: string]: any })[sourceKey] = + ConfigUtil.mergeObjects(targetValue, sourceValue); } else { Object.assign(mergeObject, { [sourceKey]: sourceValue }); } diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts index 4b7c104c3a..27fe55f363 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts @@ -45,7 +45,7 @@ export function makeApiInfoList(targetApiInfo: any): ApiInfo[] { } // store on socket -const socketArray = []; +const socketArray: any[] = []; // Returns the index of socketArray as a return value export function addSocket(socket: any): number { diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts index 999286cd56..4d23d90cbf 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts @@ -19,12 +19,12 @@ import { deleteAndDisconnectSocke, } from "./DriverCommon"; import { LedgerOperation } from "../business-logic-plugin/LedgerOperation"; -import { Socket } from "dgram"; import { ConfigUtil } from "../routing-interface/util/ConfigUtil"; import { VerifierAuthentication } from "./VerifierAuthentication"; const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; -const io = require("socket.io-client"); +import io from "socket.io-client"; +import { Socket } from "socket.io-client"; const fs = require("fs"); const path = require("path"); @@ -44,24 +44,34 @@ type VALIDATOR_TYPE = typeof VALIDATOR_TYPE[keyof typeof VALIDATOR_TYPE]; // 'so // abolish template-trade // const validatorRregistryConf: any = yaml.safeLoad(fs.readFileSync("/etc/cactus/validator-registry.yaml", 'utf8')); +type TLedgerInfo = { + validatorID: string; + validatorType: string; + validatorURL: string; + validatorKeyPath: string; + apiInfo: object; +}; + export class Verifier implements IVerifier { validatorID = ""; validatorType = ""; validatorUrl = ""; validatorKeyPath = ""; - apiInfo: {} = null; + apiInfo: object = {}; counterReqID = 1; eventListenerHash: { [key: string]: VerifierEventListener } = {}; // Listeners for events from Ledger - static mapUrlSocket: Map = new Map(); + static mapUrlSocket: Map = new Map(); + checkValidator: (key: string, data: string) => Promise = + VerifierAuthentication.verify; constructor(ledgerInfo: string) { // TODO: Configure the Verifier based on the connection information - const ledgerInfoObj: {} = JSON.parse(ledgerInfo); - this.validatorID = ledgerInfoObj["validatorID"]; - this.validatorType = ledgerInfoObj["validatorType"]; - this.validatorUrl = ledgerInfoObj["validatorURL"]; - this.validatorKeyPath = ledgerInfoObj["validatorKeyPath"]; - this.apiInfo = ledgerInfoObj["apiInfo"]; + const ledgerInfoObj = JSON.parse(ledgerInfo) as TLedgerInfo; + this.validatorID = ledgerInfoObj.validatorID; + this.validatorType = ledgerInfoObj.validatorType; + this.validatorUrl = ledgerInfoObj.validatorURL; + this.validatorKeyPath = ledgerInfoObj.validatorKeyPath; + this.apiInfo = ledgerInfoObj.apiInfo; if (VALIDATOR_TYPE.SOCKET === this.validatorType) { // create socket instance assosiated with validatorUrl if it has not created yet @@ -74,7 +84,7 @@ export class Verifier implements IVerifier { logger.debug(`socketOptions = ${JSON.stringify(socketOptions)}`); Verifier.mapUrlSocket.set( this.validatorID, - io(this.validatorUrl, socketOptions) + io(this.validatorUrl, socketOptions), ); } } @@ -83,14 +93,14 @@ export class Verifier implements IVerifier { // NOTE: asynchronous command public sendAsyncRequest( contract: object, - method: object, - args: object + method: { command: string }, + args: any, ): Promise { return new Promise((resolve, reject) => { logger.debug( `call: sendAsyncRequest, contract = ${JSON.stringify( - contract - )}, method = ${JSON.stringify(method)}, args = ${args}` + contract, + )}, method = ${JSON.stringify(method)}, args = ${args}`, ); try { // verifier comunicate with socket @@ -99,7 +109,11 @@ export class Verifier implements IVerifier { resolve(); // verifier comunicate with http } else if (VALIDATOR_TYPE.OPENAPI === this.validatorType) { - this.requestLedgerOperationHttp(contract, method, args) + this.requestLedgerOperationHttp( + contract, + method, + args as { args: any }, + ) .then(() => { resolve(); }) @@ -130,11 +144,14 @@ export class Verifier implements IVerifier { private requestLedgerOperationNeo( contract: object, method: object, - args: object + args: object, ): void { logger.debug("call : requestLedgerOperation"); try { const socket = Verifier.mapUrlSocket.get(this.validatorID); + if (socket === undefined) { + throw Error(`No socket for validator with ID ${this.validatorID}`); + } const requestData: {} = { contract: contract, @@ -153,17 +170,18 @@ export class Verifier implements IVerifier { public sendSyncRequest( contract: object, method: object, - args: object + args: object, ): Promise { return new Promise((resolve, reject) => { logger.debug("call : sendSyncRequest"); try { logger.debug( - `##in sendSyncRequest, contract = ${JSON.stringify( - contract - )}, method = ${JSON.stringify(method)}, args = ${JSON.stringify( - args - )}, ` + "##in sendSyncRequest, contract:", + contract, + "method:", + method, + "args:", + args, ); let responseFlag = false; @@ -173,6 +191,10 @@ export class Verifier implements IVerifier { // Preparing socket const socket = Verifier.mapUrlSocket.get(this.validatorID); + if (socket === undefined) { + throw Error(`No socket for validator with ID ${this.validatorID}`); + } + socket.on("connect_error", (err: object) => { logger.error("##connect_error:", err); // end communication @@ -191,24 +213,22 @@ export class Verifier implements IVerifier { reject(err); }); socket.on("response", (result: any) => { - logger.debug(`#[recv]response, res: ${result}`); + logger.debug("#[recv]response, res:", result); if (reqID === result.id) { responseFlag = true; - VerifierAuthentication.verify( - this.validatorKeyPath, - result.resObj.data - ) + this.checkValidator(this.validatorKeyPath, result.resObj.data) .then((decodedData) => { const resultObj = { status: result.resObj.status, data: decodedData.result, }; - logger.debug(`resultObj = ${resultObj}`); + logger.debug("resultObj =", resultObj); // Result reply resolve(resultObj); }) .catch((err) => { + responseFlag = false; logger.error(err); }); } @@ -221,19 +241,19 @@ export class Verifier implements IVerifier { args: args, reqID: reqID, }; - logger.debug(`requestData : ${requestData}`); + logger.debug("requestData:", requestData); socket.emit("request2", requestData); logger.debug("set timeout"); // Time-out setting setTimeout(() => { if (responseFlag === false) { - logger.debug("requestTimeout reqID : " + reqID); + logger.debug("requestTimeout reqID:", reqID); resolve({ status: 504, amount: 0 }); } }, config.verifier.syncFunctionTimeoutMillisecond); } catch (err) { - logger.error(`##Error: sendSyncRequest, ${err}`); + logger.error("##Error: sendSyncRequest:", err); reject(err); } }); @@ -241,17 +261,17 @@ export class Verifier implements IVerifier { private requestLedgerOperationHttp( contract: object, - method: object, - args: object + method: { command: string }, + args: { args: any }, ): Promise { return new Promise((resolve, reject) => { try { logger.debug( `##in requestLedgerOperationHttp, contract = ${JSON.stringify( - contract + contract, )}, method = ${JSON.stringify(method)}, args = ${JSON.stringify( - args - )}` + args, + )}`, ); const eventListenerHash = this.eventListenerHash; const validatorID = this.validatorID; @@ -273,15 +293,15 @@ export class Verifier implements IVerifier { for (const key in eventListenerHash) { logger.debug( `key : ${key}, eventListenerHash[key] : ${JSON.stringify( - eventListenerHash[key] - )}` + eventListenerHash[key], + )}`, ); eventListener = eventListenerHash[key]; eventListener.onEvent(event); } } else { logger.debug( - `##requestLedgerOperationHttp eventListener does not exist` + `##requestLedgerOperationHttp eventListener does not exist`, ); } logger.debug(`##after onEvent()`); @@ -289,7 +309,7 @@ export class Verifier implements IVerifier { // resolve(responseObj); } catch (err) { logger.error( - `##Error: requestLedgerOperationHttp#httpReq.onload, ${err}` + `##Error: requestLedgerOperationHttp#httpReq.onload, ${err}`, ); } }; @@ -298,12 +318,12 @@ export class Verifier implements IVerifier { }; logger.debug(`validatorUrl: ${this.validatorUrl}`); - httpReq.open("POST", this.validatorUrl + method["command"]); + httpReq.open("POST", this.validatorUrl + method.command); // httpReq.setRequestHeader('content-type', 'application/json'); httpReq.setRequestHeader("Content-Type", "application/json"); // httpReq.send(args['args']); - logger.debug(`args['args']: ${JSON.stringify(args["args"])}`); - httpReq.send(JSON.stringify(args["args"])); + logger.debug(`args['args']: ${JSON.stringify(args.args)}`); + httpReq.send(JSON.stringify(args.args)); resolve(); } catch (err) { @@ -328,7 +348,7 @@ export class Verifier implements IVerifier { public startMonitor( id: string, options: Object, - eventListener: VerifierEventListener + eventListener: VerifierEventListener, ): Promise { return new Promise((resolve, reject) => { logger.debug("call : startMonitor"); @@ -337,10 +357,13 @@ export class Verifier implements IVerifier { if (Object.keys(this.eventListenerHash).length > 0) { logger.debug( - `##in startMonitor, validatorUrl = ${this.validatorUrl}` + `##in startMonitor, validatorUrl = ${this.validatorUrl}`, ); const socket = Verifier.mapUrlSocket.get(this.validatorID); + if (socket === undefined) { + throw Error(`No socket for validator with ID ${this.validatorID}`); + } socket.on("connect_error", (err: object) => { logger.error("##connect_error:", err); @@ -368,19 +391,16 @@ export class Verifier implements IVerifier { logger.debug( `##eventReceived Object.keys(this.eventListenerHash).length : ${ Object.keys(this.eventListenerHash).length - }` + }`, ); if (Object.keys(this.eventListenerHash).length > 0) { - VerifierAuthentication.verify( - this.validatorKeyPath, - res.blockData - ) + this.checkValidator(this.validatorKeyPath, res.blockData) .then((decodedData) => { const resultObj = { status: res.status, blockData: decodedData.blockData, }; - logger.debug(`resultObj = ${resultObj}`); + logger.debug("resultObj =", resultObj); const event = new LedgerEvent(); event.verifierId = this.validatorID; logger.debug(`##event.verifierId: ${event.verifierId}`); @@ -389,7 +409,7 @@ export class Verifier implements IVerifier { const eventListener = this.eventListenerHash[key]; if (eventListener != null) { logger.debug( - `##set eventListener: ${eventListener}, ${this.constructor.name}, ${this.validatorID}` + `##set eventListener: ${eventListener}, ${this.constructor.name}, ${this.validatorID}`, ); eventListener.onEvent(event); } else { @@ -438,7 +458,10 @@ export class Verifier implements IVerifier { } if (Object.keys(this.eventListenerHash).length === 0) { const socket = Verifier.mapUrlSocket.get(this.validatorID); - logger.debug("##emit: startMonitor"); + if (socket === undefined) { + throw Error(`No socket for validator with ID ${this.validatorID}`); + } + logger.debug("##emit: stopMonitor"); socket.emit("stopMonitor"); } } catch (err) { @@ -448,10 +471,12 @@ export class Verifier implements IVerifier { private setEventListener( appId: string, - eventListener: VerifierEventListener | null + eventListener: VerifierEventListener | null, ): void { logger.debug(`##call : setEventListener`); - this.eventListenerHash[appId] = eventListener; + if (eventListener) { + this.eventListenerHash[appId] = eventListener; + } return; } diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierAuthentication.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierAuthentication.ts index 6e1a30b4c6..dbbfe58813 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierAuthentication.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierAuthentication.ts @@ -24,18 +24,23 @@ export class VerifierAuthentication { algorithms: "ES256", }; - jwt.verify(targetData, publicKey, option, function (err, decoded) { - if (err) { - // Authentication NG - logger.debug(`Authentication NG : error = ${err}`); - reject(err); - } else { - // Authentication OK - // logger.debug(`Authentication OK : decoded = ${JSON.stringify(decoded)}`); - logger.debug(`Authentication OK`); - resolve(decoded); - } - }); + jwt.verify( + targetData, + publicKey, + option, + function (err: any, decoded: any) { + if (err) { + // Authentication NG + logger.debug(`Authentication NG : error = ${err}`); + reject(err); + } else { + // Authentication OK + // logger.debug(`Authentication OK : decoded = ${JSON.stringify(decoded)}`); + logger.debug(`Authentication OK`); + resolve(decoded); + } + }, + ); }); } }