From a6a04cbb84c07a0618ceb7b6992a371a63fdcd7f Mon Sep 17 00:00:00 2001 From: Steven Oderayi Date: Fri, 10 Jul 2020 15:59:36 +0100 Subject: [PATCH 1/8] Add bulk get topic and handler --- audit-resolve.json | 42 +++- config/default.json | 23 +++ docker/central-ledger/default.json | 23 +++ package-lock.json | 322 +++++++++++++++++++++++------ package.json | 16 +- src/handlers/bulk/get/handler.js | 173 ++++++++++++++++ src/handlers/bulk/index.js | 3 + 7 files changed, 535 insertions(+), 67 deletions(-) create mode 100644 src/handlers/bulk/get/handler.js diff --git a/audit-resolve.json b/audit-resolve.json index 8b1378917..7e9f5ef07 100644 --- a/audit-resolve.json +++ b/audit-resolve.json @@ -1 +1,41 @@ - +{ + "decisions": { + "1523|@mojaloop/central-services-database>knex>lodash": { + "decision": "ignore", + "madeAt": 1594379549137, + "expiresAt": 1594984342743 + }, + "1523|@mojaloop/central-services-database>lodash": { + "decision": "ignore", + "madeAt": 1594379523201, + "expiresAt": 1594984279931 + }, + "1523|@mojaloop/central-services-health>@mojaloop/central-services-error-handling>lodash": { + "decision": "ignore", + "madeAt": 1594379523202, + "expiresAt": 1594984279931 + }, + "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>lodash": { + "decision": "ignore", + "madeAt": 1594379523202, + "expiresAt": 1594984279931 + }, + "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>lodash": { + "decision": "ignore", + "madeAt": 1594379523202, + "expiresAt": 1594984279931 + }, + "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>lodash": { + "decision": "ignore", + "madeAt": 1594379523202, + "expiresAt": 1594984279931 + }, + "1523|@mojaloop/central-services-stream>@mojaloop/central-services-error-handling>lodash": { + "decision": "ignore", + "madeAt": 1594379523202, + "expiresAt": 1594984279931 + } + }, + "rules": {}, + "version": 1 +} \ No newline at end of file diff --git a/config/default.json b/config/default.json index 7f502d3ad..52822273e 100644 --- a/config/default.json +++ b/config/default.json @@ -170,6 +170,29 @@ "auto.offset.reset": "earliest" } } + }, + "GET": { + "config": { + "options": { + "mode": 2, + "batchSize": 1, + "pollFrequency": 10, + "recursiveTimeout": 100, + "messageCharset": "utf8", + "messageAsJSON": true, + "sync": true, + "consumeTimeout": 1000 + }, + "rdkafkaConf": { + "client.id": "cl-con-bulk-get", + "group.id": "cl-group-bulk-get", + "metadata.broker.list": "localhost:9092", + "socket.keepalive.enable": true + }, + "topicConf": { + "auto.offset.reset": "earliest" + } + } } }, "TRANSFER": { diff --git a/docker/central-ledger/default.json b/docker/central-ledger/default.json index 0536ddb08..199a8b452 100644 --- a/docker/central-ledger/default.json +++ b/docker/central-ledger/default.json @@ -170,6 +170,29 @@ "auto.offset.reset": "earliest" } } + }, + "GET": { + "config": { + "options": { + "mode": 2, + "batchSize": 1, + "pollFrequency": 10, + "recursiveTimeout": 100, + "messageCharset": "utf8", + "messageAsJSON": true, + "sync": true, + "consumeTimeout": 1000 + }, + "rdkafkaConf": { + "client.id": "cl-con-bulk-get", + "group.id": "cl-group-bulk-get", + "metadata.broker.list": "localhost:29092", + "socket.keepalive.enable": true + }, + "topicConf": { + "auto.offset.reset": "earliest" + } + } } }, "TRANSFER": { diff --git a/package-lock.json b/package-lock.json index 133874546..152111ffa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@mojaloop/central-ledger", - "version": "10.5.2", + "version": "10.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -271,6 +271,28 @@ "to-fast-properties": "^2.0.0" } }, + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + }, + "dependencies": { + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + } + } + }, "@grpc/proto-loader": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz", @@ -788,16 +810,21 @@ "uuid": "^3.4.0", "v8flags": "^3.1.3" } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" } } }, "@mojaloop/central-services-error-handling": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-error-handling/-/central-services-error-handling-10.4.1.tgz", - "integrity": "sha512-WGhZC+L5va4XwA2jFi7+1S1DrnpRE7Vdefu6u676d2AH1SvMx2ZM8e5943+1Y1T/xlF1ngXYrP7HSMaQG4g+GA==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-error-handling/-/central-services-error-handling-10.6.0.tgz", + "integrity": "sha512-93Jbz/CWNxMiA6/x+KmQezf7C/K3etIAwmXdeAjR9BBDM9xJt1nGfRDovXJZzqV5pTgh9ytGen7A3ub6oVqcQA==", "requires": { "@mojaloop/sdk-standard-components": "10.3.2", - "lodash": "4.17.15" + "lodash": "4.17.19" } }, "@mojaloop/central-services-health": { @@ -812,6 +839,32 @@ "tslib": "2.0.0" }, "dependencies": { + "@mojaloop/central-services-error-handling": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-error-handling/-/central-services-error-handling-10.4.1.tgz", + "integrity": "sha512-WGhZC+L5va4XwA2jFi7+1S1DrnpRE7Vdefu6u676d2AH1SvMx2ZM8e5943+1Y1T/xlF1ngXYrP7HSMaQG4g+GA==", + "requires": { + "@mojaloop/sdk-standard-components": "10.3.2", + "lodash": "4.17.15" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + } + } + }, + "@mojaloop/central-services-logger": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-logger/-/central-services-logger-10.4.0.tgz", + "integrity": "sha512-vndjDG6klX7cGF8+5KrlmwDtav+2rCL5Ntpfd5NG9FqxluFcUkj9d2BUUs99CzG+qkkJZNITvfL8uBooSdYiJg==", + "requires": { + "parse-strings-in-object": "2.0.0", + "rc": "1.2.8", + "winston": "3.2.1" + } + }, "@mojaloop/central-services-shared": { "version": "10.4.2", "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-10.4.2.tgz", @@ -834,18 +887,104 @@ "mustache": "4.0.1", "openapi-backend": "3.5.0", "raw-body": "2.4.1" + }, + "dependencies": { + "@mojaloop/event-sdk": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@mojaloop/event-sdk/-/event-sdk-10.4.0.tgz", + "integrity": "sha512-F6ceYlFR7gd3IUvUmJnE5aqKX5+1gsV+KdudFtWzOjjuP9dtuKtkAtVUP934ijvlGKF6vZPGheiwgnqGUh1cTA==", + "requires": { + "@grpc/proto-loader": "0.5.4", + "@mojaloop/central-services-logger": "10.4.0", + "brototype": "0.0.6", + "error-callsites": "2.0.3", + "grpc": "1.24.3", + "lodash": "4.17.15", + "moment": "2.26.0", + "parse-strings-in-object": "2.0.0", + "protobufjs": "6.9.0", + "rc": "1.2.8", + "serialize-error": "4.1.0", + "sinon": "9.0.2", + "traceparent": "1.0.0", + "tslib": "2.0.0", + "uuid4": "1.1.4", + "winston": "3.2.1" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + } } + }, + "moment": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", + "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==" + }, + "uuid4": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/uuid4/-/uuid4-1.1.4.tgz", + "integrity": "sha512-Gr1q2k40LpF8CokcnQFjPDsdslzJbTCTBG5xQIEflUov431gFkY5KduiGIeKYAamkQnNn4IfdHJbLnl9Bib8TQ==" } } }, "@mojaloop/central-services-logger": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-logger/-/central-services-logger-10.4.0.tgz", - "integrity": "sha512-vndjDG6klX7cGF8+5KrlmwDtav+2rCL5Ntpfd5NG9FqxluFcUkj9d2BUUs99CzG+qkkJZNITvfL8uBooSdYiJg==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-logger/-/central-services-logger-10.6.0.tgz", + "integrity": "sha512-fvZVCtquX+QR+kuKhx/jiyf+B5E7zXYi1HfgaLWR/5+wqdopMltxRGYyRZJyJ1uqdstm+/HOSFvWjqv3JXZ1hw==", "requires": { "parse-strings-in-object": "2.0.0", "rc": "1.2.8", - "winston": "3.2.1" + "winston": "3.3.3" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "requires": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + } + } } }, "@mojaloop/central-services-metrics": { @@ -857,33 +996,44 @@ } }, "@mojaloop/central-services-shared": { - "version": "10.5.2", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-10.5.2.tgz", - "integrity": "sha512-e8mLezEPFmUk3HTxxGnWn0IbHSHLuzgLukenB5iLYrbEc61340Y50peYH5Fmq/5KI8LVXFNVoUUm4GhOEdksuQ==", + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-10.6.1.tgz", + "integrity": "sha512-xUGiZgrpRW9uWshHHmHm3ecvJtJrJNv8BlYcbV9vo+1M5a5336WLd97Zwe/2/o9DwYyCFuNMjz/7JS6tfYEoUw==", "requires": { "@hapi/catbox": "11.1.0", "@hapi/catbox-memory": "5.0.0", - "@mojaloop/central-services-error-handling": "10.4.1", - "@mojaloop/central-services-logger": "10.4.0", + "@mojaloop/central-services-error-handling": "10.6.0", + "@mojaloop/central-services-logger": "10.6.0", "@mojaloop/central-services-metrics": "9.5.0", - "@mojaloop/event-sdk": "10.4.0", - "ajv": "6.12.2", - "ajv-keywords": "3.5.0", + "@mojaloop/event-sdk": "10.6.0", + "ajv": "6.12.3", + "ajv-keywords": "3.5.1", "axios": "0.19.2", "base64url": "3.0.1", "clone": "2.1.2", "data-urls": "2.0.0", "immutable": "3.8.2", - "lodash": "4.17.15", + "lodash": "4.17.19", "mustache": "4.0.1", "openapi-backend": "3.5.1", "raw-body": "2.4.1" }, "dependencies": { + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ajv-keywords": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.0.tgz", - "integrity": "sha512-eyoaac3btgU8eJlvh01En8OCKzRqlLe2G5jDsCr3RiE2uLGMEEB1aaGwVVpwR8M95956tGH6R+9edC++OvzaVw==" + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.1.tgz", + "integrity": "sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA==" }, "openapi-backend": { "version": "3.5.1", @@ -922,6 +1072,13 @@ "requires": { "@mojaloop/sdk-standard-components": "8.6.9", "lodash": "4.17.15" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + } } }, "@mojaloop/central-services-logger": { @@ -964,17 +1121,17 @@ } }, "@mojaloop/event-sdk": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@mojaloop/event-sdk/-/event-sdk-10.4.0.tgz", - "integrity": "sha512-F6ceYlFR7gd3IUvUmJnE5aqKX5+1gsV+KdudFtWzOjjuP9dtuKtkAtVUP934ijvlGKF6vZPGheiwgnqGUh1cTA==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/@mojaloop/event-sdk/-/event-sdk-10.6.0.tgz", + "integrity": "sha512-mDVow/3WDILDUF2v32fqcOZAoRQCOZX8D2fJF3kHvZLGthU9ydNPHK118aVibw76XAyq6E6UbxHMXg3ZUPBlhg==", "requires": { "@grpc/proto-loader": "0.5.4", - "@mojaloop/central-services-logger": "10.4.0", + "@mojaloop/central-services-logger": "10.6.0", "brototype": "0.0.6", "error-callsites": "2.0.3", "grpc": "1.24.3", - "lodash": "4.17.15", - "moment": "2.26.0", + "lodash": "4.17.19", + "moment": "2.27.0", "parse-strings-in-object": "2.0.0", "protobufjs": "6.9.0", "rc": "1.2.8", @@ -982,19 +1139,53 @@ "sinon": "9.0.2", "traceparent": "1.0.0", "tslib": "2.0.0", - "uuid4": "1.1.4", - "winston": "3.2.1" + "uuid4": "2.0.2", + "winston": "3.3.3" }, "dependencies": { - "moment": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", - "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==" + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" }, - "uuid4": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/uuid4/-/uuid4-1.1.4.tgz", - "integrity": "sha512-Gr1q2k40LpF8CokcnQFjPDsdslzJbTCTBG5xQIEflUov431gFkY5KduiGIeKYAamkQnNn4IfdHJbLnl9Bib8TQ==" + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "requires": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + } } } }, @@ -1301,9 +1492,9 @@ "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" }, "@types/node": { - "version": "13.13.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.12.tgz", - "integrity": "sha512-zWz/8NEPxoXNT9YyF2osqyA9WjssZukYpgI4UYZpOjcyqwIUqWGkcCionaEb9Ki+FULyPyvNFpg/329Kd2/pbw==" + "version": "13.13.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.13.tgz", + "integrity": "sha512-UfvBE9oRCAJVzfR+3eWm/sdLFe/qroAPEXP3GPJ1SehQiEVgZT6NQZWYbPMiJ3UdcKM06v4j+S1lTcdWCmw+3g==" }, "abab": { "version": "2.0.3", @@ -4003,6 +4194,11 @@ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", @@ -5779,27 +5975,32 @@ "dev": true }, "knex": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/knex/-/knex-0.21.1.tgz", - "integrity": "sha512-uWszXC2DPaLn/YznGT9wFTWUG9+kqbL4DMz+hCH789GLcLuYzq8werHPDKBJxtKvxrW/S1XIXgrTWdMypiVvsw==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/knex/-/knex-0.21.2.tgz", + "integrity": "sha512-hNp9f3yXCHtMrhV2pVsuCNYmPlgXhyqviMQGLBd9zdF03ZqCO9MPng0oYhNMgIs+vDr55VC6tjEbF1OQ1La7Kg==", "requires": { - "colorette": "1.1.0", + "colorette": "1.2.1", "commander": "^5.1.0", "debug": "4.1.1", "esm": "^3.2.25", "getopts": "2.2.5", "inherits": "~2.0.4", - "interpret": "^2.0.0", + "interpret": "^2.2.0", "liftoff": "3.1.0", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "mkdirp": "^1.0.4", - "pg-connection-string": "2.2.0", + "pg-connection-string": "2.3.0", "tarn": "^3.0.0", "tildify": "2.0.0", "uuid": "^7.0.3", - "v8flags": "^3.1.3" + "v8flags": "^3.2.0" }, "dependencies": { + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==" + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -5814,9 +6015,9 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "pg-connection-string": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.2.0.tgz", - "integrity": "sha512-xB/+wxcpFipUZOQcSzcgkjcNOosGhEoPSjz06jC89lv1dj7mc9bZv6wLVy8M2fVjP0a/xN0N988YDq1L0FhK3A==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz", + "integrity": "sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w==" }, "tarn": { "version": "3.0.0", @@ -5922,9 +6123,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, "lodash.camelcase": { "version": "4.3.0", @@ -6485,9 +6686,9 @@ } }, "mongoose": { - "version": "5.9.20", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.20.tgz", - "integrity": "sha512-vRP6Csu2obzSl3ed7kTQMrolBNgweiRJ/eBU1PSe/rJfjqWS1oqDE2D1ZPGxkVOsKXs7Gyd84GAXerj8IB2UWg==", + "version": "5.9.22", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.22.tgz", + "integrity": "sha512-nwH2LwrGN/jR0Qi8TqSog0MWZRtxdpQxVFcPNjs+CUyCMaxKqFJYrkPILTPKPMMzwrAv1cCQqrvoLl+ggklvbg==", "requires": { "bson": "^1.1.4", "kareem": "2.3.1", @@ -6497,7 +6698,7 @@ "mquery": "3.2.2", "ms": "2.1.2", "regexp-clone": "1.0.0", - "safe-buffer": "5.1.2", + "safe-buffer": "5.2.1", "sift": "7.0.1", "sliced": "1.0.1" }, @@ -6519,6 +6720,11 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.7.0.tgz", "integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, diff --git a/package.json b/package.json index 70e501a63..1f2a7e44b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mojaloop/central-ledger", - "version": "10.5.2", + "version": "10.6.0", "description": "Central ledger hosted by a scheme to record and settle transfers", "license": "Apache-2.0", "author": "ModusBox", @@ -82,13 +82,13 @@ "@hapi/vision": "6.0.0", "@mojaloop/central-object-store": "9.1.0-snapshot", "@mojaloop/central-services-database": "9.2.0", - "@mojaloop/central-services-error-handling": "10.4.1", + "@mojaloop/central-services-error-handling": "10.6.0", "@mojaloop/central-services-health": "10.4.0", - "@mojaloop/central-services-logger": "10.4.0", + "@mojaloop/central-services-logger": "10.6.0", "@mojaloop/central-services-metrics": "9.5.0", - "@mojaloop/central-services-shared": "10.5.2", + "@mojaloop/central-services-shared": "10.6.1", "@mojaloop/central-services-stream": "9.5.0", - "@mojaloop/event-sdk": "10.4.0", + "@mojaloop/event-sdk": "10.6.0", "@mojaloop/forensic-logging-client": "8.3.0", "@mojaloop/ml-number": "8.2.0", "@now-ims/hapi-now-auth": "2.0.2", @@ -105,10 +105,10 @@ "hapi-auth-basic": "5.0.0", "hapi-auth-bearer-token": "6.2.1", "hapi-swagger": "13.0.2", - "knex": "0.21.1", - "lodash": "4.17.15", + "knex": "0.21.2", + "lodash": "4.17.19", "moment": "2.27.0", - "mongoose": "5.9.20", + "mongoose": "5.9.22", "npm-run-all": "4.1.5", "rc": "1.2.8", "require-glob": "3.2.0", diff --git a/src/handlers/bulk/get/handler.js b/src/handlers/bulk/get/handler.js new file mode 100644 index 000000000..835d46abf --- /dev/null +++ b/src/handlers/bulk/get/handler.js @@ -0,0 +1,173 @@ +/***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + + * Gates Foundation + - Name Surname + + * ModusBox + - Steven Oderayi + -------------- + ******/ +'use strict' + +const Logger = require('@mojaloop/central-services-logger') +const EventSdk = require('@mojaloop/event-sdk') +const Util = require('@mojaloop/central-services-shared').Util +const Kafka = require('@mojaloop/central-services-shared').Util.Kafka +const Producer = require('@mojaloop/central-services-stream').Util.Producer +const Consumer = require('@mojaloop/central-services-stream').Util.Consumer +const Enum = require('@mojaloop/central-services-shared').Enum +const Metrics = require('@mojaloop/central-services-metrics') +const ErrorHandler = require('@mojaloop/central-services-error-handling') +const BulkTransferService = require('../../../domain/bulkTransfer') +const TransferObjectTransform = require('../../../domain/transfer/transform') +const Validator = require('../shared/validator') +const Config = require('../../../lib/config') + +const location = { module: 'BulkGetHandler', method: '', path: '' } +const consumerCommit = true +const fromSwitch = true + +/** + * @function BulkGetHandler + * + * @async + * @description Gets a bulk transfer by id. Gets Kafka config from default.json + * + * Calls createHandler to register the handler against the Stream Processing API + * + * @param {error} error - error thrown if something fails within Kafka + * @param {array} messages - a list of messages to consume for the relevant topic + * + * @returns {object} - Returns a boolean: true if successful, or throws and error if failed + */ +const getBulkTransfer = async (error, messages) => { + const histTimerEnd = Metrics.getHistogram( + 'transfer_bulk_get', + 'Consume a get bulk transfer message from the kafka topic and process it accordingly', + ['success', 'fspId'] + ).startTimer() + if (error) { + throw ErrorHandler.Factory.reformatFSPIOPError(error) + } + const message = Array.isArray(messages) ? messages[0] : messages + const contextFromMessage = EventSdk.Tracer.extractContextFromMessage(message.value) + const span = EventSdk.Tracer.createChildSpanFromContext('cl_bulk_transfer_get', contextFromMessage) + try { + await span.audit(message, EventSdk.AuditEventAction.start) + const metadata = message.value.metadata + const action = metadata.event.action + const bulkTransferId = message.value.content.uriParams.id + const kafkaTopic = message.topic + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, { method: `getBulkTransfer:${action}` })) + + const actionLetter = Enum.Events.ActionLetter.get + const params = { message, kafkaTopic, span, consumer: Consumer, producer: Producer } + const eventDetail = { functionality: Enum.Events.Event.Type.NOTIFICATION, action: Enum.Events.Event.Action.BULK_GET } + + Util.breadcrumb(location, { path: 'validationFailed' }) + if (!await Validator.validateParticipantByName(message.value.from)) { + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `breakParticipantDoesntExist--${actionLetter}1`)) + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, histTimerEnd }) + histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) + return true + } + const bulkTransfer = await BulkTransferService.getByIdLight(bulkTransferId) + if (!bulkTransfer) { + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackErrorBulkTransferNotFound--${actionLetter}3`)) + const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.TRANSFER_ID_NOT_FOUND, 'Provided Bulk Transfer ID was not found on the server.') + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, fromSwitch }) + throw fspiopError + } + if (!await Validator.validateParticipantTransferId(message.value.from, bulkTransferId)) { + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackErrorNotBulkTransferParticipant--${actionLetter}2`)) + const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.CLIENT_ERROR) + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, fromSwitch }) + throw fspiopError + } + Util.breadcrumb(location, { path: 'validationPassed' }) + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackMessage--${actionLetter}4`)) + message.value.content.payload = TransferObjectTransform.toFulfil(bulkTransfer) + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, fromSwitch }) + histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) + return true + } catch (err) { + histTimerEnd({ success: false, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) + const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err) + Logger.isErrorEnabled && Logger.error(`${Util.breadcrumb(location)}::${err.message}--G0`) + const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message) + await span.error(fspiopError, state) + await span.finish(fspiopError.message, state) + return true + } finally { + if (!span.isFinished) { + await span.finish() + } + } +} + +/** + * @function registerBulkFulfilHandler + * + * @async + * @description Registers the handler for bulk-transfer topic. Gets Kafka config from default.json + * + * @returns {boolean} - Returns a boolean: true if successful, or throws and error if failed + */ +const registerGetBulkTransferHandler = async () => { + try { + const bulkGetHandler = { + command: getBulkTransfer, + topicName: Kafka.transformGeneralTopicName(Config.KAFKA_CONFIG.TOPIC_TEMPLATES.GENERAL_TOPIC_TEMPLATE.TEMPLATE, Enum.Events.Event.Type.BULK, Enum.Events.Event.Action.GET), + config: Kafka.getKafkaConfig(Config.KAFKA_CONFIG, Enum.Kafka.Config.CONSUMER, Enum.Events.Event.Type.BULK.toUpperCase(), Enum.Events.Event.Action.GET.toUpperCase()) + } + bulkGetHandler.config.rdkafkaConf['client.id'] = bulkGetHandler.topicName + await Consumer.createHandler(bulkGetHandler.topicName, bulkGetHandler.config, bulkGetHandler.command) + return true + } catch (err) { + Logger.isErrorEnabled && Logger.error(err) + throw ErrorHandler.Factory.reformatFSPIOPError(err) + } +} + +/** + * @function RegisterAllHandlers + * + * @async + * @description Registers all module handlers + * + * @returns {boolean} - Returns a boolean: true if successful, or throws and error if failed + */ +const registerAllHandlers = async () => { + try { + await registerGetBulkTransferHandler() + return true + } catch (err) { + Logger.isErrorEnabled && Logger.error(err) + throw ErrorHandler.Factory.reformatFSPIOPError(err) + } +} + +module.exports = { + getBulkTransfer, + registerGetBulkTransferHandler, + registerAllHandlers +} diff --git a/src/handlers/bulk/index.js b/src/handlers/bulk/index.js index f8d28a3e8..6f129ceb0 100644 --- a/src/handlers/bulk/index.js +++ b/src/handlers/bulk/index.js @@ -34,6 +34,7 @@ const BulkPrepareHandlers = require('./prepare/handler') const BulkFulfilHandlers = require('./fulfil/handler') const BulkProcessingHandlers = require('./processing/handler') +const GetBulkTransferHandlers = require('./get/handler') const Logger = require('@mojaloop/central-services-logger') /** @@ -49,6 +50,7 @@ const registerAllHandlers = async () => { await BulkPrepareHandlers.registerAllHandlers() await BulkFulfilHandlers.registerAllHandlers() await BulkProcessingHandlers.registerAllHandlers() + await GetBulkTransferHandlers.registerAllHandlers() return true } catch (err) { Logger.isErrorEnabled && Logger.error(err) @@ -60,5 +62,6 @@ module.exports = { registerBulkPrepareHandler: BulkPrepareHandlers.registerBulkPrepareHandler, registerBulkFulfilHandler: BulkFulfilHandlers.registerBulkFulfilHandler, registerBulkProcessingHandler: BulkProcessingHandlers.registerBulkProcessingHandler, + registerGetBulkTransferHandler: GetBulkTransferHandlers.registerGetBulkTransferHandler, registerAllHandlers } From 5e95a2d55218e1951662599361259d297e054835 Mon Sep 17 00:00:00 2001 From: Steven Oderayi Date: Mon, 13 Jul 2020 13:48:22 +0100 Subject: [PATCH 2/8] Implement GET bulk transfer logic --- config/default.json | 2 +- package-lock.json | 6 ++--- package.json | 2 +- src/domain/bulkTransfer/index.js | 2 +- src/handlers/bulk/get/handler.js | 38 ++++++++++++++++++++------- src/handlers/bulk/shared/validator.js | 14 +++++++++- 6 files changed, 47 insertions(+), 17 deletions(-) diff --git a/config/default.json b/config/default.json index 52822273e..aa3193ca6 100644 --- a/config/default.json +++ b/config/default.json @@ -34,7 +34,7 @@ "RECONNECT_INTERVAL": 5000 }, "MONGODB": { - "DISABLED": true, + "DISABLED": false, "URI": "mongodb://localhost:27017/mlos" }, "ERROR_HANDLING": { diff --git a/package-lock.json b/package-lock.json index 152111ffa..eb3afcd81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6686,9 +6686,9 @@ } }, "mongoose": { - "version": "5.9.22", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.22.tgz", - "integrity": "sha512-nwH2LwrGN/jR0Qi8TqSog0MWZRtxdpQxVFcPNjs+CUyCMaxKqFJYrkPILTPKPMMzwrAv1cCQqrvoLl+ggklvbg==", + "version": "5.9.23", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.23.tgz", + "integrity": "sha512-fMYlMRJz0T6Ax2K2P0jt+kxXd4qaRxyfZCha1YBMczmA2EBlT5SnBlcDyJ4YQa4/z+GoDh06uH090w7BfBcdWg==", "requires": { "bson": "^1.1.4", "kareem": "2.3.1", diff --git a/package.json b/package.json index 1f2a7e44b..28197d3d3 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "knex": "0.21.2", "lodash": "4.17.19", "moment": "2.27.0", - "mongoose": "5.9.22", + "mongoose": "5.9.23", "npm-run-all": "4.1.5", "rc": "1.2.8", "require-glob": "3.2.0", diff --git a/src/domain/bulkTransfer/index.js b/src/domain/bulkTransfer/index.js index cf713e3d7..5f075d0e3 100644 --- a/src/domain/bulkTransfer/index.js +++ b/src/domain/bulkTransfer/index.js @@ -90,7 +90,7 @@ const getBulkTransferById = async (id) => { if ((bulkTransfer.bulkTransferStateId === Enum.Transfers.BulkTransferState.ACCEPTED && transfer.bulkProcessingStateId === Enum.Transfers.BulkProcessingState.ACCEPTED) || (bulkTransfer.bulkTransferStateId === Enum.Transfers.BulkTransferState.COMPLETED && - transfer.bulkProcessingStateId > Enum.Transfers.BulkProcessingState.PROCESSING)) { + transfer.bulkProcessingStateId > Enum.Transfers.BulkProcessingState.PROCESSING)) { payeeIndividualTransfers.push(result) } return resolve(result) diff --git a/src/handlers/bulk/get/handler.js b/src/handlers/bulk/get/handler.js index 835d46abf..d99a67e5b 100644 --- a/src/handlers/bulk/get/handler.js +++ b/src/handlers/bulk/get/handler.js @@ -38,7 +38,7 @@ const Enum = require('@mojaloop/central-services-shared').Enum const Metrics = require('@mojaloop/central-services-metrics') const ErrorHandler = require('@mojaloop/central-services-error-handling') const BulkTransferService = require('../../../domain/bulkTransfer') -const TransferObjectTransform = require('../../../domain/transfer/transform') +const BulkTransferModel = require('../../../models/bulkTransfer/bulkTransfer') const Validator = require('../shared/validator') const Config = require('../../../lib/config') @@ -52,16 +52,16 @@ const fromSwitch = true * @async * @description Gets a bulk transfer by id. Gets Kafka config from default.json * - * Calls createHandler to register the handler against the Stream Processing API + * Calls createHandler to register the handler against the Stream Processing API. * * @param {error} error - error thrown if something fails within Kafka * @param {array} messages - a list of messages to consume for the relevant topic * - * @returns {object} - Returns a boolean: true if successful, or throws and error if failed + * @returns {object} - Returns a boolean: true if successful, or throws an error if failed */ const getBulkTransfer = async (error, messages) => { const histTimerEnd = Metrics.getHistogram( - 'transfer_bulk_get', + 'bulk_transfer_get', 'Consume a get bulk transfer message from the kafka topic and process it accordingly', ['success', 'fspId'] ).startTimer() @@ -84,28 +84,46 @@ const getBulkTransfer = async (error, messages) => { const eventDetail = { functionality: Enum.Events.Event.Type.NOTIFICATION, action: Enum.Events.Event.Action.BULK_GET } Util.breadcrumb(location, { path: 'validationFailed' }) - if (!await Validator.validateParticipantByName(message.value.from)) { + + if (!(await Validator.validateParticipantByName(message.value.from)).isValid) { Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `breakParticipantDoesntExist--${actionLetter}1`)) await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, histTimerEnd }) histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) return true } - const bulkTransfer = await BulkTransferService.getByIdLight(bulkTransferId) - if (!bulkTransfer) { + // TODO: Validate this. Is this sufficient for checking existence of bulk transfer? + const bulkTransferLight = await BulkTransferModel.getById(bulkTransferId) + if (!bulkTransferLight) { Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackErrorBulkTransferNotFound--${actionLetter}3`)) - const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.TRANSFER_ID_NOT_FOUND, 'Provided Bulk Transfer ID was not found on the server.') + const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.BULK_TRANSFER_ID_NOT_FOUND, 'Provided Bulk Transfer ID was not found on the server.') await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, fromSwitch }) throw fspiopError } - if (!await Validator.validateParticipantTransferId(message.value.from, bulkTransferId)) { + // The SD says this should be 404 response which I think will not be constent with single transfers + // which responds with CLIENT_ERROR instead + const participants = BulkTransferService.getParticipantsById(bulkTransferId) + if (![participants.payeeFsp, participants.payerFsp].includes(message.value.from)) { Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackErrorNotBulkTransferParticipant--${actionLetter}2`)) const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.CLIENT_ERROR) await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, fromSwitch }) throw fspiopError } + const isPayeeRequest = participants.payeeFsp === message.value.from Util.breadcrumb(location, { path: 'validationPassed' }) Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackMessage--${actionLetter}4`)) - message.value.content.payload = TransferObjectTransform.toFulfil(bulkTransfer) + const bulkTransfer = await BulkTransferService.getBulkTransferById(bulkTransferId) + let payload = { + bulkTransferState: bulkTransfer.bulkTransferStateId + } + if (bulkTransfer.bulkTransferStateId !== Enum.Transfers.BulkProcessingState.PROCESSING) { + payload = { + ...payload, + completedTimestamp: bulkTransfer.completedDate, + individualTransferResults: isPayeeRequest ? bulkTransfer.payeeBulkTransfer.individualTransferResults : bulkTransfer.payerBulkTransfer.individualTransferResults, + extensionList: isPayeeRequest ? bulkTransfer.payeeBulkTransfer.extensionList : bulkTransfer.payerBulkTransfer.extensionList + } + } + message.value.content.payload = payload await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, fromSwitch }) histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) return true diff --git a/src/handlers/bulk/shared/validator.js b/src/handlers/bulk/shared/validator.js index e784dd64a..6b55a049e 100644 --- a/src/handlers/bulk/shared/validator.js +++ b/src/handlers/bulk/shared/validator.js @@ -25,6 +25,7 @@ * ModusBox - Georgi Georgiev - Rajiv Mothilal + - Steven Oderayi -------------- ******/ 'use strict' @@ -130,7 +131,18 @@ const validateBulkTransferFulfilment = async (payload, headers) => { return { isValid, reasons } } +const validateParticipantBulkTransferId = async function (participantName, bulkTransferId) { + const bulkTransferParticipant = await BulkTransferService.getBulkTransferParticipant(participantName, bulkTransferId) + let validationPassed = false + if (Array.isArray(bulkTransferParticipant) && bulkTransferParticipant.length > 0) { + validationPassed = true + } + return validationPassed +} + module.exports = { validateBulkTransfer, - validateBulkTransferFulfilment + validateBulkTransferFulfilment, + validateParticipantByName, + validateParticipantBulkTransferId } From 86749f3bd5b96d625e067f7fa6b7833fa0caaad2 Mon Sep 17 00:00:00 2001 From: Steven Oderayi Date: Mon, 13 Jul 2020 14:06:30 +0100 Subject: [PATCH 3/8] Restore default config --- config/default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/default.json b/config/default.json index aa3193ca6..52822273e 100644 --- a/config/default.json +++ b/config/default.json @@ -34,7 +34,7 @@ "RECONNECT_INTERVAL": 5000 }, "MONGODB": { - "DISABLED": false, + "DISABLED": true, "URI": "mongodb://localhost:27017/mlos" }, "ERROR_HANDLING": { From 9637c931685ebcadccf413c096b31815dec0b709 Mon Sep 17 00:00:00 2001 From: Steven Oderayi Date: Tue, 14 Jul 2020 14:36:22 +0100 Subject: [PATCH 4/8] Add unit tests --- package-lock.json | 367 ++++-------------- package.json | 8 +- src/domain/bulkTransfer/index.js | 6 +- test/unit/handlers/bulk/get/handler.test.js | 389 ++++++++++++++++++++ 4 files changed, 474 insertions(+), 296 deletions(-) create mode 100644 test/unit/handlers/bulk/get/handler.test.js diff --git a/package-lock.json b/package-lock.json index eb3afcd81..0d8c003a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -761,61 +761,13 @@ } }, "@mojaloop/central-services-database": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-database/-/central-services-database-9.2.0.tgz", - "integrity": "sha512-MEdXBBv4VFheaxe4629fIZjhlxNN7oHAnBPjkOjyTuZaZO4C8toycpw8qWZydjMxyKIbqybkjnzFBSbIj97FRA==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-database/-/central-services-database-10.6.0.tgz", + "integrity": "sha512-hqTTSCcS0zAwjvcHtPzDzg4cUS//0syAPsohdBxY+tKUwwMRaI+rv6b1TzV9U/33LyBdLeUZcb0zOTOmmcoUuQ==", "requires": { - "knex": "0.20.10", - "lodash": "4.17.15", + "knex": "0.21.2", + "lodash": "4.17.19", "mysql": "2.18.1" - }, - "dependencies": { - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "knex": { - "version": "0.20.10", - "resolved": "https://registry.npmjs.org/knex/-/knex-0.20.10.tgz", - "integrity": "sha512-07D6fvY5NdvrfRPmkLLG+OrHvmAy55OX7eXkN8TMiOOI5lWJh1dC2zKjeEQJqUILMOsTnZCGqTKGaRm4t1E9xg==", - "requires": { - "bluebird": "^3.7.2", - "colorette": "1.1.0", - "commander": "^4.1.1", - "debug": "4.1.1", - "esm": "^3.2.25", - "getopts": "2.2.5", - "inherits": "~2.0.4", - "interpret": "^2.0.0", - "liftoff": "3.1.0", - "lodash": "^4.17.15", - "mkdirp": "^0.5.1", - "pg-connection-string": "2.1.0", - "tarn": "^2.0.0", - "tildify": "2.0.0", - "uuid": "^3.4.0", - "v8flags": "^3.1.3" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - } } }, "@mojaloop/central-services-error-handling": { @@ -828,107 +780,15 @@ } }, "@mojaloop/central-services-health": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-health/-/central-services-health-10.4.0.tgz", - "integrity": "sha512-0dOYlfWaRga/N4cTtho8MATfo0Z6FUEZcJXFPci02niG0jWsu1rB56f/8nkzHal17kQiQaiuElxbxvjJRh5cvg==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-health/-/central-services-health-10.6.0.tgz", + "integrity": "sha512-ypO55rFBEW98v38rcJPvPJ5d2jPU45MoMjgOYnVVAptLK8YcUwomtMZGwfnXggPFyo2m/+p/rV8I9zhKap04rg==", "requires": { "@hapi/hapi": "19.1.1", - "@mojaloop/central-services-error-handling": "10.4.1", - "@mojaloop/central-services-logger": "10.4.0", - "@mojaloop/central-services-shared": "10.4.2", + "@mojaloop/central-services-error-handling": "10.6.0", + "@mojaloop/central-services-logger": "10.6.0", + "@mojaloop/central-services-shared": "10.6.1", "tslib": "2.0.0" - }, - "dependencies": { - "@mojaloop/central-services-error-handling": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-error-handling/-/central-services-error-handling-10.4.1.tgz", - "integrity": "sha512-WGhZC+L5va4XwA2jFi7+1S1DrnpRE7Vdefu6u676d2AH1SvMx2ZM8e5943+1Y1T/xlF1ngXYrP7HSMaQG4g+GA==", - "requires": { - "@mojaloop/sdk-standard-components": "10.3.2", - "lodash": "4.17.15" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - } - } - }, - "@mojaloop/central-services-logger": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-logger/-/central-services-logger-10.4.0.tgz", - "integrity": "sha512-vndjDG6klX7cGF8+5KrlmwDtav+2rCL5Ntpfd5NG9FqxluFcUkj9d2BUUs99CzG+qkkJZNITvfL8uBooSdYiJg==", - "requires": { - "parse-strings-in-object": "2.0.0", - "rc": "1.2.8", - "winston": "3.2.1" - } - }, - "@mojaloop/central-services-shared": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-10.4.2.tgz", - "integrity": "sha512-CM5EKSOC9L/ldXiPVHXOup4MwHWMDYCIp4zMFc40cq11kh6qjg2R6QBWkquQiqXm5pP0jtCUM7j74KRu/M+UUA==", - "requires": { - "@hapi/catbox": "11.1.0", - "@hapi/catbox-memory": "5.0.0", - "@mojaloop/central-services-error-handling": "10.4.1", - "@mojaloop/central-services-logger": "10.4.0", - "@mojaloop/central-services-metrics": "9.5.0", - "@mojaloop/event-sdk": "10.4.0", - "ajv": "6.12.2", - "ajv-keywords": "3.4.1", - "axios": "0.19.2", - "base64url": "3.0.1", - "clone": "2.1.2", - "data-urls": "2.0.0", - "immutable": "3.8.2", - "lodash": "4.17.15", - "mustache": "4.0.1", - "openapi-backend": "3.5.0", - "raw-body": "2.4.1" - }, - "dependencies": { - "@mojaloop/event-sdk": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@mojaloop/event-sdk/-/event-sdk-10.4.0.tgz", - "integrity": "sha512-F6ceYlFR7gd3IUvUmJnE5aqKX5+1gsV+KdudFtWzOjjuP9dtuKtkAtVUP934ijvlGKF6vZPGheiwgnqGUh1cTA==", - "requires": { - "@grpc/proto-loader": "0.5.4", - "@mojaloop/central-services-logger": "10.4.0", - "brototype": "0.0.6", - "error-callsites": "2.0.3", - "grpc": "1.24.3", - "lodash": "4.17.15", - "moment": "2.26.0", - "parse-strings-in-object": "2.0.0", - "protobufjs": "6.9.0", - "rc": "1.2.8", - "serialize-error": "4.1.0", - "sinon": "9.0.2", - "traceparent": "1.0.0", - "tslib": "2.0.0", - "uuid4": "1.1.4", - "winston": "3.2.1" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - } - } - }, - "moment": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", - "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==" - }, - "uuid4": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/uuid4/-/uuid4-1.1.4.tgz", - "integrity": "sha512-Gr1q2k40LpF8CokcnQFjPDsdslzJbTCTBG5xQIEflUov431gFkY5KduiGIeKYAamkQnNn4IfdHJbLnl9Bib8TQ==" - } } }, "@mojaloop/central-services-logger": { @@ -1054,69 +914,21 @@ } }, "@mojaloop/central-services-stream": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-stream/-/central-services-stream-9.5.0.tgz", - "integrity": "sha512-ZAyIn7zTbbnEwDQl5rjmeoNULHlW4ThWy7KDKoGnQ9bPueslb7oGXFQhmv/MLZkllWXwUjjWsIpycB54tQewwA==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-stream/-/central-services-stream-10.6.0.tgz", + "integrity": "sha512-1f+027JPvXL/xT4Z9YgTB+dbNCSi77qI9AqSFlBq/QYz1BpWWWmBAwKCoj/IKP+9LBPkkpSC6Xq+TcmCvCpzUw==", "requires": { - "@mojaloop/central-services-error-handling": "9.1.0", - "@mojaloop/central-services-logger": "9.5.1", + "@mojaloop/central-services-error-handling": "10.6.0", + "@mojaloop/central-services-logger": "10.6.0", "async": "3.2.0", "events": "3.1.0", - "node-rdkafka": "2.8.0" + "node-rdkafka": "2.9.0" }, "dependencies": { - "@mojaloop/central-services-error-handling": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-error-handling/-/central-services-error-handling-9.1.0.tgz", - "integrity": "sha512-6tljAx/3kITegnVgCxpOMGtzsrtSLRjNbcwXH1QidKtGeic1MsQIJgQIJuQcQlXGrIVDpJ/4JyOpfKCOh+AxwQ==", - "requires": { - "@mojaloop/sdk-standard-components": "8.6.9", - "lodash": "4.17.15" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - } - } - }, - "@mojaloop/central-services-logger": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-logger/-/central-services-logger-9.5.1.tgz", - "integrity": "sha512-VItX0jmJkGk5GiXnO5s2Fz7cpYvGtq0AmzrjT+Va39XvL/eMPMvzDy08wRbkcyD/RRTzu/20BKMWBw7GtkzG6A==", - "requires": { - "parse-strings-in-object": "2.0.0", - "rc": "1.2.8", - "winston": "3.2.1" - } - }, - "@mojaloop/sdk-standard-components": { - "version": "8.6.9", - "resolved": "https://registry.npmjs.org/@mojaloop/sdk-standard-components/-/sdk-standard-components-8.6.9.tgz", - "integrity": "sha512-2S1pmYm8rdAlgrzUhS67+vMpKWWWxYnq2p/Hd4idrWHehSz6C4b1oxF/e4wx4SxVbFkMwgdXQt4Dy4tvoswhbQ==", - "requires": { - "base64url": "^3.0.1", - "ilp-packet": "2.2.0", - "jsonwebtoken": "^8.5.1", - "jws": "^3.2.2", - "request": "^2.34", - "request-promise-native": "^1.0.7" - } - }, "async": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } } } }, @@ -1574,6 +1386,7 @@ "version": "6.12.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1581,11 +1394,6 @@ "uri-js": "^4.2.2" } }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" - }, "ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -1779,6 +1587,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, "requires": { "safer-buffer": "~2.1.0" } @@ -1796,7 +1605,8 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true }, "assign-symbols": { "version": "1.0.0", @@ -1829,7 +1639,8 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true }, "atob": { "version": "2.1.2", @@ -1883,12 +1694,14 @@ "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true }, "aws4": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", - "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==" + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "dev": true }, "axios": { "version": "0.19.2", @@ -1967,6 +1780,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, "requires": { "tweetnacl": "^0.14.3" } @@ -2432,7 +2246,8 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true }, "catbox-memory": { "version": "4.0.1", @@ -2694,11 +2509,6 @@ "simple-swizzle": "^0.2.2" } }, - "colorette": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", - "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==" - }, "colornames": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", @@ -2727,6 +2537,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -2848,6 +2659,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -3052,7 +2864,8 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true }, "delegates": { "version": "1.0.0", @@ -3188,6 +3001,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -3960,7 +3774,8 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true }, "fast-deep-equal": { "version": "3.1.3", @@ -4285,12 +4100,14 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true }, "form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -4427,6 +4244,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -4763,12 +4581,14 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true }, "har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, "requires": { "ajv": "^6.5.5", "har-schema": "^2.0.0" @@ -4924,6 +4744,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -5446,7 +5267,8 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "is-unc-path": { "version": "1.0.0", @@ -5485,7 +5307,8 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true }, "istanbul-lib-coverage": { "version": "3.0.0", @@ -5680,7 +5503,8 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true }, "jsdoc": { "version": "3.6.4", @@ -5765,7 +5589,8 @@ "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true }, "json-schema-ref-parser": { "version": "6.1.0", @@ -5791,7 +5616,8 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true }, "json5": { "version": "2.1.3", @@ -5887,6 +5713,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -6397,6 +6224,7 @@ "version": "2.1.27", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, "requires": { "mime-db": "1.44.0" } @@ -6686,9 +6514,9 @@ } }, "mongoose": { - "version": "5.9.23", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.23.tgz", - "integrity": "sha512-fMYlMRJz0T6Ax2K2P0jt+kxXd4qaRxyfZCha1YBMczmA2EBlT5SnBlcDyJ4YQa4/z+GoDh06uH090w7BfBcdWg==", + "version": "5.9.24", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.24.tgz", + "integrity": "sha512-uxTLy/ExYmOfKvvbjn1PHbjSJg0SQzff+dW6jbnywtbBcfPRC/3etnG9hPv6KJe/5TFZQGxCyiSezkqa0+iJAQ==", "requires": { "bson": "^1.1.4", "kareem": "2.3.1", @@ -6900,9 +6728,9 @@ } }, "node-rdkafka": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/node-rdkafka/-/node-rdkafka-2.8.0.tgz", - "integrity": "sha512-ZjCeUi7LxQIRXGkrUPvXcOnRwMO5vnUrqnDuR0eNbUla1jz1tRfvGYpncg7fdcxzHzT9Ddf8JJvQWpuGEu2DZQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/node-rdkafka/-/node-rdkafka-2.9.0.tgz", + "integrity": "sha512-lVBb3J/KVMDXUSdC0avoNZ/9Yab9XiDMTFPKdMkXc4AjaIafVPGLNa5yVV7hly9pBfZ5yIHF71sAI4SH/E5G4Q==", "requires": { "bindings": "^1.3.1", "nan": "^2.14.0" @@ -7499,7 +7327,8 @@ "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7671,22 +7500,6 @@ "format-util": "^1.0.3" } }, - "openapi-backend": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/openapi-backend/-/openapi-backend-3.5.0.tgz", - "integrity": "sha512-KXo23yI6TE2kJTU9p+WMkK8eROvH1txIZOjCYRBvdXblJQHlfW7PoPPY8eUlw9suyFJz/r4h+pJSRwKQDZ5p1g==", - "requires": { - "ajv": "^6.10.0", - "bath-es5": "^3.0.3", - "cookie": "^0.4.0", - "lodash": "^4.17.15", - "mock-json-schema": "^1.0.7", - "openapi-schema-validation": "^0.4.2", - "openapi-types": "^1.3.4", - "qs": "^6.9.3", - "swagger-parser": "^9.0.1" - } - }, "openapi-schema-validation": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/openapi-schema-validation/-/openapi-schema-validation-0.4.2.tgz", @@ -8042,12 +7855,8 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg-connection-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.1.0.tgz", - "integrity": "sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg==" + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true }, "picomatch": { "version": "2.2.2", @@ -8359,7 +8168,8 @@ "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true }, "pstree.remy": { "version": "1.1.8", @@ -8706,6 +8516,7 @@ "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -8732,28 +8543,11 @@ "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true } } }, - "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", - "requires": { - "lodash": "^4.17.15" - } - }, - "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", - "requires": { - "request-promise-core": "1.1.3", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -9400,6 +9194,7 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -9513,11 +9308,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" - }, "stream-shift": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", @@ -9874,11 +9664,6 @@ "yallist": "^3.0.3" } }, - "tarn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tarn/-/tarn-2.0.0.tgz", - "integrity": "sha512-7rNMCZd3s9bhQh47ksAQd92ADFcJUjjbyOvyFjNLwTPpGieFHMC84S+LOzw0fx1uh6hnDz/19r8CPMnIjJlMMA==" - }, "tdigest": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", @@ -10050,6 +9835,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, "requires": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -10085,6 +9871,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -10355,7 +10142,8 @@ "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true }, "uuid4": { "version": "2.0.2", @@ -10403,6 +10191,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", diff --git a/package.json b/package.json index 28197d3d3..8a24af836 100644 --- a/package.json +++ b/package.json @@ -81,13 +81,13 @@ "@hapi/joi": "17.1.1", "@hapi/vision": "6.0.0", "@mojaloop/central-object-store": "9.1.0-snapshot", - "@mojaloop/central-services-database": "9.2.0", + "@mojaloop/central-services-database": "10.6.0", "@mojaloop/central-services-error-handling": "10.6.0", - "@mojaloop/central-services-health": "10.4.0", + "@mojaloop/central-services-health": "10.6.0", "@mojaloop/central-services-logger": "10.6.0", "@mojaloop/central-services-metrics": "9.5.0", "@mojaloop/central-services-shared": "10.6.1", - "@mojaloop/central-services-stream": "9.5.0", + "@mojaloop/central-services-stream": "10.6.0", "@mojaloop/event-sdk": "10.6.0", "@mojaloop/forensic-logging-client": "8.3.0", "@mojaloop/ml-number": "8.2.0", @@ -108,7 +108,7 @@ "knex": "0.21.2", "lodash": "4.17.19", "moment": "2.27.0", - "mongoose": "5.9.23", + "mongoose": "5.9.24", "npm-run-all": "4.1.5", "rc": "1.2.8", "require-glob": "3.2.0", diff --git a/src/domain/bulkTransfer/index.js b/src/domain/bulkTransfer/index.js index 5f075d0e3..d6ba7b40a 100644 --- a/src/domain/bulkTransfer/index.js +++ b/src/domain/bulkTransfer/index.js @@ -24,7 +24,7 @@ 'use strict' /** - * @module src/domain/transfer/ + * @module src/domain/bulkTransfer/ */ const Enum = require('@mojaloop/central-services-shared').Enum @@ -90,7 +90,7 @@ const getBulkTransferById = async (id) => { if ((bulkTransfer.bulkTransferStateId === Enum.Transfers.BulkTransferState.ACCEPTED && transfer.bulkProcessingStateId === Enum.Transfers.BulkProcessingState.ACCEPTED) || (bulkTransfer.bulkTransferStateId === Enum.Transfers.BulkTransferState.COMPLETED && - transfer.bulkProcessingStateId > Enum.Transfers.BulkProcessingState.PROCESSING)) { + transfer.bulkProcessingStateId > Enum.Transfers.BulkProcessingState.PROCESSING)) { payeeIndividualTransfers.push(result) } return resolve(result) @@ -124,7 +124,7 @@ const getBulkTransferById = async (id) => { payerFsp: bulkTransfer.payerFsp, payeeFsp: bulkTransfer.payeeFsp, expiration: bulkTransfer.expirationDate, - completedDate: bulkTransfer.completedDate, + completedDate: bulkTransfer.completedTimestamp, payerBulkTransfer, payeeBulkTransfer } diff --git a/test/unit/handlers/bulk/get/handler.test.js b/test/unit/handlers/bulk/get/handler.test.js new file mode 100644 index 000000000..e5f5b376e --- /dev/null +++ b/test/unit/handlers/bulk/get/handler.test.js @@ -0,0 +1,389 @@ +/***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******/ +'use strict' + +const Uuid = require('uuid4') +const Sinon = require('sinon') +const Proxyquire = require('proxyquire') +const Test = require('tapes')(require('tape')) +const EventSdk = require('@mojaloop/event-sdk') +const Kafka = require('@mojaloop/central-services-shared').Util.Kafka +const MainUtil = require('@mojaloop/central-services-shared').Util +const KafkaConsumer = require('@mojaloop/central-services-stream').Kafka.Consumer +const Consumer = require('@mojaloop/central-services-stream').Util.Consumer +const Enum = require('@mojaloop/central-services-shared').Enum +const Comparators = require('@mojaloop/central-services-shared').Util.Comparators +const Validator = require('../../../../../src/handlers/bulk/shared/validator') +const BulkTransferService = require('../../../../../src/domain/bulkTransfer') +const BulkTransferModel = require('../../../../../src/models/bulkTransfer/bulkTransfer') +const ilp = require('../../../../../src/models/transfer/ilpPacket') +// const TransferState = Enum.Transfers.TransferState +// const TransferInternalState = Enum.Transfers.TransferInternalState + +const bulkTransfer = { + bulkTransferId: 'fake-bulk-transfer-id', + bulkQuoteId: 'fake-bulk-quote-id', + payerFsp: 'dfsp1', + payeeFsp: 'dfsp2', + expiration: '2016-05-24T08:38:08.699-04:00', + individualTransfers: [ + { + transferId: 'b51ec534-ee48-4575-b6a9-ead2955b8999', + transferAmount: { + currency: 'USD', + amount: '433.88' + }, + ilpPacket: 'AYIBgQAAAAAAAASwNGxldmVsb25lLmRmc3AxLm1lci45T2RTOF81MDdqUUZERmZlakgyOVc4bXFmNEpLMHlGTFGCAUBQU0svMS4wCk5vbmNlOiB1SXlweUYzY3pYSXBFdzVVc05TYWh3CkVuY3J5cHRpb246IG5vbmUKUGF5bWVudC1JZDogMTMyMzZhM2ItOGZhOC00MTYzLTg0NDctNGMzZWQzZGE5OGE3CgpDb250ZW50LUxlbmd0aDogMTM1CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbgpTZW5kZXItSWRlbnRpZmllcjogOTI4MDYzOTEKCiJ7XCJmZWVcIjowLFwidHJhbnNmZXJDb2RlXCI6XCJpbnZvaWNlXCIsXCJkZWJpdE5hbWVcIjpcImFsaWNlIGNvb3BlclwiLFwiY3JlZGl0TmFtZVwiOlwibWVyIGNoYW50XCIsXCJkZWJpdElkZW50aWZpZXJcIjpcIjkyODA2MzkxXCJ9IgA', + condition: 'YlK5TZyhflbXaDRPtR5zhCu8FrbgvrQwwmzuH0iQ0AI' + } + ], + extensionList: { + extension: [ + { + key: 'key1', + value: 'value1' + }, + { + key: 'key2', + value: 'value2' + } + ] + } +} + +const bulkTransferReturn = { + bulkTransferId: bulkTransfer.bulkTransferId, + bulkTransferStateId: 'COMPLETED', + completedTimestamp: new Date().toISOString(), + payerFsp: 'payerfsp', + payeeFsp: 'payeefsp', + bulkQuoteId: bulkTransfer.bulkQuoteId, + expirationDate: new Date().toISOString() +} + +const messageProtocol = { + id: Uuid(), + from: bulkTransfer.payerFsp, + to: bulkTransfer.payeeFsp, + type: 'application/json', + content: { + headers: { + 'fspiop-source': bulkTransfer.payeeFsp, + 'fspiop-destination': 'source' + }, + uriParams: { id: bulkTransfer.bulkTransferId } + }, + metadata: { + event: { + id: Uuid(), + type: Enum.Events.Event.Type.BULK, + action: Enum.Events.Event.Action.GET, + createdAt: new Date(), + state: { + status: 'success', + code: 0 + } + } + }, + pp: '' +} + +const topicName = 'topic-test' + +const messages = [ + { + topic: topicName, + value: messageProtocol + } +] + +const config = { + options: { + mode: 2, + batchSize: 1, + pollFrequency: 10, + recursiveTimeout: 100, + messageCharset: 'utf8', + messageAsJSON: true, + sync: true, + consumeTimeout: 1000 + }, + rdkafkaConf: { + 'client.id': 'kafka-test', + debug: 'all', + 'group.id': 'central-ledger-kafka', + 'metadata.broker.list': 'localhost:9092', + 'enable.auto.commit': false + } +} + +const command = () => { } + +let SpanStub +let allBulkTransferHandlers + +Test('Bulk Transfer GET handler', getHandlerTest => { + let sandbox + + getHandlerTest.beforeEach(test => { + sandbox = Sinon.createSandbox() + SpanStub = { + audit: sandbox.stub().callsFake(), + error: sandbox.stub().callsFake(), + finish: sandbox.stub().callsFake(), + debug: sandbox.stub().callsFake(), + info: sandbox.stub().callsFake(), + getChild: sandbox.stub().returns(SpanStub), + setTags: sandbox.stub().callsFake() + } + + const TracerStub = { + extractContextFromMessage: sandbox.stub().callsFake(() => { + return {} + }), + createChildSpanFromContext: sandbox.stub().callsFake(() => { + return SpanStub + }) + } + + const EventSdkStub = { + Tracer: TracerStub + } + + allBulkTransferHandlers = Proxyquire('../../../../../src/handlers/bulk/get/handler', { + '@mojaloop/event-sdk': EventSdkStub + }) + + sandbox.stub(KafkaConsumer.prototype, 'constructor').returns(Promise.resolve()) + sandbox.stub(KafkaConsumer.prototype, 'connect').returns(Promise.resolve()) + sandbox.stub(KafkaConsumer.prototype, 'consume').returns(Promise.resolve()) + sandbox.stub(KafkaConsumer.prototype, 'commitMessageSync').returns(Promise.resolve()) + sandbox.stub(Comparators) + sandbox.stub(Validator) + sandbox.stub(BulkTransferService) + sandbox.stub(BulkTransferModel) + sandbox.stub(Consumer, 'getConsumer').returns({ + commitMessageSync: async function () { + return true + } + }) + sandbox.stub(Consumer, 'isConsumerAutoCommitEnabled').returns(false) + sandbox.stub(ilp) + sandbox.stub(Kafka) + sandbox.stub(MainUtil.StreamingProtocol) + Kafka.produceGeneralMessage.returns(Promise.resolve()) + test.end() + }) + + getHandlerTest.afterEach(test => { + sandbox.restore() + test.end() + }) + + getHandlerTest.test('registerGetBulkTransferHandler should', registerHandlerTest => { + registerHandlerTest.test('returns true when registering the GET bulk transfer handler', async (test) => { + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + const result = await allBulkTransferHandlers.registerGetBulkTransferHandler() + test.equal(result, true) + test.end() + }) + + registerHandlerTest.test('return an error when registering GET bulk transfer handler.', async (test) => { + try { + await Consumer.createHandler(topicName, config, command) + Kafka.transformGeneralTopicName.returns(topicName) + Kafka.getKafkaConfig.throws(new Error()) + await allBulkTransferHandlers.registerGetBulkTransferHandler() + test.fail('Error not thrown') + test.end() + } catch (e) { + test.pass('Error thrown') + test.end() + } + }) + registerHandlerTest.end() + }) + + getHandlerTest.test('get bulk transfer by id should', getBulkTransferTest => { + getBulkTransferTest.test('return true on a single message', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages[0]) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return true on an array of messages', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Consumer.isConsumerAutoCommitEnabled.returns(true) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when an error is passed in', async (test) => { + try { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformGeneralTopicName.returns(topicName) + Kafka.getKafkaConfig.returns(config) + await allBulkTransferHandlers.getBulkTransfer(true, localMessages) + test.fail('Error not thrown') + test.end() + } catch (e) { + test.pass('Error thrown') + test.end() + } + }) + + getBulkTransferTest.test('return an error when the Kafka topic is invalid', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Consumer.getConsumer.throws(new Error()) + Kafka.getKafkaConfig.returns(config) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the bulk transfer by id is not found', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.returns(null) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the bulk transfer by id is not found - autocommit enabled', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.returns(null) + Consumer.isConsumerAutoCommitEnabled.returns(true) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the requester is not involved in the bulk transfer', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + Validator.validateParticipantBulkTransferId.returns(false) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.returns({}) + Consumer.isConsumerAutoCommitEnabled.returns(true) + localMessages[0].value.from = 'invalidfsp' + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the requester is not involved in the bulk transfer - autocommit disabled', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + Validator.validateParticipantBulkTransferId.returns(false) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.returns({}) + Consumer.isConsumerAutoCommitEnabled.returns(false) + localMessages[0].value.from = 'invalidfsp' + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the bulk transfer by id is found - autocommit enabled', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferReturn)) + Consumer.isConsumerAutoCommitEnabled.returns(true) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('log an error when general message cannot be produced', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.proceed.throws(new Error()) + Validator.validateParticipantByName.returns({ isValid: true }) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + const bulkTransferResult = MainUtil.clone(bulkTransferReturn) + bulkTransferResult.bulkTransferStateId = Enum.Transfers.BulkProcessingState.PROCESSING + bulkTransferResult.extensionList = [] + BulkTransferModel.getById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferResult)) + BulkTransferService.getBulkTransferById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferResult)) + + try { + await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + const expectedState = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, '2001', 'Internal server error') + test.ok(SpanStub.finish.calledWith('', expectedState)) + test.end() + } catch (e) { + test.fail('Error thrown') + test.end() + } + }) + + getBulkTransferTest.end() + }) + + getHandlerTest.end() +}) From 47527f00e6c387b4bbef376de7bd007daadf4ac8 Mon Sep 17 00:00:00 2001 From: Steven Oderayi Date: Tue, 14 Jul 2020 14:45:23 +0100 Subject: [PATCH 5/8] Bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 04c6893b3..b089f5678 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@mojaloop/central-ledger", - "version": "10.6.0", + "version": "10.6.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5a4b6f634..44a0d06ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mojaloop/central-ledger", - "version": "10.6.0", + "version": "10.6.1", "description": "Central ledger hosted by a scheme to record and settle transfers", "license": "Apache-2.0", "author": "ModusBox", From 09b0bea69bd3a332773cd6a4f13e197a9390dc6c Mon Sep 17 00:00:00 2001 From: Steven Oderayi Date: Wed, 15 Jul 2020 11:07:59 +0100 Subject: [PATCH 6/8] More bug fixes --- package-lock.json | 86 ++++++++++++++++++------- package.json | 6 +- src/handlers/bulk/get/handler.js | 15 +++-- src/handlers/bulk/processing/handler.js | 33 ++++++---- 4 files changed, 93 insertions(+), 47 deletions(-) diff --git a/package-lock.json b/package-lock.json index b089f5678..b38e790db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -784,6 +784,43 @@ "@mojaloop/central-services-logger": "10.6.0", "@mojaloop/central-services-shared": "10.6.1", "tslib": "2.0.0" + }, + "dependencies": { + "@mojaloop/central-services-shared": { + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-10.6.1.tgz", + "integrity": "sha512-xUGiZgrpRW9uWshHHmHm3ecvJtJrJNv8BlYcbV9vo+1M5a5336WLd97Zwe/2/o9DwYyCFuNMjz/7JS6tfYEoUw==", + "requires": { + "@hapi/catbox": "11.1.0", + "@hapi/catbox-memory": "5.0.0", + "@mojaloop/central-services-error-handling": "10.6.0", + "@mojaloop/central-services-logger": "10.6.0", + "@mojaloop/central-services-metrics": "9.5.0", + "@mojaloop/event-sdk": "10.6.0", + "ajv": "6.12.3", + "ajv-keywords": "3.5.1", + "axios": "0.19.2", + "base64url": "3.0.1", + "clone": "2.1.2", + "data-urls": "2.0.0", + "immutable": "3.8.2", + "lodash": "4.17.19", + "mustache": "4.0.1", + "openapi-backend": "3.5.1", + "raw-body": "2.4.1" + } + }, + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + } } }, "@mojaloop/central-services-logger": { @@ -851,9 +888,9 @@ } }, "@mojaloop/central-services-shared": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-10.6.1.tgz", - "integrity": "sha512-xUGiZgrpRW9uWshHHmHm3ecvJtJrJNv8BlYcbV9vo+1M5a5336WLd97Zwe/2/o9DwYyCFuNMjz/7JS6tfYEoUw==", + "version": "10.6.2", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-10.6.2.tgz", + "integrity": "sha512-16fEcpaB0dYt+2acYJOtm95IQEtkXDgZSucHAYgZcqrpH6C7Tx9SmMJ/smXR6fDg88uIB6Hs9J4zE/61BhlFlw==", "requires": { "@hapi/catbox": "11.1.0", "@hapi/catbox-memory": "5.0.0", @@ -884,27 +921,6 @@ "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } - }, - "ajv-keywords": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.1.tgz", - "integrity": "sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA==" - }, - "openapi-backend": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/openapi-backend/-/openapi-backend-3.5.1.tgz", - "integrity": "sha512-aVScBkutF280uC4OouZkUThy58Ot3dk2K1HIll9zNsi1If0paU5enwTZKUkLQybSWkvq1MATddz5uz7J4h/sOg==", - "requires": { - "ajv": "^6.10.0", - "bath-es5": "^3.0.3", - "cookie": "^0.4.0", - "lodash": "^4.17.15", - "mock-json-schema": "^1.0.7", - "openapi-schema-validation": "^0.4.2", - "openapi-types": "^1.3.4", - "qs": "^6.9.3", - "swagger-parser": "^9.0.1" - } } } }, @@ -1381,7 +1397,6 @@ "version": "6.12.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1389,6 +1404,11 @@ "uri-js": "^4.2.2" } }, + "ajv-keywords": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.1.tgz", + "integrity": "sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA==" + }, "ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -7497,6 +7517,22 @@ "format-util": "^1.0.3" } }, + "openapi-backend": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/openapi-backend/-/openapi-backend-3.5.1.tgz", + "integrity": "sha512-aVScBkutF280uC4OouZkUThy58Ot3dk2K1HIll9zNsi1If0paU5enwTZKUkLQybSWkvq1MATddz5uz7J4h/sOg==", + "requires": { + "ajv": "^6.10.0", + "bath-es5": "^3.0.3", + "cookie": "^0.4.0", + "lodash": "^4.17.15", + "mock-json-schema": "^1.0.7", + "openapi-schema-validation": "^0.4.2", + "openapi-types": "^1.3.4", + "qs": "^6.9.3", + "swagger-parser": "^9.0.1" + } + }, "openapi-schema-validation": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/openapi-schema-validation/-/openapi-schema-validation-0.4.2.tgz", diff --git a/package.json b/package.json index 44a0d06ba..0b7b5a6df 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "@mojaloop/central-services-health": "10.6.0", "@mojaloop/central-services-logger": "10.6.0", "@mojaloop/central-services-metrics": "9.5.0", - "@mojaloop/central-services-shared": "10.6.1", + "@mojaloop/central-services-shared": "10.6.2", "@mojaloop/central-services-stream": "10.6.0", "@mojaloop/event-sdk": "10.6.0", "@mojaloop/forensic-logging-client": "8.3.0", @@ -105,6 +105,7 @@ "hapi-auth-basic": "5.0.0", "hapi-auth-bearer-token": "6.2.1", "hapi-swagger": "13.0.2", + "ilp-packet": "2.2.0", "knex": "0.21.2", "lodash": "4.17.19", "moment": "2.27.0", @@ -112,8 +113,7 @@ "npm-run-all": "4.1.5", "rc": "1.2.8", "require-glob": "3.2.0", - "uuid4": "2.0.2", - "ilp-packet": "2.2.0" + "uuid4": "2.0.2" }, "optionalDependencies": { "mysql": "2.18.1" diff --git a/src/handlers/bulk/get/handler.js b/src/handlers/bulk/get/handler.js index d99a67e5b..dd7e47e3a 100644 --- a/src/handlers/bulk/get/handler.js +++ b/src/handlers/bulk/get/handler.js @@ -101,7 +101,7 @@ const getBulkTransfer = async (error, messages) => { } // The SD says this should be 404 response which I think will not be constent with single transfers // which responds with CLIENT_ERROR instead - const participants = BulkTransferService.getParticipantsById(bulkTransferId) + const participants = await BulkTransferService.getParticipantsById(bulkTransferId) if (![participants.payeeFsp, participants.payerFsp].includes(message.value.from)) { Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackErrorNotBulkTransferParticipant--${actionLetter}2`)) const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.CLIENT_ERROR) @@ -111,16 +111,17 @@ const getBulkTransfer = async (error, messages) => { const isPayeeRequest = participants.payeeFsp === message.value.from Util.breadcrumb(location, { path: 'validationPassed' }) Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackMessage--${actionLetter}4`)) - const bulkTransfer = await BulkTransferService.getBulkTransferById(bulkTransferId) + const bulkTransferResult = await BulkTransferService.getBulkTransferById(bulkTransferId) + const bulkTransfer = isPayeeRequest ? bulkTransferResult.payeeBulkTransfer : bulkTransferResult.payerBulkTransfer let payload = { - bulkTransferState: bulkTransfer.bulkTransferStateId + bulkTransferState: bulkTransfer.bulkTransferState } - if (bulkTransfer.bulkTransferStateId !== Enum.Transfers.BulkProcessingState.PROCESSING) { + if (bulkTransfer.bulkTransferState !== Enum.Transfers.BulkTransferState.PROCESSING) { payload = { ...payload, - completedTimestamp: bulkTransfer.completedDate, - individualTransferResults: isPayeeRequest ? bulkTransfer.payeeBulkTransfer.individualTransferResults : bulkTransfer.payerBulkTransfer.individualTransferResults, - extensionList: isPayeeRequest ? bulkTransfer.payeeBulkTransfer.extensionList : bulkTransfer.payerBulkTransfer.extensionList + completedTimestamp: bulkTransfer.completedTimestamp, + individualTransferResults: bulkTransfer.individualTransferResults, + extensionList: bulkTransfer.extensionList } } message.value.content.payload = payload diff --git a/src/handlers/bulk/processing/handler.js b/src/handlers/bulk/processing/handler.js index 80542d550..feffbe750 100644 --- a/src/handlers/bulk/processing/handler.js +++ b/src/handlers/bulk/processing/handler.js @@ -300,21 +300,30 @@ const bulkProcessing = async (error, messages) => { await (new BulkTransferResultModel(payeeBulkResponse)).save() const payerParams = Util.clone(params) const payeeParams = Util.clone(params) + let payerPayload + let payeePayload + + if (action === Enum.Events.Event.Action.BULK_ABORT && params.decodedPayload.errorInformation) { + payerPayload = { bulkTransferId: payerBulkResponse.bulkTransferId, errorInformation: params.decodedPayload.errorInformation } + payeePayload = { bulkTransferId: payeeBulkResponse.bulkTransferId, errorInformation: params.decodedPayload.errorInformation } + } else { + payerPayload = Util.omitNil({ + bulkTransferId: payerBulkResponse.bulkTransferId, + bulkTransferState: payerBulkResponse.bulkTransferState, + completedTimestamp: payerBulkResponse.completedTimestamp, + extensionList: payerBulkResponse.extensionList + }) + payeePayload = Util.omitNil({ + bulkTransferId: payeeBulkResponse.bulkTransferId, + bulkTransferState: payeeBulkResponse.bulkTransferState, + completedTimestamp: payeeBulkResponse.completedTimestamp, + extensionList: payeeBulkResponse.extensionList + }) + } - const payerPayload = Util.omitNil({ - bulkTransferId: payerBulkResponse.bulkTransferId, - bulkTransferState: payerBulkResponse.bulkTransferState, - completedTimestamp: payerBulkResponse.completedTimestamp, - extensionList: payerBulkResponse.extensionList - }) const payerMetadata = Util.StreamingProtocol.createMetadataWithCorrelatedEvent(params.message.value.metadata.event.id, payerParams.message.value.metadata.type, payerParams.message.value.metadata.action, Enum.Events.EventStatus.SUCCESS) payerParams.message.value = Util.StreamingProtocol.createMessage(params.message.value.id, participants.payerFsp, payerBulkResponse.headers[normalizedKeys[Enum.Http.Headers.FSPIOP.SOURCE]], payerMetadata, payerBulkResponse.headers, payerPayload) - const payeePayload = Util.omitNil({ - bulkTransferId: payeeBulkResponse.bulkTransferId, - bulkTransferState: payeeBulkResponse.bulkTransferState, - completedTimestamp: payeeBulkResponse.completedTimestamp, - extensionList: payeeBulkResponse.extensionList - }) + const payeeMetadata = Util.StreamingProtocol.createMetadataWithCorrelatedEvent(params.message.value.metadata.event.id, payeeParams.message.value.metadata.type, payeeParams.message.value.metadata.action, Enum.Events.EventStatus.SUCCESS) payeeParams.message.value = Util.StreamingProtocol.createMessage(params.message.value.id, participants.payeeFsp, Enum.Http.Headers.FSPIOP.SWITCH.value, payeeMetadata, payeeBulkResponse.headers, payeePayload) if ([Enum.Events.Event.Action.BULK_TIMEOUT_RECEIVED, Enum.Events.Event.Action.BULK_TIMEOUT_RESERVED].includes(action)) { From f2a1affe3e5526e9af30936213902d3135746e8a Mon Sep 17 00:00:00 2001 From: Steven Oderayi Date: Wed, 15 Jul 2020 12:09:26 +0100 Subject: [PATCH 7/8] Fix unit test --- test/unit/handlers/bulk/get/handler.test.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/unit/handlers/bulk/get/handler.test.js b/test/unit/handlers/bulk/get/handler.test.js index e5f5b376e..dfab7abfb 100644 --- a/test/unit/handlers/bulk/get/handler.test.js +++ b/test/unit/handlers/bulk/get/handler.test.js @@ -369,7 +369,19 @@ Test('Bulk Transfer GET handler', getHandlerTest => { bulkTransferResult.bulkTransferStateId = Enum.Transfers.BulkProcessingState.PROCESSING bulkTransferResult.extensionList = [] BulkTransferModel.getById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferResult)) - BulkTransferService.getBulkTransferById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferResult)) + const bulkTransferResult2 = { + ...bulkTransferResult, + bulkTransferState: 'COMPLETED', + payerBulkTransfer: { + bulkTransferState: 'COMPLETED', + individualTransferResults: [] + }, + payeeBulkTransfer: { + bulkTransferState: 'COMPLETED', + individualTransferResults: [] + } + } + BulkTransferService.getBulkTransferById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferResult2)) try { await allBulkTransferHandlers.getBulkTransfer(null, localMessages) From 093adefe48db9ba756e255bcb99a1fb15bb46ea7 Mon Sep 17 00:00:00 2001 From: Steven Oderayi Date: Wed, 15 Jul 2020 12:33:02 +0100 Subject: [PATCH 8/8] ensure error code is returned as string and not number for bulk get --- src/domain/bulkTransfer/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/bulkTransfer/index.js b/src/domain/bulkTransfer/index.js index d6ba7b40a..d1a17c641 100644 --- a/src/domain/bulkTransfer/index.js +++ b/src/domain/bulkTransfer/index.js @@ -54,7 +54,7 @@ const getBulkTransferById = async (id) => { } if (transfer.errorCode) { result.errorInformation = { - errorCode: transfer.errorCode, + errorCode: transfer.errorCode.toString(), errorDescription: transfer.errorDescription } } else {