mirror of
https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-service.git
synced 2026-09-21 16:52:03 -07:00
Merge pull request #10 from Permissionless-Software-Foundation/dh-rate-limiter
feat(rate limiter): Created a rate limiter middleware
This commit is contained in:
Generated
+200
-53
@@ -3788,6 +3788,15 @@
|
||||
"mimic-response": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"cls-bluebird": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz",
|
||||
"integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=",
|
||||
"requires": {
|
||||
"is-bluebird": "^1.0.2",
|
||||
"shimmer": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
@@ -4875,6 +4884,11 @@
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"dottie": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz",
|
||||
"integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg=="
|
||||
},
|
||||
"drbg.js": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz",
|
||||
@@ -5110,9 +5124,9 @@
|
||||
}
|
||||
},
|
||||
"engine.io-client": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.1.tgz",
|
||||
"integrity": "sha512-oVu9kBkGbcggulyVF0kz6BV3ganqUeqXvD79WOFKa+11oK692w1NyFkuEj4xrkFRpZhn92QOqTk4RQq5LiBXbQ==",
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.2.tgz",
|
||||
"integrity": "sha512-QEqIp+gJ/kMHeUun7f5Vv3bteRHppHH/FMBQX/esFj/fuYfjyUKWGMo3VCvIP/V8bE9KcjHmRZrhIz2Z9oNsDA==",
|
||||
"requires": {
|
||||
"component-emitter": "~1.3.0",
|
||||
"component-inherit": "0.0.3",
|
||||
@@ -5123,15 +5137,8 @@
|
||||
"parseqs": "0.0.6",
|
||||
"parseuri": "0.0.6",
|
||||
"ws": "~7.4.2",
|
||||
"xmlhttprequest-ssl": "~1.5.4",
|
||||
"xmlhttprequest-ssl": "~1.6.2",
|
||||
"yeast": "0.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "7.4.4",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz",
|
||||
"integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"engine.io-parser": {
|
||||
@@ -6587,8 +6594,7 @@
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"resolved": "",
|
||||
"optional": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
@@ -6791,8 +6797,7 @@
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"resolved": "",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
@@ -7277,9 +7282,9 @@
|
||||
}
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.7.6",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
|
||||
"integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==",
|
||||
"version": "4.7.7",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
|
||||
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5",
|
||||
@@ -7480,9 +7485,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz",
|
||||
"integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg=="
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
|
||||
},
|
||||
"html-escaper": {
|
||||
"version": "2.0.2",
|
||||
@@ -7746,6 +7751,11 @@
|
||||
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
|
||||
"integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8="
|
||||
},
|
||||
"inflection": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz",
|
||||
"integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY="
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
@@ -10742,6 +10752,11 @@
|
||||
"binary-extensions": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-bluebird": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
|
||||
"integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
|
||||
},
|
||||
"is-boolean-object": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
|
||||
@@ -12031,6 +12046,16 @@
|
||||
"koa-send": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"koa2-ratelimit": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/koa2-ratelimit/-/koa2-ratelimit-0.9.0.tgz",
|
||||
"integrity": "sha512-gCjHnjm5Xgc+Qzx3Xr8qb0Iatd9Xw4YC2ZemIpdbkFTpNjfJcoI1Df5lS/H0K+NeSxggxYN0K23ToPS/SPN/Gg==",
|
||||
"requires": {
|
||||
"mongoose": "^5.5.13",
|
||||
"promise-redis": "0.0.5",
|
||||
"sequelize": "^5.8.7"
|
||||
}
|
||||
},
|
||||
"kuler": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
|
||||
@@ -13779,9 +13804,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash._baseiteratee": {
|
||||
"version": "4.7.0",
|
||||
@@ -14343,8 +14368,7 @@
|
||||
"dependencies": {
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
|
||||
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
|
||||
"resolved": "",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-package-data": {
|
||||
@@ -14675,6 +14699,14 @@
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.33",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz",
|
||||
"integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
}
|
||||
},
|
||||
"mongodb": {
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz",
|
||||
@@ -15036,9 +15068,9 @@
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||
},
|
||||
"neo-async": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
|
||||
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
},
|
||||
"nerf-dart": {
|
||||
@@ -18702,6 +18734,15 @@
|
||||
"is-promise": "~1"
|
||||
}
|
||||
},
|
||||
"promise-redis": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/promise-redis/-/promise-redis-0.0.5.tgz",
|
||||
"integrity": "sha1-PjziqtkS6SfJam7O2NGw+YJmZgk=",
|
||||
"requires": {
|
||||
"redis": "*",
|
||||
"redis-commands": "*"
|
||||
}
|
||||
},
|
||||
"promise-timeout": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz",
|
||||
@@ -19066,6 +19107,42 @@
|
||||
"esprima": "~4.0.0"
|
||||
}
|
||||
},
|
||||
"redis": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz",
|
||||
"integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==",
|
||||
"requires": {
|
||||
"denque": "^1.5.0",
|
||||
"redis-commands": "^1.7.0",
|
||||
"redis-errors": "^1.2.0",
|
||||
"redis-parser": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"denque": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
|
||||
"integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"redis-commands": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz",
|
||||
"integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ=="
|
||||
},
|
||||
"redis-errors": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||
"integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60="
|
||||
},
|
||||
"redis-parser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||
"integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
|
||||
"requires": {
|
||||
"redis-errors": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"regexp-clone": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
|
||||
@@ -19301,6 +19378,14 @@
|
||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
|
||||
},
|
||||
"retry-as-promised": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz",
|
||||
"integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==",
|
||||
"requires": {
|
||||
"any-promise": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"reusify": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
@@ -19769,6 +19854,53 @@
|
||||
"upper-case-first": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"sequelize": {
|
||||
"version": "5.22.4",
|
||||
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.22.4.tgz",
|
||||
"integrity": "sha512-xFQQ38HPg7EyDRDA+NdzMSRWbo9m6Z/RxpjnkBl3ggyQG+jRrup48x0jaw4Ox42h56wFnXOBC2NZOkTJfZeWCw==",
|
||||
"requires": {
|
||||
"bluebird": "^3.5.0",
|
||||
"cls-bluebird": "^2.1.0",
|
||||
"debug": "^4.1.1",
|
||||
"dottie": "^2.0.0",
|
||||
"inflection": "1.12.0",
|
||||
"lodash": "^4.17.15",
|
||||
"moment": "^2.24.0",
|
||||
"moment-timezone": "^0.5.21",
|
||||
"retry-as-promised": "^3.2.0",
|
||||
"semver": "^6.3.0",
|
||||
"sequelize-pool": "^2.3.0",
|
||||
"toposort-class": "^1.0.1",
|
||||
"uuid": "^3.3.3",
|
||||
"validator": "^10.11.0",
|
||||
"wkx": "^0.4.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"sequelize-pool": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz",
|
||||
"integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA=="
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
|
||||
@@ -19820,6 +19952,11 @@
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
||||
},
|
||||
"shimmer": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
|
||||
"integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
|
||||
},
|
||||
"side-channel": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||
@@ -20028,9 +20165,9 @@
|
||||
}
|
||||
},
|
||||
"engine.io-client": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.1.3.tgz",
|
||||
"integrity": "sha512-C3JYYyvna0FvSKOWGWpo0/EQ6MayO8uEKam1oedLZRpxLego9Fk6K3UH/Phieu1xPHauM7YqAygJ+6SraVc0Qg==",
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.1.4.tgz",
|
||||
"integrity": "sha512-843fqAdKeUMFqKi1sSjnR11tJ4wi8sIefu6+JC1OzkkJBmjtc/gM/rZ53tJfu5Iae/3gApm5veoS+v+gtT0+Fg==",
|
||||
"requires": {
|
||||
"base64-arraybuffer": "0.1.4",
|
||||
"component-emitter": "~1.3.0",
|
||||
@@ -20040,7 +20177,7 @@
|
||||
"parseqs": "0.0.6",
|
||||
"parseuri": "0.0.6",
|
||||
"ws": "~7.4.2",
|
||||
"xmlhttprequest-ssl": "~1.5.4",
|
||||
"xmlhttprequest-ssl": "~1.6.2",
|
||||
"yeast": "0.1.2"
|
||||
}
|
||||
},
|
||||
@@ -20061,6 +20198,11 @@
|
||||
"component-emitter": "~1.3.0",
|
||||
"debug": "~4.3.1"
|
||||
}
|
||||
},
|
||||
"xmlhttprequest-ssl": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.2.tgz",
|
||||
"integrity": "sha512-tYOaldF/0BLfKuoA39QMwD4j2m8lq4DIncqj1yuNELX4vz9+z/ieG/vwmctjJce+boFHXstqhWnHSxc4W8f4qg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -21081,6 +21223,11 @@
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"toposort-class": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
|
||||
"integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
|
||||
},
|
||||
"touch": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
||||
@@ -21269,24 +21416,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.1.tgz",
|
||||
"integrity": "sha512-W7KxyzeaQmZvUFbGj4+YFshhVrMBGSg2IbcYAjGWGvx8DHvJMclbTDMpffdxFUGPBHjIytk7KJUR/KUXstUGDw==",
|
||||
"version": "3.13.5",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.5.tgz",
|
||||
"integrity": "sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"commander": "~2.20.3",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
"optional": true
|
||||
},
|
||||
"uid-safe": {
|
||||
"version": "2.1.5",
|
||||
@@ -21534,6 +21668,11 @@
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"validator": {
|
||||
"version": "10.11.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
|
||||
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
|
||||
},
|
||||
"varint": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz",
|
||||
@@ -21764,6 +21903,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"wkx": {
|
||||
"version": "0.4.8",
|
||||
"resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz",
|
||||
"integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
@@ -21870,9 +22017,9 @@
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
|
||||
},
|
||||
"xmlhttprequest-ssl": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
|
||||
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.2.tgz",
|
||||
"integrity": "sha512-tYOaldF/0BLfKuoA39QMwD4j2m8lq4DIncqj1yuNELX4vz9+z/ieG/vwmctjJce+boFHXstqhWnHSxc4W8f4qg=="
|
||||
},
|
||||
"xor-distance": {
|
||||
"version": "2.0.0",
|
||||
|
||||
+2
-11
@@ -11,22 +11,12 @@
|
||||
"test:unit:rest": "export SVC_ENV=test && mocha --exit --timeout 15000 test/unit/rest-api/",
|
||||
"test:unit:jsonrpc": "export SVC_ENV=test && mocha --exit --timeout 15000 test/unit/json-rpc/",
|
||||
"test:e2e:auto": "export SVC_ENV=test && mocha --exit --timeout 15000 test/e2e/automated/",
|
||||
"test:temp": "export SVC_ENV=test && mocha --exit --timeout 15000 -g '#rate-limit' test/unit/json-rpc/",
|
||||
"lint": "standard --env mocha --fix",
|
||||
"docs": "./node_modules/.bin/apidoc -i src/ -o docs",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||
"coverage:report": "export SVC_ENV=test && nyc --reporter=html mocha --exit --timeout 15000 test/unit/biz-logic/ test/unit/json-rpc/ test/unit/rest-api/ test/e2e/automated/"
|
||||
},
|
||||
"keywords": [
|
||||
"koa-api-boilerplate",
|
||||
"api",
|
||||
"koa",
|
||||
"koa2",
|
||||
"boilerplate",
|
||||
"es6",
|
||||
"mongoose",
|
||||
"passportjs",
|
||||
"apidoc"
|
||||
],
|
||||
"author": "Chris Troutner <chris.troutner@gmail.com>",
|
||||
"license": "MIT",
|
||||
"apidoc": {
|
||||
@@ -53,6 +43,7 @@
|
||||
"koa-passport": "^4.1.3",
|
||||
"koa-router": "^10.0.0",
|
||||
"koa-static": "^5.0.0",
|
||||
"koa2-ratelimit": "^0.9.0",
|
||||
"line-reader": "^0.4.0",
|
||||
"mongoose": "^5.11.15",
|
||||
"nodemailer": "^6.4.17",
|
||||
|
||||
@@ -9,6 +9,7 @@ const jsonrpc = require('jsonrpc-lite')
|
||||
// const AuthLib = require('../../lib/auth')
|
||||
const UserLib = require('../../lib/users')
|
||||
const wlogger = require('../../lib/wlogger')
|
||||
const RateLimit = require('../rate-limit')
|
||||
|
||||
class AuthRPC {
|
||||
constructor (localConfig) {
|
||||
@@ -16,6 +17,7 @@ class AuthRPC {
|
||||
// this.authLib = new AuthLib()
|
||||
this.jsonrpc = jsonrpc
|
||||
this.userLib = new UserLib()
|
||||
this.rateLimit = new RateLimit()
|
||||
}
|
||||
|
||||
// Top-level router for this library. All other methods in this class are for
|
||||
@@ -32,6 +34,7 @@ class AuthRPC {
|
||||
// Route the call based on the requested endpoint.
|
||||
switch (endpoint) {
|
||||
case 'authUser':
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.authUser(rpcData)
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -51,6 +51,10 @@ class JSONRPC {
|
||||
return
|
||||
}
|
||||
|
||||
// Added the property "from" to the parsedData object;
|
||||
// necessary for calculating rate limits (based on the IPFS ID).
|
||||
parsedData.from = from
|
||||
|
||||
// Default return string
|
||||
let retObj = _this.defaultResponse()
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Rate limit
|
||||
*/
|
||||
/* eslint no-useless-catch: 0 */
|
||||
|
||||
// Local libraries
|
||||
const RateLimitLib = require('koa2-ratelimit').RateLimit
|
||||
|
||||
class RateLimit {
|
||||
constructor (options) {
|
||||
// Encapsulate dependencies
|
||||
this.RateLimitLib = RateLimitLib
|
||||
|
||||
// Set default rate limit options.
|
||||
this.defaultOptions = {
|
||||
interval: { min: 1 },
|
||||
max: 60,
|
||||
onLimitReached: this.onLimitReached
|
||||
}
|
||||
|
||||
// ctx obj
|
||||
this.context = {
|
||||
state: {
|
||||
user: ''
|
||||
},
|
||||
request: {
|
||||
ip: ''
|
||||
},
|
||||
user: '',
|
||||
set: () => {}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`this.defaultOptions: ${JSON.stringify(this.defaultOptions, null, 2)}`
|
||||
)
|
||||
console.log(`options: ${JSON.stringify(options, null, 2)}`)
|
||||
|
||||
// Set rate limit settings. Default values are overwritten if user passes
|
||||
// in an options object.
|
||||
this.rateLimitOptions = Object.assign({}, this.defaultOptions, options)
|
||||
console.log(
|
||||
`this.rateLimitOptions: ${JSON.stringify(this.rateLimitOptions, null, 2)}`
|
||||
)
|
||||
this.rateLimit = this.RateLimitLib.middleware(this.rateLimitOptions)
|
||||
}
|
||||
|
||||
// This function is called when the user hits their rate limits.
|
||||
onLimitReached () {
|
||||
try {
|
||||
const error = new Error() // Establish provided options as the default options.
|
||||
error.message = 'Too many requests, please try again later.'
|
||||
error.status = 429
|
||||
throw error
|
||||
} catch (error) {
|
||||
// console.log("Error in onLimitReached()", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// This is the middleware function called by the router.
|
||||
async limiter (from) {
|
||||
try {
|
||||
if (!from || typeof from !== 'string') {
|
||||
throw new Error('from must be a string')
|
||||
}
|
||||
|
||||
// Set context.limiter
|
||||
// This overrides the default koa behavior and adapts the rate limiter
|
||||
// to work with the JSON RPC over IPFS.
|
||||
this.context.state.user = from
|
||||
this.context.request.ip = from
|
||||
this.context.user = from
|
||||
|
||||
await this.rateLimit(this.context, () => {})
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('Error in rate-limit.js/limiter()')
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RateLimit
|
||||
@@ -8,6 +8,7 @@ const jsonrpc = require('jsonrpc-lite')
|
||||
// Local libraries
|
||||
const UserLib = require('../../lib/users')
|
||||
const Validators = require('../validators')
|
||||
const RateLimit = require('../rate-limit')
|
||||
|
||||
class UserRPC {
|
||||
constructor (localConfig) {
|
||||
@@ -15,6 +16,7 @@ class UserRPC {
|
||||
this.userLib = new UserLib()
|
||||
this.jsonrpc = jsonrpc
|
||||
this.validators = new Validators()
|
||||
this.rateLimit = new RateLimit()
|
||||
}
|
||||
|
||||
// Top-level router for this library. All other methods in this class are for
|
||||
@@ -31,22 +33,27 @@ class UserRPC {
|
||||
// Route the call based on the value of the method property.
|
||||
switch (endpoint) {
|
||||
case 'createUser':
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.createUser(rpcData)
|
||||
|
||||
case 'getAllUsers':
|
||||
await this.validators.ensureUser(rpcData)
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.getAll(rpcData)
|
||||
|
||||
case 'getUser':
|
||||
user = await this.validators.ensureUser(rpcData)
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.getUser(rpcData, user)
|
||||
|
||||
case 'updateUser':
|
||||
user = await this.validators.ensureTargetUserOrAdmin(rpcData)
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.updateUser(rpcData, user)
|
||||
|
||||
case 'deleteUser':
|
||||
user = await this.validators.ensureTargetUserOrAdmin(rpcData)
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.deleteUser(rpcData, user)
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -55,7 +62,7 @@ class UserRPC {
|
||||
|
||||
return {
|
||||
success: false,
|
||||
status: 500,
|
||||
status: err.status || 500,
|
||||
message: err.message,
|
||||
endpoint
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ process.env.SVC_ENV = 'test'
|
||||
// Local libraries
|
||||
const config = require('../../../config')
|
||||
const AuthRPC = require('../../../src/rpc/auth')
|
||||
const RateLimit = require('../../../src/rpc/rate-limit')
|
||||
const UserLib = require('../../../src/lib/users')
|
||||
const userLib = new UserLib()
|
||||
|
||||
@@ -48,6 +49,7 @@ describe('#AuthRPC', () => {
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
uut = new AuthRPC()
|
||||
uut.rateLimit = new RateLimit({ max: 100 })
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
@@ -71,6 +73,7 @@ describe('#AuthRPC', () => {
|
||||
const authCall = jsonrpc.request(id, 'auth', { endpoint: 'authUser' })
|
||||
const jsonStr = JSON.stringify(authCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.authRouter(rpcData)
|
||||
|
||||
@@ -87,6 +90,7 @@ describe('#AuthRPC', () => {
|
||||
const authCall = jsonrpc.request(id, 'auth', { endpoint: 'authUser' })
|
||||
const jsonStr = JSON.stringify(authCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.authRouter(rpcData)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ process.env.SVC_ENV = 'test'
|
||||
// Local libraries
|
||||
const config = require('../../../config')
|
||||
const UserRPC = require('../../../src/rpc/users')
|
||||
const RateLimit = require('../../../src/rpc/rate-limit')
|
||||
const UserModel = require('../../../src/models/users')
|
||||
|
||||
describe('#UserRPC', () => {
|
||||
@@ -40,6 +41,7 @@ describe('#UserRPC', () => {
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
uut = new UserRPC()
|
||||
uut.rateLimit = new RateLimit({ max: 100 })
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
@@ -120,6 +122,7 @@ describe('#UserRPC', () => {
|
||||
const userCall = jsonrpc.request(id, 'users', { endpoint: 'createUser' })
|
||||
const jsonStr = JSON.stringify(userCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.userRouter(rpcData)
|
||||
|
||||
@@ -139,9 +142,10 @@ describe('#UserRPC', () => {
|
||||
})
|
||||
const jsonStr = JSON.stringify(userCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.userRouter(rpcData)
|
||||
|
||||
console.log('result', result)
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
@@ -159,6 +163,7 @@ describe('#UserRPC', () => {
|
||||
})
|
||||
const jsonStr = JSON.stringify(userCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.userRouter(rpcData)
|
||||
// console.log('result: ', result)
|
||||
@@ -179,7 +184,7 @@ describe('#UserRPC', () => {
|
||||
})
|
||||
const jsonStr = JSON.stringify(userCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
|
||||
rpcData.from = 'Origin request'
|
||||
const result = await uut.userRouter(rpcData)
|
||||
|
||||
assert.equal(result, true)
|
||||
@@ -199,6 +204,7 @@ describe('#UserRPC', () => {
|
||||
})
|
||||
const jsonStr = JSON.stringify(userCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.userRouter(rpcData)
|
||||
// console.log('result: ', result)
|
||||
@@ -216,6 +222,7 @@ describe('#UserRPC', () => {
|
||||
const userCall = jsonrpc.request(id, 'users', { endpoint: 'createUser' })
|
||||
const jsonStr = JSON.stringify(userCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.userRouter(rpcData)
|
||||
// console.log('result: ', result)
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
Unit tests for the JSON RPC validator middleware.
|
||||
|
||||
TODO: ensureTargetUserOrAdmin: it should exit quietly if user is an admin.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
const sinon = require('sinon')
|
||||
const assert = require('chai').assert
|
||||
|
||||
// Set the environment variable to signal this is a test.
|
||||
process.env.SVC_ENV = 'test'
|
||||
|
||||
// Local libraries
|
||||
const RateLimit = require('../../../src/rpc/rate-limit')
|
||||
|
||||
describe('#rate-limit', () => {
|
||||
let uut
|
||||
let sandbox
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
uut = new RateLimit()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should use the options provided', async () => {
|
||||
try {
|
||||
const options = {
|
||||
interval: { min: 10 },
|
||||
delayAfter: 1,
|
||||
timeWait: { sec: 5 },
|
||||
max: 2,
|
||||
onLimitReached: () => {
|
||||
throw new Error('custom message error')
|
||||
}
|
||||
}
|
||||
const _uut = new RateLimit(options)
|
||||
|
||||
// Assert options
|
||||
assert.equal(_uut.rateLimitOptions.interval.min, options.interval.min)
|
||||
assert.equal(_uut.rateLimitOptions.delayAfter, options.delayAfter)
|
||||
assert.equal(_uut.rateLimitOptions.timeWait.sec, options.timeWait.sec)
|
||||
|
||||
const from = 'constructor test'
|
||||
const firstRequest = await _uut.limiter(from)
|
||||
assert.isTrue(firstRequest)
|
||||
|
||||
const secondRequest = await _uut.limiter(from)
|
||||
assert.isTrue(secondRequest)
|
||||
|
||||
await _uut.limiter(from)
|
||||
assert.fail('unexpected error')
|
||||
} catch (error) {
|
||||
assert.include(error.message, 'custom message error')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#onLimitReached', () => {
|
||||
it('should throw error', async () => {
|
||||
try {
|
||||
uut.onLimitReached()
|
||||
assert.fail('unexpected error')
|
||||
} catch (error) {
|
||||
assert.equal(error.status, 429)
|
||||
assert.include(
|
||||
error.message,
|
||||
'Too many requests, please try again later.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#limiter', () => {
|
||||
it('should throw error if "from" input is not provider', async () => {
|
||||
try {
|
||||
await uut.limiter()
|
||||
assert.fail('unexpected error')
|
||||
} catch (error) {
|
||||
assert.include(error.message, 'from must be a string')
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw error 429', async () => {
|
||||
try {
|
||||
const _uut = new RateLimit({ max: 1 })
|
||||
const from = 'Origin request'
|
||||
|
||||
const firstRequest = await _uut.limiter(from)
|
||||
assert.isTrue(firstRequest)
|
||||
|
||||
const secondRequest = await _uut.limiter(from)
|
||||
assert.isTrue(secondRequest)
|
||||
|
||||
await _uut.limiter(from)
|
||||
assert.fail('unexpected error')
|
||||
} catch (error) {
|
||||
assert.include(
|
||||
error.message,
|
||||
'Too many requests, please try again later.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user