From 4c0072949ea43327431cb424f75e498c8bf24ac8 Mon Sep 17 00:00:00 2001 From: AnnoyingRains <35289650+AnnoyingRain5@users.noreply.github.com> Date: Tue, 24 Aug 2021 15:42:23 +1000 Subject: [PATCH 001/105] Added dockerfile to allow deploying via docker --- dockerfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 dockerfile diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..0d34ca6 --- /dev/null +++ b/dockerfile @@ -0,0 +1,16 @@ +# syntax=docker/dockerfile:1 +FROM node:12-alpine +EXPOSE 7070/tcp +RUN apk add --no-cache npm python3 make g++ +WORKDIR /app +COPY . . +RUN mkdir /config +VOLUME /config +WORKDIR /app/src +RUN mv example.config.json /config/config.json +RUN mv example.servers.json /config/servers.json +RUN npm install +WORKDIR /app +RUN echo "cp /config/config.json /app/src/config.json && cp /config/servers.json /app/src/servers.json && npm start" > startup.sh +RUN chmod +x startup.sh +ENTRYPOINT "/app/startup.sh" \ No newline at end of file From a38af2825d460d756e6b78dcd9835c9eee2ee1d5 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 08:33:35 -0400 Subject: [PATCH 002/105] Removed older dockerfile --- dockerfile | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 dockerfile diff --git a/dockerfile b/dockerfile deleted file mode 100644 index 0d34ca6..0000000 --- a/dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM node:12-alpine -EXPOSE 7070/tcp -RUN apk add --no-cache npm python3 make g++ -WORKDIR /app -COPY . . -RUN mkdir /config -VOLUME /config -WORKDIR /app/src -RUN mv example.config.json /config/config.json -RUN mv example.servers.json /config/servers.json -RUN npm install -WORKDIR /app -RUN echo "cp /config/config.json /app/src/config.json && cp /config/servers.json /app/src/servers.json && npm start" > startup.sh -RUN chmod +x startup.sh -ENTRYPOINT "/app/startup.sh" \ No newline at end of file From b2c1d73e51cb1ec3f7feaba72b4edfbc46f67ff0 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 08:36:57 -0400 Subject: [PATCH 003/105] Don't use `this` in database.js --- src/database.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/database.js b/src/database.js index dd9a306..20186bb 100644 --- a/src/database.js +++ b/src/database.js @@ -48,14 +48,14 @@ async function getUserByPID(pid) { async function doesUserExist(username) { verifyConnected(); - return !!await this.getUserByUsername(username); + return !!await getUserByUsername(username); } async function getUserBasic(token) { verifyConnected(); const [username, password] = Buffer.from(token, 'base64').toString().split(' '); - const user = await this.getUserByUsername(username); + const user = await getUserByUsername(username); if (!user) { return null; @@ -92,7 +92,7 @@ async function getUserBearer(token) { async function getUserProfileJSONByPID(pid) { verifyConnected(); - const user = await this.getUserByPID(pid); + const user = await getUserByPID(pid); const device = user.get('devices')[0]; // Just grab the first device let device_attributes; From 81585da939b043d38137c40ea8a5de3171fb7fe0 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 08:41:02 -0400 Subject: [PATCH 004/105] Made getUserBasic spec issue more clear --- src/database.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/database.js b/src/database.js index 20186bb..1f00cbf 100644 --- a/src/database.js +++ b/src/database.js @@ -54,6 +54,8 @@ async function doesUserExist(username) { async function getUserBasic(token) { verifyConnected(); + // Wii U sends Basic auth as `username password`, where the password may not have spaces + // This is not to spec, but that is the consoles fault not ours const [username, password] = Buffer.from(token, 'base64').toString().split(' '); const user = await getUserByUsername(username); From 71f171e51d8e47d4db6a9cbc3f29ccbad1d8dd84 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:22:47 -0400 Subject: [PATCH 005/105] Return error on XML parse error --- src/middleware/xml-parser.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/middleware/xml-parser.js b/src/middleware/xml-parser.js index 5ed1578..2ab8ff7 100644 --- a/src/middleware/xml-parser.js +++ b/src/middleware/xml-parser.js @@ -22,7 +22,17 @@ function XMLMiddleware(request, response, next) { request.body = xmlParser(body); request.body = request.body.toObject(); } catch (error) { - return next(); + response.status(401); + + // TODO: This is not a real error code, check to see if better one exists + return response.send(xmlbuilder.create({ + errors: { + error: { + code: '0004', + message: 'XML parse error' + } + } + }).end()); } next(); From 14b2c73986fb6f2ad9fb5f6835860c9f506981eb Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:23:35 -0400 Subject: [PATCH 006/105] Added start of redis cache --- package-lock.json | 158 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + src/cache.js | 97 ++++++++++++++++++++++++++++ src/server.js | 13 ++-- 4 files changed, 265 insertions(+), 4 deletions(-) create mode 100644 src/cache.js diff --git a/package-lock.json b/package-lock.json index 38af0d3..e9214bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "morgan": "^1.9.1", "multer": "^1.4.3", "nodemailer": "^6.4.2", + "redis": "^4.3.1", "tga": "^1.0.4", "xmlbuilder": "^13.0.2", "xmlbuilder2": "0.0.4" @@ -158,6 +159,64 @@ "node": ">=6.0" } }, + "node_modules/@redis/bloom": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz", + "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/client": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.3.0.tgz", + "integrity": "sha512-XCFV60nloXAefDsPnYMjHGtvbtHR8fV5Om8cQ0JYqTNbWcQo/4AryzJ2luRj4blveWazRK/j40gES8M7Cp6cfQ==", + "dependencies": { + "cluster-key-slot": "1.1.0", + "generic-pool": "3.8.2", + "yallist": "4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@redis/client/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@redis/graph": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz", + "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/json": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", + "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/search": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", + "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/time-series": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", + "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, "node_modules/@sindresorhus/is": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", @@ -679,6 +738,14 @@ "mimic-response": "^1.0.0" } }, + "node_modules/cluster-key-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", + "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -1466,6 +1533,14 @@ "wide-align": "^1.1.0" } }, + "node_modules/generic-pool": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", + "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==", + "engines": { + "node": ">= 4" + } + }, "node_modules/get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -2820,6 +2895,19 @@ "util-deprecate": "~1.0.1" } }, + "node_modules/redis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.3.1.tgz", + "integrity": "sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA==", + "dependencies": { + "@redis/bloom": "1.0.2", + "@redis/client": "1.3.0", + "@redis/graph": "1.0.1", + "@redis/json": "1.0.4", + "@redis/search": "1.1.0", + "@redis/time-series": "1.0.3" + } + }, "node_modules/regexp-clone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", @@ -3626,6 +3714,53 @@ } } }, + "@redis/bloom": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz", + "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==", + "requires": {} + }, + "@redis/client": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.3.0.tgz", + "integrity": "sha512-XCFV60nloXAefDsPnYMjHGtvbtHR8fV5Om8cQ0JYqTNbWcQo/4AryzJ2luRj4blveWazRK/j40gES8M7Cp6cfQ==", + "requires": { + "cluster-key-slot": "1.1.0", + "generic-pool": "3.8.2", + "yallist": "4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "@redis/graph": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz", + "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==", + "requires": {} + }, + "@redis/json": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", + "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", + "requires": {} + }, + "@redis/search": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", + "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", + "requires": {} + }, + "@redis/time-series": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", + "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "requires": {} + }, "@sindresorhus/is": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", @@ -4059,6 +4194,11 @@ "mimic-response": "^1.0.0" } }, + "cluster-key-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", + "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -4701,6 +4841,11 @@ "wide-align": "^1.1.0" } }, + "generic-pool": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", + "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==" + }, "get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -5752,6 +5897,19 @@ "util-deprecate": "~1.0.1" } }, + "redis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.3.1.tgz", + "integrity": "sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA==", + "requires": { + "@redis/bloom": "1.0.2", + "@redis/client": "1.3.0", + "@redis/graph": "1.0.1", + "@redis/json": "1.0.4", + "@redis/search": "1.1.0", + "@redis/time-series": "1.0.3" + } + }, "regexp-clone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", diff --git a/package.json b/package.json index 5235b5e..089fa2e 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "morgan": "^1.9.1", "multer": "^1.4.3", "nodemailer": "^6.4.2", + "redis": "^4.3.1", "tga": "^1.0.4", "xmlbuilder": "^13.0.2", "xmlbuilder2": "0.0.4" diff --git a/src/cache.js b/src/cache.js new file mode 100644 index 0000000..0b753f4 --- /dev/null +++ b/src/cache.js @@ -0,0 +1,97 @@ +const redis = require('redis'); +let client; + +async function connect() { + client = redis.createClient(); + client.on('error', (err) => console.log('Redis Client Error', err)); + + await client.connect(); +} + +// NEX server cache functions + +async function getNEXPublicCert(name) { + return Buffer.from(await client.get(`nex:${name}:public_cert`)); +} + +async function getNEXPrivateCert(name) { + return Buffer.from(await client.get(`nex:${name}:private_cert`)); +} + +async function getNEXSecretKey(name) { + return Buffer.from(await client.get(`nex:${name}:secret_key`)); +} + +async function getNEXAESKey(name) { + return Buffer.from(await client.get(`nex:${name}:aes_key`)); +} + +async function setNEXPublicCert(name, value) { + await client.set(`nex:${name}:public_cert`, value); +} + +async function setNEXPrivateCert(name, value) { + await client.set(`nex:${name}:private_cert`, value); +} + +async function setNEXSecretKey(name, value) { + await client.set(`nex:${name}:secret_key`, value); +} + +async function setNEXAESKey(name, value) { + await client.set(`nex:${name}:aes_key`, value); +} + +// 3rd party service cache functions + +async function getServicePublicCert(name) { + return Buffer.from(await client.get(`service:${name}:public_cert`)); +} + +async function getServicePrivateCert(name) { + return Buffer.from(await client.get(`service:${name}:private_cert`)); +} + +async function getServiceSecretKey(name) { + return Buffer.from(await client.get(`service:${name}:secret_key`)); +} + +async function getServiceAESKey(name) { + return Buffer.from(await client.get(`service:${name}:aes_key`)); +} + +async function setServicePublicCert(name, value) { + await client.set(`service:${name}:public_cert`, value); +} + +async function setServicePrivateCert(name, value) { + await client.set(`service:${name}:private_cert`, value); +} + +async function setServiceSecretKey(name, value) { + await client.set(`service:${name}:secret_key`, value); +} + +async function setServiceAESKey(name, value) { + await client.set(`service:${name}:aes_key`, value); +} + +module.exports = { + connect, + getNEXPublicCert, + getNEXPrivateCert, + getNEXSecretKey, + getNEXAESKey, + setNEXPublicCert, + setNEXPrivateCert, + setNEXSecretKey, + setNEXAESKey, + getServicePublicCert, + getServicePrivateCert, + getServiceSecretKey, + getServiceAESKey, + setServicePublicCert, + setServicePrivateCert, + setServiceSecretKey, + setServiceAESKey, +}; \ No newline at end of file diff --git a/src/server.js b/src/server.js index 779221e..be724af 100644 --- a/src/server.js +++ b/src/server.js @@ -3,6 +3,7 @@ process.title = 'Pretendo - Account'; const express = require('express'); const morgan = require('morgan'); const xmlparser = require('./middleware/xml-parser'); +const cache = require('./cache'); const database = require('./database'); const util = require('./util'); const logger = require('../logger'); @@ -70,11 +71,15 @@ app.use((error, request, response) => { }); }); -// Starts the server -logger.info('Starting server'); +async function main() { + // Starts the server + logger.info('Starting server'); + + await database.connect(); + await cache.connect(); -database.connect().then(() => { app.listen(port, () => { logger.success(`Server started on port ${port}`); }); -}); \ No newline at end of file +} + From 9e921ea9eb2086e6ca67781ce9d351735a5d0659 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:28:24 -0400 Subject: [PATCH 007/105] Removed extar tab --- src/cache.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cache.js b/src/cache.js index 0b753f4..a17f076 100644 --- a/src/cache.js +++ b/src/cache.js @@ -11,7 +11,7 @@ async function connect() { // NEX server cache functions async function getNEXPublicCert(name) { - return Buffer.from(await client.get(`nex:${name}:public_cert`)); + return Buffer.from(await client.get(`nex:${name}:public_cert`)); } async function getNEXPrivateCert(name) { From c2a8d3a4bd99b196dcc9e082d00f3f6ef7b766bf Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:31:13 -0400 Subject: [PATCH 008/105] Added null check to cache --- src/cache.js | 64 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/src/cache.js b/src/cache.js index a17f076..6a708bf 100644 --- a/src/cache.js +++ b/src/cache.js @@ -11,19 +11,43 @@ async function connect() { // NEX server cache functions async function getNEXPublicCert(name) { - return Buffer.from(await client.get(`nex:${name}:public_cert`)); + const publicCert = await client.get(`nex:${name}:public_cert`); + + if (publicCert !== null) { + return Buffer.from(publicCert); + } else { + return publicCert; + } } async function getNEXPrivateCert(name) { - return Buffer.from(await client.get(`nex:${name}:private_cert`)); + const privateCert = await client.get(`nex:${name}:private_cert`); + + if (privateCert !== null) { + return Buffer.from(privateCert); + } else { + return privateCert; + } } async function getNEXSecretKey(name) { - return Buffer.from(await client.get(`nex:${name}:secret_key`)); + const secretKey = await client.get(`nex:${name}:secret_key`); + + if (secretKey !== null) { + return Buffer.from(secretKey); + } else { + return secretKey; + } } async function getNEXAESKey(name) { - return Buffer.from(await client.get(`nex:${name}:aes_key`)); + const aesKey = await client.get(`nex:${name}:aes_key`); + + if (aesKey !== null) { + return Buffer.from(aesKey); + } else { + return aesKey; + } } async function setNEXPublicCert(name, value) { @@ -45,19 +69,43 @@ async function setNEXAESKey(name, value) { // 3rd party service cache functions async function getServicePublicCert(name) { - return Buffer.from(await client.get(`service:${name}:public_cert`)); + const publicCert = await client.get(`service:${name}:public_cert`); + + if (publicCert !== null) { + return Buffer.from(publicCert); + } else { + return publicCert; + } } async function getServicePrivateCert(name) { - return Buffer.from(await client.get(`service:${name}:private_cert`)); + const privateCert = await client.get(`service:${name}:private_cert`); + + if (privateCert !== null) { + return Buffer.from(privateCert); + } else { + return privateCert; + } } async function getServiceSecretKey(name) { - return Buffer.from(await client.get(`service:${name}:secret_key`)); + const secretKey = await client.get(`service:${name}:secret_key`); + + if (secretKey !== null) { + return Buffer.from(secretKey); + } else { + return secretKey; + } } async function getServiceAESKey(name) { - return Buffer.from(await client.get(`service:${name}:aes_key`)); + const aesKey = await client.get(`service:${name}:aes_key`); + + if (aesKey !== null) { + return Buffer.from(aesKey); + } else { + return aesKey; + } } async function setServicePublicCert(name, value) { From 8af546714e56b0841d52379a439d732c590a6ad2 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:36:18 -0400 Subject: [PATCH 009/105] Removed duplicate code from cache --- src/cache.js | 92 +++++++++++++++++----------------------------------- 1 file changed, 29 insertions(+), 63 deletions(-) diff --git a/src/cache.js b/src/cache.js index 6a708bf..d870071 100644 --- a/src/cache.js +++ b/src/cache.js @@ -8,120 +8,86 @@ async function connect() { await client.connect(); } -// NEX server cache functions +async function setCachedFile(type, name, fileName, value) { + await client.set(`${type}:${name}:${fileName}`, value); +} -async function getNEXPublicCert(name) { - const publicCert = await client.get(`nex:${name}:public_cert`); +async function getCachedFile(type, name, fileName) { + const cachedFile = await client.get(`${type}:${name}:${fileName}`); - if (publicCert !== null) { - return Buffer.from(publicCert); + if (cachedFile !== null) { + return Buffer.from(cachedFile); } else { - return publicCert; + return cachedFile; } } -async function getNEXPrivateCert(name) { - const privateCert = await client.get(`nex:${name}:private_cert`); +// NEX server cache functions - if (privateCert !== null) { - return Buffer.from(privateCert); - } else { - return privateCert; - } +async function getNEXPublicCert(name) { + return await getCachedFile(`nex:${name}:public_cert`); } -async function getNEXSecretKey(name) { - const secretKey = await client.get(`nex:${name}:secret_key`); +async function getNEXPrivateCert(name) { + return await getCachedFile(`nex:${name}:private_cert`); +} - if (secretKey !== null) { - return Buffer.from(secretKey); - } else { - return secretKey; - } +async function getNEXSecretKey(name) { + return await getCachedFile(`nex:${name}:secret_key`); } async function getNEXAESKey(name) { - const aesKey = await client.get(`nex:${name}:aes_key`); - - if (aesKey !== null) { - return Buffer.from(aesKey); - } else { - return aesKey; - } + return await getCachedFile(`nex:${name}:aes_key`); } async function setNEXPublicCert(name, value) { - await client.set(`nex:${name}:public_cert`, value); + await setCachedFile('nex', name, 'public_cert', value); } async function setNEXPrivateCert(name, value) { - await client.set(`nex:${name}:private_cert`, value); + await setCachedFile('nex', name, 'private_cert', value); } async function setNEXSecretKey(name, value) { - await client.set(`nex:${name}:secret_key`, value); + await setCachedFile('nex', name, 'secret_key', value); } async function setNEXAESKey(name, value) { - await client.set(`nex:${name}:aes_key`, value); + await setCachedFile('nex', name, 'aes_key', value); } // 3rd party service cache functions async function getServicePublicCert(name) { - const publicCert = await client.get(`service:${name}:public_cert`); - - if (publicCert !== null) { - return Buffer.from(publicCert); - } else { - return publicCert; - } + return await getCachedFile(`service:${name}:public_cert`); } async function getServicePrivateCert(name) { - const privateCert = await client.get(`service:${name}:private_cert`); - - if (privateCert !== null) { - return Buffer.from(privateCert); - } else { - return privateCert; - } + return await getCachedFile(`service:${name}:private_cert`); } async function getServiceSecretKey(name) { - const secretKey = await client.get(`service:${name}:secret_key`); - - if (secretKey !== null) { - return Buffer.from(secretKey); - } else { - return secretKey; - } + return await getCachedFile(`service:${name}:secret_key`); } async function getServiceAESKey(name) { - const aesKey = await client.get(`service:${name}:aes_key`); - - if (aesKey !== null) { - return Buffer.from(aesKey); - } else { - return aesKey; - } + return await getCachedFile(`service:${name}:aes_key`); } async function setServicePublicCert(name, value) { - await client.set(`service:${name}:public_cert`, value); + await setCachedFile('service', name, 'public_cert', value); } async function setServicePrivateCert(name, value) { - await client.set(`service:${name}:private_cert`, value); + await setCachedFile('service', name, 'private_cert', value); } async function setServiceSecretKey(name, value) { - await client.set(`service:${name}:secret_key`, value); + await setCachedFile('service', name, 'secret_key', value); } async function setServiceAESKey(name, value) { - await client.set(`service:${name}:aes_key`, value); + await setCachedFile('service', name, 'aes_key', value); } module.exports = { From 0996df985ead53c9e4405578dd7c7955551fb1e9 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:40:30 -0400 Subject: [PATCH 010/105] Add encoding option to cache --- src/cache.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/cache.js b/src/cache.js index d870071..7d928a8 100644 --- a/src/cache.js +++ b/src/cache.js @@ -12,11 +12,11 @@ async function setCachedFile(type, name, fileName, value) { await client.set(`${type}:${name}:${fileName}`, value); } -async function getCachedFile(type, name, fileName) { +async function getCachedFile(type, name, fileName, encoding) { const cachedFile = await client.get(`${type}:${name}:${fileName}`); if (cachedFile !== null) { - return Buffer.from(cachedFile); + return Buffer.from(cachedFile, encoding); } else { return cachedFile; } @@ -24,20 +24,20 @@ async function getCachedFile(type, name, fileName) { // NEX server cache functions -async function getNEXPublicCert(name) { - return await getCachedFile(`nex:${name}:public_cert`); +async function getNEXPublicCert(name, encoding) { + return await getCachedFile(`nex:${name}:public_cert`, encoding); } -async function getNEXPrivateCert(name) { - return await getCachedFile(`nex:${name}:private_cert`); +async function getNEXPrivateCert(name, encoding) { + return await getCachedFile(`nex:${name}:private_cert`, encoding); } -async function getNEXSecretKey(name) { - return await getCachedFile(`nex:${name}:secret_key`); +async function getNEXSecretKey(name, encoding) { + return await getCachedFile(`nex:${name}:secret_key`, encoding); } -async function getNEXAESKey(name) { - return await getCachedFile(`nex:${name}:aes_key`); +async function getNEXAESKey(name, encoding) { + return await getCachedFile(`nex:${name}:aes_key`, encoding); } async function setNEXPublicCert(name, value) { @@ -58,20 +58,20 @@ async function setNEXAESKey(name, value) { // 3rd party service cache functions -async function getServicePublicCert(name) { - return await getCachedFile(`service:${name}:public_cert`); +async function getServicePublicCert(name, encoding) { + return await getCachedFile(`service:${name}:public_cert`, encoding); } -async function getServicePrivateCert(name) { - return await getCachedFile(`service:${name}:private_cert`); +async function getServicePrivateCert(name, encoding) { + return await getCachedFile(`service:${name}:private_cert`, encoding); } -async function getServiceSecretKey(name) { - return await getCachedFile(`service:${name}:secret_key`); +async function getServiceSecretKey(name, encoding) { + return await getCachedFile(`service:${name}:secret_key`, encoding); } -async function getServiceAESKey(name) { - return await getCachedFile(`service:${name}:aes_key`); +async function getServiceAESKey(name, encoding) { + return await getCachedFile(`service:${name}:aes_key`, encoding); } async function setServicePublicCert(name, value) { From 64e12fa667e924cc6114b026c53b23d3b21559fd Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:45:18 -0400 Subject: [PATCH 011/105] Changed name from cert to key for RSA keys in cache --- src/cache.js | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/cache.js b/src/cache.js index 7d928a8..f6772a3 100644 --- a/src/cache.js +++ b/src/cache.js @@ -24,12 +24,12 @@ async function getCachedFile(type, name, fileName, encoding) { // NEX server cache functions -async function getNEXPublicCert(name, encoding) { - return await getCachedFile(`nex:${name}:public_cert`, encoding); +async function getNEXPublicKey(name, encoding) { + return await getCachedFile(`nex:${name}:public_key`, encoding); } -async function getNEXPrivateCert(name, encoding) { - return await getCachedFile(`nex:${name}:private_cert`, encoding); +async function getNEXPrivateKey(name, encoding) { + return await getCachedFile(`nex:${name}:private_key`, encoding); } async function getNEXSecretKey(name, encoding) { @@ -40,12 +40,12 @@ async function getNEXAESKey(name, encoding) { return await getCachedFile(`nex:${name}:aes_key`, encoding); } -async function setNEXPublicCert(name, value) { - await setCachedFile('nex', name, 'public_cert', value); +async function setNEXPublicKey(name, value) { + await setCachedFile('nex', name, 'public_key', value); } -async function setNEXPrivateCert(name, value) { - await setCachedFile('nex', name, 'private_cert', value); +async function setNEXPrivateKey(name, value) { + await setCachedFile('nex', name, 'private_key', value); } async function setNEXSecretKey(name, value) { @@ -58,12 +58,12 @@ async function setNEXAESKey(name, value) { // 3rd party service cache functions -async function getServicePublicCert(name, encoding) { - return await getCachedFile(`service:${name}:public_cert`, encoding); +async function getServicePublicKey(name, encoding) { + return await getCachedFile(`service:${name}:public_key`, encoding); } -async function getServicePrivateCert(name, encoding) { - return await getCachedFile(`service:${name}:private_cert`, encoding); +async function getServicePrivateKey(name, encoding) { + return await getCachedFile(`service:${name}:private_key`, encoding); } async function getServiceSecretKey(name, encoding) { @@ -74,12 +74,12 @@ async function getServiceAESKey(name, encoding) { return await getCachedFile(`service:${name}:aes_key`, encoding); } -async function setServicePublicCert(name, value) { - await setCachedFile('service', name, 'public_cert', value); +async function setServicePublicKey(name, value) { + await setCachedFile('service', name, 'public_key', value); } -async function setServicePrivateCert(name, value) { - await setCachedFile('service', name, 'private_cert', value); +async function setServicePrivateKey(name, value) { + await setCachedFile('service', name, 'private_key', value); } async function setServiceSecretKey(name, value) { @@ -92,20 +92,20 @@ async function setServiceAESKey(name, value) { module.exports = { connect, - getNEXPublicCert, - getNEXPrivateCert, + getNEXPublicKey, + getNEXPrivateKey, getNEXSecretKey, getNEXAESKey, - setNEXPublicCert, - setNEXPrivateCert, + setNEXPublicKey, + setNEXPrivateKey, setNEXSecretKey, setNEXAESKey, - getServicePublicCert, - getServicePrivateCert, + getServicePublicKey, + getServicePrivateKey, getServiceSecretKey, getServiceAESKey, - setServicePublicCert, - setServicePrivateCert, + setServicePublicKey, + setServicePrivateKey, setServiceSecretKey, setServiceAESKey, }; \ No newline at end of file From 663872e3c7fc74f89333a95395727b9485b103bc Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:48:27 -0400 Subject: [PATCH 012/105] decryptToken() now uses file cache --- src/util.js | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/util.js b/src/util.js index 14f2094..9d0f15f 100644 --- a/src/util.js +++ b/src/util.js @@ -2,6 +2,7 @@ const crypto = require('crypto'); const NodeRSA = require('node-rsa'); const fs = require('fs-extra'); const aws = require('aws-sdk'); +const cache = require('./cache'); const config = require('../config.json'); const spacesEndpoint = new aws.Endpoint('nyc3.digitaloceanspaces.com'); @@ -123,12 +124,17 @@ function generateToken(cryptoOptions, tokenOptions) { } function decryptToken(token) { + const cryptoPath = `${__dirname}/../certs/access`; // Access and refresh tokens use a different format since they must be much smaller // Assume a small length means access or refresh token if (token.length <= 32) { - const cryptoPath = `${__dirname}/../certs/access`; - const aesKey = Buffer.from(fs.readFileSync(`${cryptoPath}/aes.key`, { encoding: 'utf8' }), 'hex'); + let aesKey = cache.getServiceAESKey('account', 'hex'); + + if (aesKey === null) { + aesKey = Buffer.from(fs.readFileSync(`${cryptoPath}/aes.key`, { encoding: 'utf8' }), 'hex'); + await cache.setServiceAESKey(aesKey); + } const iv = Buffer.alloc(16); @@ -140,14 +146,19 @@ function decryptToken(token) { return decryptedBody; } - const cryptoPath = `${__dirname}/../certs/access`; + let privateKeyBytes = cache.getServicePrivateKey('account'); + if (privateKeyBytes === null) { + privateKeyBytes = fs.readFileSync(`${cryptoPath}/private.pem`); + await cache.setServicePrivateKey(privateKeyBytes); + } - const cryptoOptions = { - private_key: fs.readFileSync(`${cryptoPath}/private.pem`), - hmac_secret: fs.readFileSync(`${cryptoPath}/secret.key`) - }; + let secretKey = cache.getServiceSecretKey('account'); + if (secretKey === null) { + secretKey = fs.readFileSync(`${cryptoPath}/secret.key`); + await cache.setServiceSecretKey(secretKey); + } - const privateKey = new NodeRSA(cryptoOptions.private_key, 'pkcs1-private-pem', { + const privateKey = new NodeRSA(privateKeyBytes, 'pkcs1-private-pem', { environment: 'browser', encryptionScheme: { 'hash': 'sha256', @@ -174,7 +185,7 @@ function decryptToken(token) { let decryptedBody = decipher.update(encryptedBody); decryptedBody = Buffer.concat([decryptedBody, decipher.final()]); - const hmac = crypto.createHmac('sha1', cryptoOptions.hmac_secret).update(decryptedBody); + const hmac = crypto.createHmac('sha1', secretKey).update(decryptedBody); const calculatedSignature = hmac.digest(); if (!signature.equals(calculatedSignature)) { From 82e4080199813043355c2b9587d5dd1bec34322a Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 18:51:31 -0400 Subject: [PATCH 013/105] decryptToken() now uses async functions --- src/database.js | 2 +- src/services/api/routes/v1/login.js | 2 +- src/util.js | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/database.js b/src/database.js index 1f00cbf..d535206 100644 --- a/src/database.js +++ b/src/database.js @@ -75,7 +75,7 @@ async function getUserBasic(token) { async function getUserBearer(token) { verifyConnected(); - const decryptedToken = util.decryptToken(Buffer.from(token, 'base64')); + const decryptedToken = await util.decryptToken(Buffer.from(token, 'base64')); const unpackedToken = util.unpackToken(decryptedToken); const user = await getUserByPID(unpackedToken.pid); diff --git a/src/services/api/routes/v1/login.js b/src/services/api/routes/v1/login.js index 3d86f03..ab1966d 100644 --- a/src/services/api/routes/v1/login.js +++ b/src/services/api/routes/v1/login.js @@ -67,7 +67,7 @@ router.post('/', async (request, response) => { }); } } else { - const decryptedToken = util.decryptToken(Buffer.from(refresh_token, 'base64')); + const decryptedToken = await util.decryptToken(Buffer.from(refresh_token, 'base64')); const unpackedToken = util.unpackToken(decryptedToken); pnid = await database.getUserByPID(unpackedToken.pid); diff --git a/src/util.js b/src/util.js index 9d0f15f..601f248 100644 --- a/src/util.js +++ b/src/util.js @@ -123,7 +123,7 @@ function generateToken(cryptoOptions, tokenOptions) { return token.toString('base64'); // Encode to base64 for transport } -function decryptToken(token) { +async function decryptToken(token) { const cryptoPath = `${__dirname}/../certs/access`; // Access and refresh tokens use a different format since they must be much smaller @@ -132,7 +132,8 @@ function decryptToken(token) { let aesKey = cache.getServiceAESKey('account', 'hex'); if (aesKey === null) { - aesKey = Buffer.from(fs.readFileSync(`${cryptoPath}/aes.key`, { encoding: 'utf8' }), 'hex'); + const fileBuffer = await fs.readFile(`${cryptoPath}/aes.key`, { encoding: 'utf8' }); + aesKey = Buffer.from(fileBuffer, 'hex'); await cache.setServiceAESKey(aesKey); } @@ -148,13 +149,13 @@ function decryptToken(token) { let privateKeyBytes = cache.getServicePrivateKey('account'); if (privateKeyBytes === null) { - privateKeyBytes = fs.readFileSync(`${cryptoPath}/private.pem`); + privateKeyBytes = await fs.readFile(`${cryptoPath}/private.pem`); await cache.setServicePrivateKey(privateKeyBytes); } let secretKey = cache.getServiceSecretKey('account'); if (secretKey === null) { - secretKey = fs.readFileSync(`${cryptoPath}/secret.key`); + secretKey = await fs.readFile(`${cryptoPath}/secret.key`); await cache.setServiceSecretKey(secretKey); } From 8172c1cac96175d69db71eb138ef3c316ae2097e Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:02:32 -0400 Subject: [PATCH 014/105] /service_token/@me uses cache and async fs --- src/services/nnid/routes/provider.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/services/nnid/routes/provider.js b/src/services/nnid/routes/provider.js index 30989c5..c1f7a95 100644 --- a/src/services/nnid/routes/provider.js +++ b/src/services/nnid/routes/provider.js @@ -32,7 +32,7 @@ router.get('/service_token/@me', async (request, response) => { const cryptoPath = `${__dirname}/../../../../certs/${service_type}/${service_name}`; - if (!fs.pathExistsSync(cryptoPath)) { + if (!await fs.pathExists(cryptoPath)) { // Need to generate keys return response.send(xmlbuilder.create({ errors: { @@ -44,12 +44,21 @@ router.get('/service_token/@me', async (request, response) => { }).end()); } - const publicKey = fs.readFileSync(`${cryptoPath}/public.pem`); - const hmacSecret = fs.readFileSync(`${cryptoPath}/secret.key`); + let publicKey = cache.getServicePublicKey(service_name); + if (publicKey === null) { + publicKey = await fs.readFile(`${cryptoPath}/public.pem`); + await cache.setServicePublicKey(publicKey); + } + + let secretKey = cache.getServiceSecretKey(service_name); + if (secretKey === null) { + secretKey = await fs.readFile(`${cryptoPath}/secret.key`); + await cache.setServiceSecretKey(secretKey); + } const cryptoOptions = { public_key: publicKey, - hmac_secret: hmacSecret + hmac_secret: secretKey }; const tokenOptions = { From 754f2fb85c31edb292d48f2920531aee3c8af81e Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:08:48 -0400 Subject: [PATCH 015/105] Forgot to add name to cache set --- src/services/nnid/routes/provider.js | 4 ++-- src/util.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/nnid/routes/provider.js b/src/services/nnid/routes/provider.js index c1f7a95..67aef1d 100644 --- a/src/services/nnid/routes/provider.js +++ b/src/services/nnid/routes/provider.js @@ -47,13 +47,13 @@ router.get('/service_token/@me', async (request, response) => { let publicKey = cache.getServicePublicKey(service_name); if (publicKey === null) { publicKey = await fs.readFile(`${cryptoPath}/public.pem`); - await cache.setServicePublicKey(publicKey); + await cache.setServicePublicKey(service_name, publicKey); } let secretKey = cache.getServiceSecretKey(service_name); if (secretKey === null) { secretKey = await fs.readFile(`${cryptoPath}/secret.key`); - await cache.setServiceSecretKey(secretKey); + await cache.setServiceSecretKey(service_name, secretKey); } const cryptoOptions = { diff --git a/src/util.js b/src/util.js index 601f248..d139295 100644 --- a/src/util.js +++ b/src/util.js @@ -134,7 +134,7 @@ async function decryptToken(token) { if (aesKey === null) { const fileBuffer = await fs.readFile(`${cryptoPath}/aes.key`, { encoding: 'utf8' }); aesKey = Buffer.from(fileBuffer, 'hex'); - await cache.setServiceAESKey(aesKey); + await cache.setServiceAESKey('account', aesKey); } const iv = Buffer.alloc(16); @@ -150,13 +150,13 @@ async function decryptToken(token) { let privateKeyBytes = cache.getServicePrivateKey('account'); if (privateKeyBytes === null) { privateKeyBytes = await fs.readFile(`${cryptoPath}/private.pem`); - await cache.setServicePrivateKey(privateKeyBytes); + await cache.setServicePrivateKey('account', privateKeyBytes); } let secretKey = cache.getServiceSecretKey('account'); if (secretKey === null) { secretKey = await fs.readFile(`${cryptoPath}/secret.key`); - await cache.setServiceSecretKey(secretKey); + await cache.setServiceSecretKey('account', secretKey); } const privateKey = new NodeRSA(privateKeyBytes, 'pkcs1-private-pem', { From da3516baede70a129b667f96293989b882f26f83 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:28:07 -0400 Subject: [PATCH 016/105] generateToken() now uses cache and async fs --- src/services/api/routes/v1/login.js | 4 ++-- src/services/api/routes/v1/register.js | 4 ++-- src/services/nasc/routes/ac.js | 2 +- src/services/nnid/routes/oauth.js | 4 ++-- src/services/nnid/routes/provider.js | 4 ++-- src/util.js | 12 +++++++++--- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/services/api/routes/v1/login.js b/src/services/api/routes/v1/login.js index ab1966d..e57df6c 100644 --- a/src/services/api/routes/v1/login.js +++ b/src/services/api/routes/v1/login.js @@ -117,8 +117,8 @@ router.post('/', async (request, response) => { expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const accessToken = util.generateToken(cryptoOptions, accessTokenOptions); - const refreshToken = util.generateToken(cryptoOptions, refreshTokenOptions); + const accessToken = await util.generateToken(cryptoOptions, accessTokenOptions); + const refreshToken = await util.generateToken(cryptoOptions, refreshTokenOptions); response.json({ access_token: accessToken, diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 51a3ef5..8ea8c47 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -337,8 +337,8 @@ router.post('/', async (request, response) => { expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const accessToken = util.generateToken(cryptoOptions, accessTokenOptions); - const refreshToken = util.generateToken(cryptoOptions, refreshTokenOptions); + const accessToken = await util.generateToken(cryptoOptions, accessTokenOptions); + const refreshToken = await util.generateToken(cryptoOptions, refreshTokenOptions); response.json({ access_token: accessToken, diff --git a/src/services/nasc/routes/ac.js b/src/services/nasc/routes/ac.js index 0764b36..c1ce355 100644 --- a/src/services/nasc/routes/ac.js +++ b/src/services/nasc/routes/ac.js @@ -72,7 +72,7 @@ async function processLoginRequest(request) { expire_time: BigInt(Date.now() + (3600 * 1000)) }; - let nexToken = util.generateToken(cryptoOptions, tokenOptions); + let nexToken = await util.generateToken(cryptoOptions, tokenOptions); nexToken = util.nintendoBase64Encode(Buffer.from(nexToken, 'base64')); const params = new URLSearchParams({ diff --git a/src/services/nnid/routes/oauth.js b/src/services/nnid/routes/oauth.js index fdb163b..c6bdb7f 100644 --- a/src/services/nnid/routes/oauth.js +++ b/src/services/nnid/routes/oauth.js @@ -98,8 +98,8 @@ router.post('/access_token/generate', async (request, response) => { expire_time: BigInt(Date.now() + (3600 * 1000)) }; - let accessToken = util.generateToken(null, accessTokenOptions); - let refreshToken = util.generateToken(null, refreshTokenOptions); + let accessToken = await util.generateToken(null, accessTokenOptions); + let refreshToken = await util.generateToken(null, refreshTokenOptions); if (request.isCemu) { accessToken = Buffer.from(accessToken, 'base64').toString('hex'); diff --git a/src/services/nnid/routes/provider.js b/src/services/nnid/routes/provider.js index 67aef1d..91999cf 100644 --- a/src/services/nnid/routes/provider.js +++ b/src/services/nnid/routes/provider.js @@ -70,7 +70,7 @@ router.get('/service_token/@me', async (request, response) => { expire_time: BigInt(Date.now() + (3600 * 1000)) }; - let serviceToken = util.generateToken(cryptoOptions, tokenOptions); + let serviceToken = await util.generateToken(cryptoOptions, tokenOptions); if (request.isCemu) { serviceToken = Buffer.from(serviceToken, 'base64').toString('hex'); @@ -160,7 +160,7 @@ router.get('/nex_token/@me', async (request, response) => { return response.send('0008Not Found'); } - let nexToken = util.generateToken(cryptoOptions, tokenOptions); + let nexToken = await util.generateToken(cryptoOptions, tokenOptions); if (request.isCemu) { nexToken = Buffer.from(nexToken, 'base64').toString('hex'); diff --git a/src/util.js b/src/util.js index d139295..26082e7 100644 --- a/src/util.js +++ b/src/util.js @@ -36,13 +36,19 @@ function nintendoBase64Encode(decoded) { return encoded.replaceAll('+', '.').replaceAll('/', '-').replaceAll('=', '*'); } -function generateToken(cryptoOptions, tokenOptions) { +async function generateToken(cryptoOptions, tokenOptions) { // Access and refresh tokens use a different format since they must be much smaller // They take no extra crypto options if (!cryptoOptions) { - const cryptoPath = `${__dirname}/../certs/access`; - const aesKey = Buffer.from(fs.readFileSync(`${cryptoPath}/aes.key`, { encoding: 'utf8' }), 'hex'); + let aesKey = cache.getServiceAESKey('account', 'hex'); + + if (aesKey === null) { + const fileBuffer = await fs.readFile(`${__dirname}/../certs/access/aes.key`, { encoding: 'utf8' }); + aesKey = Buffer.from(fileBuffer, 'hex'); + await cache.setServiceAESKey('account', aesKey); + } + const dataBuffer = Buffer.alloc(1 + 1 + 4 + 8); dataBuffer.writeUInt8(tokenOptions.system_type, 0x0); From 54d08b78cc9211f4f0f5fce4a1a26a229ceecb65 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:31:14 -0400 Subject: [PATCH 017/105] /nex_token/@me uses cache and async fs --- src/services/nnid/routes/provider.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/services/nnid/routes/provider.js b/src/services/nnid/routes/provider.js index 91999cf..da710d3 100644 --- a/src/services/nnid/routes/provider.js +++ b/src/services/nnid/routes/provider.js @@ -122,7 +122,7 @@ router.get('/nex_token/@me', async (request, response) => { const cryptoPath = `${__dirname}/../../../../certs/${service_type}/${service_name}`; - if (!fs.pathExistsSync(cryptoPath)) { + if (!await fs.pathExists(cryptoPath)) { // Need to generate keys return response.send(xmlbuilder.create({ errors: { @@ -134,12 +134,21 @@ router.get('/nex_token/@me', async (request, response) => { }).end()); } - const publicKey = fs.readFileSync(`${cryptoPath}/public.pem`); - const hmacSecret = fs.readFileSync(`${cryptoPath}/secret.key`); + let publicKey = cache.getNEXPublicKey(service_name); + if (publicKey === null) { + publicKey = await fs.readFile(`${cryptoPath}/public.pem`); + await cache.setNEXPublicKey(service_name, publicKey); + } + + let secretKey = cache.getNEXSecretKey(service_name); + if (secretKey === null) { + secretKey = await fs.readFile(`${cryptoPath}/secret.key`); + await cache.setNEXSecretKey(service_name, secretKey); + } const cryptoOptions = { public_key: publicKey, - hmac_secret: hmacSecret + hmac_secret: secretKey }; const tokenOptions = { From a9bf9cac7c7241c1f34ba808916d6d8cb06f686c Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:34:07 -0400 Subject: [PATCH 018/105] /access_token/generate now uses async functions --- src/services/nnid/routes/oauth.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/nnid/routes/oauth.js b/src/services/nnid/routes/oauth.js index c6bdb7f..b6a9998 100644 --- a/src/services/nnid/routes/oauth.js +++ b/src/services/nnid/routes/oauth.js @@ -49,7 +49,7 @@ router.post('/access_token/generate', async (request, response) => { const pnid = await database.getUserByUsername(user_id); - if (!pnid || !bcrypt.compareSync(password, pnid.password)) { + if (!pnid || !await bcrypt.compare(password, pnid.password)) { response.status(400); return response.send(xmlbuilder.create({ error: { @@ -72,7 +72,7 @@ router.post('/access_token/generate', async (request, response) => { const cryptoPath = `${__dirname}/../../../../certs/access`; - if (!fs.pathExistsSync(cryptoPath)) { + if (!await fs.pathExists(cryptoPath)) { // Need to generate keys return response.send(xmlbuilder.create({ errors: { From 46e103859dfec4eb3c510f5148dc2eac02ed7d46 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:36:42 -0400 Subject: [PATCH 019/105] processLoginRequest() now uses cache and async fs --- src/services/nasc/routes/ac.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/services/nasc/routes/ac.js b/src/services/nasc/routes/ac.js index c1ce355..b34c0b1 100644 --- a/src/services/nasc/routes/ac.js +++ b/src/services/nasc/routes/ac.js @@ -1,4 +1,4 @@ -const fs = require('fs'); +const fs = require('fs-extra'); const express = require('express'); const util = require('../../../util'); const database = require('../../../database'); @@ -55,12 +55,21 @@ async function processLoginRequest(request) { const cryptoPath = `${__dirname}/../../../../certs/nex/${service_name}`; - const publicKey = fs.readFileSync(`${cryptoPath}/public.pem`); - const hmacSecret = fs.readFileSync(`${cryptoPath}/secret.key`); + let publicKey = cache.getNEXPublicKey(service_name); + if (publicKey === null) { + publicKey = await fs.readFile(`${cryptoPath}/public.pem`); + await cache.setNEXPublicKey(service_name, publicKey); + } + + let secretKey = cache.getNEXSecretKey(service_name); + if (secretKey === null) { + secretKey = await fs.readFile(`${cryptoPath}/secret.key`); + await cache.setNEXSecretKey(service_name, secretKey); + } const cryptoOptions = { public_key: publicKey, - hmac_secret: hmacSecret + hmac_secret: secretKey }; const tokenOptions = { From 4661ebf3a5f602534e6fb5041d8f7b05046ceab8 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:41:41 -0400 Subject: [PATCH 020/105] /v1/register now uses cache and async fs --- src/services/api/routes/v1/register.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 8ea8c47..68bc371 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -302,7 +302,7 @@ router.post('/', async (request, response) => { const cryptoPath = `${__dirname}/../../../../../certs/access`; - if (!fs.pathExistsSync(cryptoPath)) { + if (!await fs.pathExists(cryptoPath)) { // Need to generate keys return response.status(500).json({ app: 'api', @@ -311,12 +311,21 @@ router.post('/', async (request, response) => { }); } - const publicKey = fs.readFileSync(`${cryptoPath}/public.pem`); - const hmacSecret = fs.readFileSync(`${cryptoPath}/secret.key`); + let publicKey = cache.getServicePublicKey('account'); + if (publicKey === null) { + publicKey = await fs.readFile(`${cryptoPath}/public.pem`); + await cache.setServicePublicKey('account', publicKey); + } + + let secretKey = cache.getServiceSecretKey('account'); + if (secretKey === null) { + secretKey = await fs.readFile(`${cryptoPath}/secret.key`); + await cache.setServiceSecretKey('account', secretKey); + } const cryptoOptions = { public_key: publicKey, - hmac_secret: hmacSecret + hmac_secret: secretKey }; const accessTokenOptions = { From 4dcec5388cb426c971aba6f6f8fccfeb630ccaac Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:43:07 -0400 Subject: [PATCH 021/105] /v1/login now uses cache and async fs --- src/services/api/routes/v1/login.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/services/api/routes/v1/login.js b/src/services/api/routes/v1/login.js index e57df6c..29148fb 100644 --- a/src/services/api/routes/v1/login.js +++ b/src/services/api/routes/v1/login.js @@ -82,7 +82,7 @@ router.post('/', async (request, response) => { const cryptoPath = `${__dirname}/../../../../../certs/access`; - if (!fs.pathExistsSync(cryptoPath)) { + if (!await fs.pathExists(cryptoPath)) { // Need to generate keys return response.status(500).json({ app: 'api', @@ -91,12 +91,21 @@ router.post('/', async (request, response) => { }); } - const publicKey = fs.readFileSync(`${cryptoPath}/public.pem`); - const hmacSecret = fs.readFileSync(`${cryptoPath}/secret.key`); + let publicKey = cache.getServicePublicKey('account'); + if (publicKey === null) { + publicKey = await fs.readFile(`${cryptoPath}/public.pem`); + await cache.setServicePublicKey('account', publicKey); + } + + let secretKey = cache.getServiceSecretKey('account'); + if (secretKey === null) { + secretKey = await fs.readFile(`${cryptoPath}/secret.key`); + await cache.setServiceSecretKey('account', secretKey); + } const cryptoOptions = { public_key: publicKey, - hmac_secret: hmacSecret + hmac_secret: secretKey }; const accessTokenOptions = { From fd34162a59201a64adf679711072d69b6b4d32c2 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:45:54 -0400 Subject: [PATCH 022/105] Stop server from crashing on failed token decrypt --- src/database.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/database.js b/src/database.js index d535206..5a30cba 100644 --- a/src/database.js +++ b/src/database.js @@ -75,20 +75,26 @@ async function getUserBasic(token) { async function getUserBearer(token) { verifyConnected(); - const decryptedToken = await util.decryptToken(Buffer.from(token, 'base64')); - const unpackedToken = util.unpackToken(decryptedToken); + try { + const decryptedToken = await util.decryptToken(Buffer.from(token, 'base64')); + const unpackedToken = util.unpackToken(decryptedToken); - const user = await getUserByPID(unpackedToken.pid); + const user = await getUserByPID(unpackedToken.pid); - if (user) { - const expireTime = Math.floor((Number(unpackedToken.expire_time) / 1000)); + if (user) { + const expireTime = Math.floor((Number(unpackedToken.expire_time) / 1000)); - if (Math.floor(Date.now() / 1000) > expireTime) { - return null; + if (Math.floor(Date.now() / 1000) > expireTime) { + return null; + } } - } - return user; + return user; + } catch (error) { + // TODO: Handle error + return null; + } + } async function getUserProfileJSONByPID(pid) { From 70d37d113fda9683c541959cb9be890be6923559 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:55:24 -0400 Subject: [PATCH 023/105] getUserProfileJSONByPID() now uses CDN from config --- src/database.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/database.js b/src/database.js index 5a30cba..66eb5fd 100644 --- a/src/database.js +++ b/src/database.js @@ -3,8 +3,8 @@ const bcrypt = require('bcrypt'); const util = require('./util'); const { PNID } = require('./models/pnid'); const { Server } = require('./models/server'); -const { mongoose: mongooseConfig } = require('../config.json'); -const { uri, database, options } = mongooseConfig; +const config = require('../config.json'); +const { uri, database, options } = config.mongoose; let connection; @@ -154,9 +154,9 @@ async function getUserProfileJSONByPID(pid) { mii_image: { // Images MUST be loaded over HTTPS or console ignores them // Bunny CDN is the only CDN which seems to support TLS 1.0/1.1 (required) - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/standard.tga`, + cached_url: `${config.cdn_base}/mii/${user.pid}/standard.tga`, id: user.get('mii.image_id'), - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/standard.tga`, + url: `${config.cdn_base}/mii/${user.pid}/standard.tga`, type: 'standard' } }, From 0cf319307c6c30ecda9aa5f71d152a0f37faa146 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:56:08 -0400 Subject: [PATCH 024/105] /v1/user now uses CDN from config --- src/services/api/routes/v1/user.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/api/routes/v1/user.js b/src/services/api/routes/v1/user.js index bd77b96..f129a1a 100644 --- a/src/services/api/routes/v1/user.js +++ b/src/services/api/routes/v1/user.js @@ -1,5 +1,6 @@ const router = require('express').Router(); const { PNID } = require('../../../../models/pnid'); +const config = require('../../../../config.json'); /** * [GET] @@ -36,7 +37,7 @@ router.get('/', async (request, response) => { mii: { data: pnid.get('mii.data'), name: pnid.get('mii.name'), - image_url: `https://pretendo-cdn.b-cdn.net/mii/${pnid.get('pid')}/normal_face.png` + image_url: `${config.cdn_base}/mii/${pnid.get('pid')}/normal_face.png` }, flags: { marketing: pnid.get('flags.marketing') From 2211ab475fa398803338934757856190c59ec03b Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:56:36 -0400 Subject: [PATCH 025/105] /v1/user now uses CDN from config (2) --- src/services/api/routes/v1/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/api/routes/v1/user.js b/src/services/api/routes/v1/user.js index f129a1a..ebafe2a 100644 --- a/src/services/api/routes/v1/user.js +++ b/src/services/api/routes/v1/user.js @@ -99,7 +99,7 @@ router.post('/', async (request, response) => { mii: { data: pnid.get('mii.data'), name: pnid.get('mii.name'), - image_url: `https://pretendo-cdn.b-cdn.net/mii/${pnid.get('pid')}/normal_face.png` + image_url: `${config.cdn_base}/mii/${pnid.get('pid')}/normal_face.png` }, flags: { marketing: pnid.get('flags.marketing') From 7f760d0c430b7d7a7be5ed02e167fda34f692a39 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 19:58:40 -0400 Subject: [PATCH 026/105] /v1/api/miis now uses CDN from config --- src/services/nnid/routes/miis.js | 33 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/services/nnid/routes/miis.js b/src/services/nnid/routes/miis.js index 08ef5bc..fb36803 100644 --- a/src/services/nnid/routes/miis.js +++ b/src/services/nnid/routes/miis.js @@ -1,6 +1,7 @@ const router = require('express').Router(); const xmlbuilder = require('xmlbuilder'); const { PNID } = require('../../../models/pnid'); +const config = require('../../../config.json'); /** * [GET] @@ -19,51 +20,51 @@ router.get('/', async (request, response) => { const miiImages = [ { - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/normal_face.png`, + cached_url: `${config.cdn_base}/mii/${user.pid}/normal_face.png`, id: mii.id, - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/normal_face.png`, + url: `${config.cdn_base}/mii/${user.pid}/normal_face.png`, type: 'standard' }, { - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/frustrated.png`, + cached_url: `${config.cdn_base}/mii/${user.pid}/frustrated.png`, id: mii.id, - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/frustrated.png`, + url: `${config.cdn_base}/mii/${user.pid}/frustrated.png`, type: 'frustrated_face' }, { - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/smile_open_mouth.png`, + cached_url: `${config.cdn_base}/mii/${user.pid}/smile_open_mouth.png`, id: mii.id, - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/smile_open_mouth.png`, + url: `${config.cdn_base}/mii/${user.pid}/smile_open_mouth.png`, type: 'happy_face' }, { - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/wink_left.png`, + cached_url: `${config.cdn_base}/mii/${user.pid}/wink_left.png`, id: mii.id, - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/wink_left.png`, + url: `${config.cdn_base}/mii/${user.pid}/wink_left.png`, type: 'like_face' }, { - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/normal_face.png`, + cached_url: `${config.cdn_base}/mii/${user.pid}/normal_face.png`, id: mii.id, - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/normal_face.png`, + url: `${config.cdn_base}/mii/${user.pid}/normal_face.png`, type: 'normal_face' }, { - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/sorrow.png`, + cached_url: `${config.cdn_base}/mii/${user.pid}/sorrow.png`, id: mii.id, - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/sorrow.png`, + url: `${config.cdn_base}/mii/${user.pid}/sorrow.png`, type: 'puzzled_face' }, { - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/surprised_open_mouth.png`, + cached_url: `${config.cdn_base}/mii/${user.pid}/surprised_open_mouth.png`, id: mii.id, - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/surprised_open_mouth.png`, + url: `${config.cdn_base}/mii/${user.pid}/surprised_open_mouth.png`, type: 'surprised_face' }, { - cached_url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/body.png`, + cached_url: `${config.cdn_base}/mii/${user.pid}/body.png`, id: mii.id, - url: `https://pretendo-cdn.b-cdn.net/mii/${user.pid}/body.png`, + url: `${config.cdn_base}/mii/${user.pid}/body.png`, type: 'whole_body' } ]; From 1cc4759813cbf1af74f7ce9845ee9a9612794f30 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 20:02:09 -0400 Subject: [PATCH 027/105] servers.json no longer used --- src/example.servers.json | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 src/example.servers.json diff --git a/src/example.servers.json b/src/example.servers.json deleted file mode 100644 index be3e344..0000000 --- a/src/example.servers.json +++ /dev/null @@ -1,24 +0,0 @@ -[ - { - "title_ids": [ - "000500301001500A", - "000500301001510A", - "000500301001520A", - "0005001010001C00" - ], - "server_id": "00003200", - "ip": "192.168.0.27", - "port": "60000", - "system": 1, - "crypto": { - "service": { - "cek": "", - "hmac_secret": "" - }, - "nex": { - "cek": "", - "hmac_secret": "" - } - } - } -] \ No newline at end of file From 8866b233ab04d5808e66adec76f75908585ec362 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 20:03:09 -0400 Subject: [PATCH 028/105] Moved example config to root --- src/example.config.json => example.config.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/example.config.json => example.config.json (100%) diff --git a/src/example.config.json b/example.config.json similarity index 100% rename from src/example.config.json rename to example.config.json From 7808adc004a2257fb080fba42b630f82dced514d Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 20:06:54 -0400 Subject: [PATCH 029/105] Fixed config import paths --- src/services/api/routes/v1/register.js | 2 +- src/services/api/routes/v1/user.js | 2 +- src/services/nnid/routes/miis.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 68bc371..3998194 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -8,7 +8,7 @@ const { PNID } = require('../../../../models/pnid'); const { NEXAccount } = require('../../../../models/nex-account'); const database = require('../../../../database'); const util = require('../../../../util'); -const config = require('../../../../../config'); +const config = require('../../../../../config.json'); const PNID_VALID_CHARACTERS_REGEX = /^[\w\-\.]*$/gm; const PNID_PUNCTUATION_START_REGEX = /^[\_\-\.]/gm; diff --git a/src/services/api/routes/v1/user.js b/src/services/api/routes/v1/user.js index ebafe2a..e3a8241 100644 --- a/src/services/api/routes/v1/user.js +++ b/src/services/api/routes/v1/user.js @@ -1,6 +1,6 @@ const router = require('express').Router(); const { PNID } = require('../../../../models/pnid'); -const config = require('../../../../config.json'); +const config = require('../../../../../config.json'); /** * [GET] diff --git a/src/services/nnid/routes/miis.js b/src/services/nnid/routes/miis.js index fb36803..bc99ce9 100644 --- a/src/services/nnid/routes/miis.js +++ b/src/services/nnid/routes/miis.js @@ -1,7 +1,7 @@ const router = require('express').Router(); const xmlbuilder = require('xmlbuilder'); const { PNID } = require('../../../models/pnid'); -const config = require('../../../config.json'); +const config = require('../../../../config.json'); /** * [GET] From 6e3bc960e4f0237a6a2a842f679ffe3d749bcd9f Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 20:07:53 -0400 Subject: [PATCH 030/105] Updated .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 49af38c..c70000a 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,5 @@ typings/ sign.js t.js config.json -servers.json certs /cdn \ No newline at end of file From 345492d910613db0e94fb954dafd4b47b86eff1a Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 20:08:33 -0400 Subject: [PATCH 031/105] Made server run again --- src/server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server.js b/src/server.js index be724af..343bf05 100644 --- a/src/server.js +++ b/src/server.js @@ -83,3 +83,4 @@ async function main() { }); } +main(); \ No newline at end of file From f549a602d83a8235aa4bb6bd6e634617ababb228 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 24 Sep 2022 21:14:21 -0400 Subject: [PATCH 032/105] Use joi for object validation --- package-lock.json | 87 ++++++++++++++++++++++++++++++ package.json | 1 + src/services/api/routes/v1/user.js | 22 ++++++-- 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index e9214bc..e51a154 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "got": "^11.8.2", "hcaptcha": "^0.1.0", "image-pixels": "^1.1.1", + "joi": "^17.6.1", "kaitai-struct": "^0.9.0", "moment": "^2.24.0", "moment-timezone": "^0.5.27", @@ -51,6 +52,19 @@ "node": ">=0.1.90" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, "node_modules/@oozcitak/dom": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-0.0.11.tgz", @@ -217,6 +231,24 @@ "@redis/client": "^1.0.0" } }, + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "node_modules/@sindresorhus/is": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", @@ -1902,6 +1934,18 @@ "node": ">= 0.6.0" } }, + "node_modules/joi": { + "version": "17.6.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.1.tgz", + "integrity": "sha512-Hl7/iBklIX345OCM1TiFSCZRVaAOLDGlWCp0Df2vWYgBgjkezaR7Kvm3joBciBHQjZj5sxXs859r6eqsRSlG8w==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/jpeg-js": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", @@ -3629,6 +3673,19 @@ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@oozcitak/dom": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-0.0.11.tgz", @@ -3761,6 +3818,24 @@ "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", "requires": {} }, + "@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "@sindresorhus/is": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", @@ -5128,6 +5203,18 @@ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" }, + "joi": { + "version": "17.6.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.1.tgz", + "integrity": "sha512-Hl7/iBklIX345OCM1TiFSCZRVaAOLDGlWCp0Df2vWYgBgjkezaR7Kvm3joBciBHQjZj5sxXs859r6eqsRSlG8w==", + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "jpeg-js": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", diff --git a/package.json b/package.json index 089fa2e..79d5354 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "got": "^11.8.2", "hcaptcha": "^0.1.0", "image-pixels": "^1.1.1", + "joi": "^17.6.1", "kaitai-struct": "^0.9.0", "moment": "^2.24.0", "moment-timezone": "^0.5.27", diff --git a/src/services/api/routes/v1/user.js b/src/services/api/routes/v1/user.js index e3a8241..07c014d 100644 --- a/src/services/api/routes/v1/user.js +++ b/src/services/api/routes/v1/user.js @@ -1,7 +1,17 @@ const router = require('express').Router(); +const joi = require('joi'); const { PNID } = require('../../../../models/pnid'); const config = require('../../../../../config.json'); +// TODO: Extend this later with more settings +const userSchema = joi.object({ + mii: joi.object({ + name: joi.string(), + primary: joi.string(), + data: joi.string(), + }) +}); + /** * [GET] * Implementation of for: https://api.pretendo.cc/v1/user @@ -66,12 +76,14 @@ router.post('/', async (request, response) => { }); } - if (body.mii && typeof body.mii === 'object' && body.mii.name && body.mii.primary && body.mii.data) { - const name = body.mii.name; - const primary = body.mii.primary; - const data = body.mii.data; + const valid = userSchema.validate(body); - await pnid.updateMii({ name, primary, data }); + if (valid.error) { + return response.status(400).json({ + app: 'api', + status: 400, + error: valid.error + }); } const { pid } = pnid; From 7b9534f2a8d6c9d5c2749b738e29ed82caa11655 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 25 Sep 2022 18:19:05 -0400 Subject: [PATCH 033/105] Export database connection --- src/database.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/database.js b/src/database.js index 66eb5fd..1468975 100644 --- a/src/database.js +++ b/src/database.js @@ -233,6 +233,7 @@ async function removeUserConnectionDiscord(pnid) { module.exports = { connect, + connection, getUserByUsername, getUserByPID, doesUserExist, From 9f77a0054c356b784eba53d9841c0ae23abbfbcc Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 25 Sep 2022 18:20:00 -0400 Subject: [PATCH 034/105] Added missing awaits for cache functions --- src/services/api/routes/v1/login.js | 4 ++-- src/services/api/routes/v1/register.js | 4 ++-- src/services/nasc/routes/ac.js | 4 ++-- src/services/nnid/routes/provider.js | 8 ++++---- src/util.js | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/services/api/routes/v1/login.js b/src/services/api/routes/v1/login.js index 29148fb..e791c5a 100644 --- a/src/services/api/routes/v1/login.js +++ b/src/services/api/routes/v1/login.js @@ -91,13 +91,13 @@ router.post('/', async (request, response) => { }); } - let publicKey = cache.getServicePublicKey('account'); + let publicKey= await cache.getServicePublicKey('account'); if (publicKey === null) { publicKey = await fs.readFile(`${cryptoPath}/public.pem`); await cache.setServicePublicKey('account', publicKey); } - let secretKey = cache.getServiceSecretKey('account'); + let secretKey= await cache.getServiceSecretKey('account'); if (secretKey === null) { secretKey = await fs.readFile(`${cryptoPath}/secret.key`); await cache.setServiceSecretKey('account', secretKey); diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 3998194..bfc3e05 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -311,13 +311,13 @@ router.post('/', async (request, response) => { }); } - let publicKey = cache.getServicePublicKey('account'); + let publicKey= await cache.getServicePublicKey('account'); if (publicKey === null) { publicKey = await fs.readFile(`${cryptoPath}/public.pem`); await cache.setServicePublicKey('account', publicKey); } - let secretKey = cache.getServiceSecretKey('account'); + let secretKey= await cache.getServiceSecretKey('account'); if (secretKey === null) { secretKey = await fs.readFile(`${cryptoPath}/secret.key`); await cache.setServiceSecretKey('account', secretKey); diff --git a/src/services/nasc/routes/ac.js b/src/services/nasc/routes/ac.js index b34c0b1..d6eaa26 100644 --- a/src/services/nasc/routes/ac.js +++ b/src/services/nasc/routes/ac.js @@ -55,13 +55,13 @@ async function processLoginRequest(request) { const cryptoPath = `${__dirname}/../../../../certs/nex/${service_name}`; - let publicKey = cache.getNEXPublicKey(service_name); + let publicKey= await cache.getNEXPublicKey(service_name); if (publicKey === null) { publicKey = await fs.readFile(`${cryptoPath}/public.pem`); await cache.setNEXPublicKey(service_name, publicKey); } - let secretKey = cache.getNEXSecretKey(service_name); + let secretKey= await cache.getNEXSecretKey(service_name); if (secretKey === null) { secretKey = await fs.readFile(`${cryptoPath}/secret.key`); await cache.setNEXSecretKey(service_name, secretKey); diff --git a/src/services/nnid/routes/provider.js b/src/services/nnid/routes/provider.js index da710d3..c60c2b8 100644 --- a/src/services/nnid/routes/provider.js +++ b/src/services/nnid/routes/provider.js @@ -44,13 +44,13 @@ router.get('/service_token/@me', async (request, response) => { }).end()); } - let publicKey = cache.getServicePublicKey(service_name); + let publicKey= await cache.getServicePublicKey(service_name); if (publicKey === null) { publicKey = await fs.readFile(`${cryptoPath}/public.pem`); await cache.setServicePublicKey(service_name, publicKey); } - let secretKey = cache.getServiceSecretKey(service_name); + let secretKey= await cache.getServiceSecretKey(service_name); if (secretKey === null) { secretKey = await fs.readFile(`${cryptoPath}/secret.key`); await cache.setServiceSecretKey(service_name, secretKey); @@ -134,13 +134,13 @@ router.get('/nex_token/@me', async (request, response) => { }).end()); } - let publicKey = cache.getNEXPublicKey(service_name); + let publicKey= await cache.getNEXPublicKey(service_name); if (publicKey === null) { publicKey = await fs.readFile(`${cryptoPath}/public.pem`); await cache.setNEXPublicKey(service_name, publicKey); } - let secretKey = cache.getNEXSecretKey(service_name); + let secretKey= await cache.getNEXSecretKey(service_name); if (secretKey === null) { secretKey = await fs.readFile(`${cryptoPath}/secret.key`); await cache.setNEXSecretKey(service_name, secretKey); diff --git a/src/util.js b/src/util.js index 26082e7..1ef6a2c 100644 --- a/src/util.js +++ b/src/util.js @@ -41,7 +41,7 @@ async function generateToken(cryptoOptions, tokenOptions) { // Access and refresh tokens use a different format since they must be much smaller // They take no extra crypto options if (!cryptoOptions) { - let aesKey = cache.getServiceAESKey('account', 'hex'); + let aesKey = await cache.getServiceAESKey('account', 'hex'); if (aesKey === null) { const fileBuffer = await fs.readFile(`${__dirname}/../certs/access/aes.key`, { encoding: 'utf8' }); @@ -135,7 +135,7 @@ async function decryptToken(token) { // Access and refresh tokens use a different format since they must be much smaller // Assume a small length means access or refresh token if (token.length <= 32) { - let aesKey = cache.getServiceAESKey('account', 'hex'); + let aesKey = await cache.getServiceAESKey('account', 'hex'); if (aesKey === null) { const fileBuffer = await fs.readFile(`${cryptoPath}/aes.key`, { encoding: 'utf8' }); @@ -153,13 +153,13 @@ async function decryptToken(token) { return decryptedBody; } - let privateKeyBytes = cache.getServicePrivateKey('account'); + let privateKeyBytes = await cache.getServicePrivateKey('account'); if (privateKeyBytes === null) { privateKeyBytes = await fs.readFile(`${cryptoPath}/private.pem`); await cache.setServicePrivateKey('account', privateKeyBytes); } - let secretKey = cache.getServiceSecretKey('account'); + let secretKey = await cache.getServiceSecretKey('account'); if (secretKey === null) { secretKey = await fs.readFile(`${cryptoPath}/secret.key`); await cache.setServiceSecretKey('account', secretKey); From c4ec5aafd3d1e6210b214ce2b705f56d37a39df4 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Mon, 26 Sep 2022 22:47:48 -0400 Subject: [PATCH 035/105] Export new connection data --- src/database.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/database.js b/src/database.js index 1468975..78ed760 100644 --- a/src/database.js +++ b/src/database.js @@ -9,10 +9,12 @@ const { uri, database, options } = config.mongoose; let connection; async function connect() { - await mongoose.connect(`${uri}/${database}`, options); + await mongoose.connect(`${uri}/${database}?replicaSet=rs0`, options); connection = mongoose.connection; connection.on('error', console.error.bind(console, 'connection error:')); + + module.exports.connection = connection; } function verifyConnected() { From a38b7d2165e7193236545b1a86eb9c10b7e21f9f Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Mon, 26 Sep 2022 22:48:26 -0400 Subject: [PATCH 036/105] Actually import cache --- src/services/api/routes/v1/login.js | 1 + src/services/api/routes/v1/register.js | 1 + src/services/nasc/routes/ac.js | 1 + src/services/nnid/routes/provider.js | 3 ++- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/services/api/routes/v1/login.js b/src/services/api/routes/v1/login.js index e791c5a..52a32d3 100644 --- a/src/services/api/routes/v1/login.js +++ b/src/services/api/routes/v1/login.js @@ -2,6 +2,7 @@ const router = require('express').Router(); const bcrypt = require('bcrypt'); const fs = require('fs-extra'); const database = require('../../../../database'); +const cache = require('../../../../cache'); const util = require('../../../../util'); /** diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index bfc3e05..b1508a3 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -7,6 +7,7 @@ const hcaptcha = require('hcaptcha'); const { PNID } = require('../../../../models/pnid'); const { NEXAccount } = require('../../../../models/nex-account'); const database = require('../../../../database'); +const cache = require('../../../../cache'); const util = require('../../../../util'); const config = require('../../../../../config.json'); diff --git a/src/services/nasc/routes/ac.js b/src/services/nasc/routes/ac.js index d6eaa26..6fe6b03 100644 --- a/src/services/nasc/routes/ac.js +++ b/src/services/nasc/routes/ac.js @@ -2,6 +2,7 @@ const fs = require('fs-extra'); const express = require('express'); const util = require('../../../util'); const database = require('../../../database'); +const cache = require('../../../cache'); const router = express.Router(); diff --git a/src/services/nnid/routes/provider.js b/src/services/nnid/routes/provider.js index c60c2b8..d046772 100644 --- a/src/services/nnid/routes/provider.js +++ b/src/services/nnid/routes/provider.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const { NEXAccount } = require('../../../models/nex-account'); const util = require('../../../util'); const database = require('../../../database'); +const cache = require('../../../cache'); /** * [GET] @@ -134,7 +135,7 @@ router.get('/nex_token/@me', async (request, response) => { }).end()); } - let publicKey= await cache.getNEXPublicKey(service_name); + let publicKey = await cache.getNEXPublicKey(service_name); if (publicKey === null) { publicKey = await fs.readFile(`${cryptoPath}/public.pem`); await cache.setNEXPublicKey(service_name, publicKey); From 635e830af3d4e8f082f63fec75aa8a0b5a034f49 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Mon, 26 Sep 2022 22:48:56 -0400 Subject: [PATCH 037/105] /v1/people POST not uses mongo transaction --- src/services/nnid/routes/people.js | 155 +++++++++++++++++------------ 1 file changed, 91 insertions(+), 64 deletions(-) diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index ebc058a..2ceffa1 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -8,6 +8,7 @@ const deviceCertificateMiddleware = require('../../../middleware/device-certific const ratelimit = require('../../../middleware/ratelimit'); const database = require('../../../database'); const mailer = require('../../../mailer'); +const logger = require('../../../../logger'); require('moment-timezone'); /** @@ -73,88 +74,114 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons }).end()); } - // Create new NEX account - const newNEXAccount = new NEXAccount({ - pid: 0, - password: '', - owning_pid: 0, - }); - await newNEXAccount.save(); - const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); + let pnid; + let nexAccount; + + const session = await database.connection.startSession(); + await session.startTransaction(); + + try { + const nexAccountResult = await NEXAccount.create([{ + pid: 0, + password: '', + owning_pid: 0, + }], { session }); + + nexAccount = nexAccountResult[0]; + + const pnidResult = await PNID.create([{ + pid: nexAccount.get('pid'), + creation_date: creationDate, + updated: creationDate, + username: person.get('user_id'), + password: person.get('password'), // will be hashed before saving + birthdate: person.get('birth_date'), + gender: person.get('gender'), + country: person.get('country'), + language: person.get('language'), + email: { + address: person.get('email').get('address'), + primary: person.get('email').get('primary') === 'Y', + parent: person.get('email').get('parent') === 'Y', + reachable: false, + validated: person.get('email').get('validated') === 'Y', + id: crypto.randomBytes(4).readUInt32LE() + }, + region: person.get('region'), + timezone: { + name: person.get('tz_name'), + offset: (moment.tz(person.get('tz_name')).utcOffset() * 60) + }, + mii: { + name: person.get('mii').get('name'), + primary: person.get('mii').get('name') === 'Y', + data: person.get('mii').get('data'), + id: crypto.randomBytes(4).readUInt32LE(), + hash: crypto.randomBytes(7).toString('hex'), + image_url: '', // deprecated, will be removed in the future + image_id: crypto.randomBytes(4).readUInt32LE() + }, + flags: { + active: true, + marketing: person.get('marketing_flag') === 'Y', + off_device: person.get('off_device_flag') === 'Y' + }, + validation: { + email_code: 1, // will be overwritten before saving + email_token: '' // will be overwritten before saving + } + }], { session }) + + pnid = pnidResult[0]; - const document = { - pid: newNEXAccount.get('pid'), - creation_date: creationDate, - updated: creationDate, - username: person.get('user_id'), - password: person.get('password'), // will be hashed before saving - birthdate: person.get('birth_date'), - gender: person.get('gender'), - country: person.get('country'), - language: person.get('language'), - email: { - address: person.get('email').get('address'), - primary: person.get('email').get('primary') === 'Y', - parent: person.get('email').get('parent') === 'Y', - reachable: false, - validated: person.get('email').get('validated') === 'Y', - id: crypto.randomBytes(4).readUInt32LE() - }, - region: person.get('region'), - timezone: { - name: person.get('tz_name'), - offset: (moment.tz(person.get('tz_name')).utcOffset() * 60) - }, - mii: { - name: person.get('mii').get('name'), - primary: person.get('mii').get('name') === 'Y', - data: person.get('mii').get('data'), - id: crypto.randomBytes(4).readUInt32LE(), - hash: crypto.randomBytes(7).toString('hex'), - image_url: '', // deprecated, will be removed in the future - image_id: crypto.randomBytes(4).readUInt32LE() - }, - flags: { - active: true, - marketing: person.get('marketing_flag') === 'Y', - off_device: person.get('off_device_flag') === 'Y' - }, - validation: { - email_code: 1, // will be overwritten before saving - email_token: '' // will be overwritten before saving - } - }; + // Quick hack to get the PIDs to match + // TODO: Change this + // NN with a NNID will always use the NNID PID + // even if the provided NEX PID is different + // To fix this we make them the same PID + await NEXAccount.updateOne({ pid: nexAccount.get('pid') }, { + owning_pid: nexAccount.get('pid') + }, { session }); - const newPNID = new PNID(document); - await newPNID.save(); + await session.commitTransaction(); + } catch (error) { + logger.error('[POST] /v1/api/people: ' + error); - // Quick hack to get the PIDs to match - // TODO: Change this - // NN with a NNID will always use the NNID PID - // even if the provided NEX PID is different - // To fix this we make them the same PID - await NEXAccount.updateOne({ pid: newNEXAccount.get('pid') }, { - owning_pid: newNEXAccount.get('pid') - }); + await session.abortTransaction(); + + response.status(400); + + return response.send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + } finally { + // * This runs regardless of failure + // * Returning on catch will not prevent this from running + await session.endSession(); + } await mailer.send( - newPNID.get('email'), + pnid.get('email'), '[Pretendo Network] Please confirm your e-mail address', `Hello, Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process. - https://account.pretendo.cc/account/email-confirmation?token=` + newPNID.get('identification.email_token') + ` + https://account.pretendo.cc/account/email-confirmation?token=` + pnid.get('identification.email_token') + ` If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked. - <<Confirmation code: ` + newPNID.get('identification.email_code') + '>>' + <<Confirmation code: ` + pnid.get('identification.email_code') + '>>' ); response.send(xmlbuilder.create({ person: { - pid: newPNID.get('pid') + pid: pnid.get('pid') } }).end()); }); From c9feca9ada3b5d1611c6fba5ead8fb040391e4e6 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Mon, 26 Sep 2022 22:57:39 -0400 Subject: [PATCH 038/105] NASC middleware now uses Mongo transaction --- src/middleware/nasc.js | 76 ++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/src/middleware/nasc.js b/src/middleware/nasc.js index e24756f..32f0782 100644 --- a/src/middleware/nasc.js +++ b/src/middleware/nasc.js @@ -2,6 +2,7 @@ const crypto = require('crypto'); const { Device } = require('../models/device'); const { NEXAccount } = require('../models/nex-account'); const util = require('../util'); +const database = require('../database'); const NintendoCertificate = require('../nintendo-certificate'); async function NASCMiddleware(request, response, next) { @@ -109,36 +110,53 @@ async function NASCMiddleware(request, response, next) { if (password && !pid && !pidHmac) { // Register new user - // Create new NEX account - const newNEXAccount = new NEXAccount({ - pid: 0, - password: '', - owning_pid: 0, - }); - await newNEXAccount.save(); - - pid = newNEXAccount.get('pid'); - - // Set password - await NEXAccount.updateOne({ pid }, { password }); - - if (!device) { - const deviceDocument = { - is_emulator: false, - model, - serial: serialNumber, - environment, - mac_hash: macAddressHash, - fcdcert_hash: fcdcertHash, - linked_pids: [pid] - }; - - device = new Device(deviceDocument); - } else { - device.linked_pids.push(pid); - } + const session = await database.connection.startSession(); + await session.startTransaction(); + + try { + // Create new NEX account + const nexAccountResult = await NEXAccount.create([{ + pid: 0, + password: '', + owning_pid: 0, + }], { session }); + + const nexAccount = nexAccountResult[0]; + + pid = nexAccount.get('pid'); + + // Set password + await NEXAccount.updateOne({ pid }, { password }, { session }); + + if (!device) { + device = new Device({ + is_emulator: false, + model, + serial: serialNumber, + environment, + mac_hash: macAddressHash, + fcdcert_hash: fcdcertHash, + linked_pids: [pid] + }); + } else { + device.linked_pids.push(pid); + } - await device.save(); + await device.save({ session }); + + await session.commitTransaction(); + } catch (error) { + logger.error('[NASC] REGISTER ACCOUNT: ' + error); + + await session.abortTransaction(); + + // 3DS expects 200 even on error + return response.status(200).send(util.nascError('102')); + } finally { + // * This runs regardless of failure + // * Returning on catch will not prevent this from running + await session.endSession(); + } } } From 6275cceca502d8ddfd8680e1c84656020a4269a8 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Tue, 27 Sep 2022 20:43:36 -0400 Subject: [PATCH 039/105] Stop acount server crashing during failed website token decrypt --- src/services/api/routes/v1/login.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/services/api/routes/v1/login.js b/src/services/api/routes/v1/login.js index 52a32d3..3a04c41 100644 --- a/src/services/api/routes/v1/login.js +++ b/src/services/api/routes/v1/login.js @@ -68,10 +68,7 @@ router.post('/', async (request, response) => { }); } } else { - const decryptedToken = await util.decryptToken(Buffer.from(refresh_token, 'base64')); - const unpackedToken = util.unpackToken(decryptedToken); - - pnid = await database.getUserByPID(unpackedToken.pid); + pnid = await database.getUserBearer(refresh_token); if (!pnid) { return response.status(400).json({ app: 'api', From c6dd21266fd1bf8d701b4959e2b32725603f46d4 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Tue, 27 Sep 2022 20:56:12 -0400 Subject: [PATCH 040/105] /v1/register API now uses mongo transaction --- src/services/api/routes/v1/register.js | 90 ++++++++++++++++++++++++++ src/services/nnid/routes/people.js | 2 +- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index b1508a3..5577fe9 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -9,6 +9,7 @@ const { NEXAccount } = require('../../../../models/nex-account'); const database = require('../../../../database'); const cache = require('../../../../cache'); const util = require('../../../../util'); +const logger = require('../../../../../logger'); const config = require('../../../../../config.json'); const PNID_VALID_CHARACTERS_REGEX = /^[\w\-\.]*$/gm; @@ -236,6 +237,7 @@ router.post('/', async (request, response) => { const MII_DATA = Buffer.concat([MII_DATA_FIRST, MII_DATA_NAME, MII_DATA_LAST]); // Build Mii data + /* // Create new NEX account const newNEXAccount = new NEXAccount({ pid: 0, @@ -300,6 +302,94 @@ router.post('/', async (request, response) => { await NEXAccount.updateOne({ pid: newNEXAccount.get('pid') }, { owning_pid: newNEXAccount.get('pid') }); + */ + + const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); + let pnid; + let nexAccount; + + const session = await database.connection.startSession(); + await session.startTransaction(); + + try { + const nexAccountResult = await NEXAccount.create([{ + pid: 0, + password: '', + owning_pid: 0, + }], { session }); + + nexAccount = nexAccountResult[0]; + + const pnidResult = await PNID.create([{ + pid: nexAccount.get('pid'), + creation_date: creationDate, + updated: creationDate, + username: username, + password: password, // will be hashed before saving + birthdate: '1990-01-01', // TODO: Change this + gender: 'M', // TODO: Change this + country: 'US', // TODO: Change this + language: 'en', // TODO: Change this + email: { + address: email, + primary: true, // TODO: Change this + parent: true, // TODO: Change this + reachable: false, // TODO: Change this + validated: false, // TODO: Change this + id: crypto.randomBytes(4).readUInt32LE() + }, + region: 0x310B0000, // TODO: Change this + timezone: { + name: 'America/New_York', // TODO: Change this + offset: -14400 // TODO: Change this + }, + mii: { + name: miiName, + primary: true, // TODO: Change this + data: MII_DATA.toString('base64'), + id: crypto.randomBytes(4).readUInt32LE(), + hash: crypto.randomBytes(7).toString('hex'), + image_url: '', // deprecated, will be removed in the future + image_id: crypto.randomBytes(4).readUInt32LE() + }, + flags: { + active: true, // TODO: Change this + marketing: true, // TODO: Change this + off_device: true // TODO: Change this + }, + validation: { + email_code: 1, // will be overwritten before saving + email_token: '' // will be overwritten before saving + } + }], { session }); + + pnid = pnidResult[0]; + + // Quick hack to get the PIDs to match + // TODO: Change this + // NN with a NNID will always use the NNID PID + // even if the provided NEX PID is different + // To fix this we make them the same PID + await NEXAccount.updateOne({ pid: nexAccount.get('pid') }, { + owning_pid: nexAccount.get('pid') + }, { session }); + + await session.commitTransaction(); + } catch (error) { + logger.error('[POST] /v1/api/people: ' + error); + + await session.abortTransaction(); + + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Password must have combination of letters, numbers, and/or punctuation characters' + }); + } finally { + // * This runs regardless of failure + // * Returning on catch will not prevent this from running + await session.endSession(); + } const cryptoPath = `${__dirname}/../../../../../certs/access`; diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index 2ceffa1..b090ffa 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -131,7 +131,7 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons email_code: 1, // will be overwritten before saving email_token: '' // will be overwritten before saving } - }], { session }) + }], { session }); pnid = pnidResult[0]; From 3977f8633830e8d1830372cf87ae90dfd34f0f2d Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 28 Sep 2022 12:14:50 -0400 Subject: [PATCH 041/105] Removed query injection from connection add --- src/database.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/database.js b/src/database.js index 78ed760..c64e543 100644 --- a/src/database.js +++ b/src/database.js @@ -1,11 +1,17 @@ const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); +const joi = require('joi'); const util = require('./util'); const { PNID } = require('./models/pnid'); const { Server } = require('./models/server'); const config = require('../config.json'); const { uri, database, options } = config.mongoose; +// TODO: Extend this later with more settings +const discordConnectionSchema = joi.object({ + id: joi.string() +}); + let connection; async function connect() { @@ -193,7 +199,9 @@ async function addUserConnection(pnid, data, type) { } async function addUserConnectionDiscord(pnid, data) { - if (!data.id) { + const valid = discordConnectionSchema.validate(data); + + if (valid.error) { return { app: 'api', status: 400, @@ -203,7 +211,7 @@ async function addUserConnectionDiscord(pnid, data) { await PNID.updateOne({ pid: pnid.get('pid') }, { $set: { - 'connections.discord': data + 'connections.discord.id': data.id } }); From 992ba062b955b304d5efaca4e2704205d38e922a Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 28 Sep 2022 12:20:35 -0400 Subject: [PATCH 042/105] Removed old comments --- src/services/api/routes/v1/register.js | 67 -------------------------- 1 file changed, 67 deletions(-) diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 5577fe9..b935db7 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -237,73 +237,6 @@ router.post('/', async (request, response) => { const MII_DATA = Buffer.concat([MII_DATA_FIRST, MII_DATA_NAME, MII_DATA_LAST]); // Build Mii data - /* - // Create new NEX account - const newNEXAccount = new NEXAccount({ - pid: 0, - password: '', - owning_pid: 0, - }); - await newNEXAccount.save(); - - const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); - - const document = { - pid: newNEXAccount.get('pid'), - creation_date: creationDate, - updated: creationDate, - username: username, - password: password, // will be hashed before saving - birthdate: '1990-01-01', // TODO: Change this - gender: 'M', // TODO: Change this - country: 'US', // TODO: Change this - language: 'en', // TODO: Change this - email: { - address: email, - primary: true, // TODO: Change this - parent: true, // TODO: Change this - reachable: false, // TODO: Change this - validated: false, // TODO: Change this - id: crypto.randomBytes(4).readUInt32LE() - }, - region: 0x310B0000, // TODO: Change this - timezone: { - name: 'America/New_York', // TODO: Change this - offset: -14400 // TODO: Change this - }, - mii: { - name: miiName, - primary: true, // TODO: Change this - data: MII_DATA.toString('base64'), - id: crypto.randomBytes(4).readUInt32LE(), - hash: crypto.randomBytes(7).toString('hex'), - image_url: '', // deprecated, will be removed in the future - image_id: crypto.randomBytes(4).readUInt32LE() - }, - flags: { - active: true, // TODO: Change this - marketing: true, // TODO: Change this - off_device: true // TODO: Change this - }, - validation: { - email_code: 1, // will be overwritten before saving - email_token: '' // will be overwritten before saving - } - }; - - const pnid = new PNID(document); - await pnid.save(); - - // Quick hack to get the PIDs to match - // TODO: Change this - // NN with a NNID will always use the NNID PID - // even if the provided NEX PID is different - // To fix this we make them the same PID - await NEXAccount.updateOne({ pid: newNEXAccount.get('pid') }, { - owning_pid: newNEXAccount.get('pid') - }); - */ - const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); let pnid; let nexAccount; From 27a78270cc15bf703ba2bf45a235e458fd80ecb4 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 28 Sep 2022 13:01:57 -0400 Subject: [PATCH 043/105] Removed pre-save from PNID --- src/models/pnid.js | 18 ------------------ src/services/api/routes/v1/register.js | 11 ++++++++++- src/services/nnid/routes/people.js | 11 ++++++++++- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/models/pnid.js b/src/models/pnid.js index a1e743e..6719352 100644 --- a/src/models/pnid.js +++ b/src/models/pnid.js @@ -224,24 +224,6 @@ PNIDSchema.methods.getServerMode = function () { return serverMode; }; -PNIDSchema.pre('save', async function(next) { - if (!this.isModified('password')) { - return next(); - } - - this.set('usernameLower', this.get('username').toLowerCase()); - //await this.generatePID(); - await this.generateEmailValidationCode(); - await this.generateEmailValidationToken(); - await this.generateMiiImages(); - - const primaryHash = util.nintendoPasswordHash(this.get('password'), this.get('pid')); - const hash = bcrypt.hashSync(primaryHash, 10); - - this.set('password', hash); - next(); -}); - const PNID = model('PNID', PNIDSchema); module.exports = { diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index b935db7..e5e8fb5 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const moment = require('moment'); const crypto = require('crypto'); const hcaptcha = require('hcaptcha'); +const bcrypt = require('bcrypt'); const { PNID } = require('../../../../models/pnid'); const { NEXAccount } = require('../../../../models/nex-account'); const database = require('../../../../database'); @@ -253,12 +254,16 @@ router.post('/', async (request, response) => { nexAccount = nexAccountResult[0]; + const primaryPasswordHash = util.nintendoPasswordHash(password, nexAccount.get('pid')); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); + const pnidResult = await PNID.create([{ pid: nexAccount.get('pid'), creation_date: creationDate, updated: creationDate, username: username, - password: password, // will be hashed before saving + usernameLower: username.toLowerCase(), + password: passwordHash, birthdate: '1990-01-01', // TODO: Change this gender: 'M', // TODO: Change this country: 'US', // TODO: Change this @@ -298,6 +303,10 @@ router.post('/', async (request, response) => { pnid = pnidResult[0]; + await pnid.generateEmailValidationCode(); + await pnid.generateEmailValidationToken(); + await pnid.generateMiiImages(); + // Quick hack to get the PIDs to match // TODO: Change this // NN with a NNID will always use the NNID PID diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index b090ffa..6ccebc2 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -2,6 +2,7 @@ const router = require('express').Router(); const xmlbuilder = require('xmlbuilder'); const moment = require('moment'); const crypto = require('crypto'); +const bcrypt = require('bcrypt'); const { PNID } = require('../../../models/pnid'); const { NEXAccount } = require('../../../models/nex-account'); const deviceCertificateMiddleware = require('../../../middleware/device-certificate'); @@ -90,12 +91,16 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons nexAccount = nexAccountResult[0]; + const primaryPasswordHash = util.nintendoPasswordHash(person.get('password'), nexAccount.get('pid')); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); + const pnidResult = await PNID.create([{ pid: nexAccount.get('pid'), creation_date: creationDate, updated: creationDate, username: person.get('user_id'), - password: person.get('password'), // will be hashed before saving + usernameLower: person.get('user_id').toLowerCase(), + password: passwordHash, birthdate: person.get('birth_date'), gender: person.get('gender'), country: person.get('country'), @@ -135,6 +140,10 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons pnid = pnidResult[0]; + await pnid.generateEmailValidationCode(); + await pnid.generateEmailValidationToken(); + await pnid.generateMiiImages(); + // Quick hack to get the PIDs to match // TODO: Change this // NN with a NNID will always use the NNID PID From 5ffd6c5a9d95d0172881d1e6461d13ba3628ea76 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 28 Sep 2022 18:28:02 -0400 Subject: [PATCH 044/105] Made NEX accounts unique per-device type --- src/middleware/nasc.js | 7 ++++--- src/models/nex-account.js | 26 ++++++++++++-------------- src/models/pnid.js | 2 +- src/services/api/routes/v1/register.js | 13 ++++++++----- src/services/nnid/routes/people.js | 9 +++++---- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/middleware/nasc.js b/src/middleware/nasc.js index 32f0782..8367939 100644 --- a/src/middleware/nasc.js +++ b/src/middleware/nasc.js @@ -116,13 +116,14 @@ async function NASCMiddleware(request, response, next) { try { // Create new NEX account const nexAccountResult = await NEXAccount.create([{ - pid: 0, - password: '', - owning_pid: 0, + device_type: '3ds', }], { session }); const nexAccount = nexAccountResult[0]; + await nexAccount.generatePID(); + await nexAccount.generatePassword(); + pid = nexAccount.get('pid'); // Set password diff --git a/src/models/nex-account.js b/src/models/nex-account.js index 6f91bbf..503d246 100644 --- a/src/models/nex-account.js +++ b/src/models/nex-account.js @@ -2,10 +2,15 @@ const { Schema, model } = require('mongoose'); const uniqueValidator = require('mongoose-unique-validator'); const NEXAccountSchema = new Schema({ - pid: { - type: Number, - unique: true + device_type: { + type: String, + enum: [ + // Only track the family here not the model + 'wiiu', + '3ds', + ] }, + pid: Number, password: String, owning_pid: Number, access_level: { @@ -18,6 +23,8 @@ const NEXAccountSchema = new Schema({ }, }); +NEXAccountSchema.index({ device_type: 1, pid: 1 }, { unique: true }) + NEXAccountSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); /* @@ -35,7 +42,8 @@ NEXAccountSchema.methods.generatePID = async function () { let pid = Math.floor(Math.random() * (max - min + 1) + min); const inuse = await NEXAccount.findOne({ - pid + pid, + device_type: this.get('device_type') }); pid = (inuse ? await NEXAccount.generatePID() : pid); @@ -60,16 +68,6 @@ NEXAccountSchema.methods.generatePassword = function () { this.set('password', output.join('')); }; -NEXAccountSchema.pre('save', async function (next) { - await this.generatePID(); - - if (this.get('password') === '') { - await this.generatePassword(); - } - - next(); -}); - const NEXAccount = model('NEXAccount', NEXAccountSchema); module.exports = { diff --git a/src/models/pnid.js b/src/models/pnid.js index 6719352..9475492 100644 --- a/src/models/pnid.js +++ b/src/models/pnid.js @@ -136,7 +136,7 @@ PNIDSchema.methods.generateEmailValidationCode = async function() { const inuse = await PNID.findOne({ 'identification.email_code': code }); - + code = (inuse ? await PNID.generateEmailValidationCode() : code); this.set('identification.email_code', code); diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index e5e8fb5..5e1693c 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -246,14 +246,17 @@ router.post('/', async (request, response) => { await session.startTransaction(); try { + // * PNIDs can only be registered from a Wii U + // * So assume website users are WiiU NEX accounts const nexAccountResult = await NEXAccount.create([{ - pid: 0, - password: '', - owning_pid: 0, + device_type: 'wiiu', }], { session }); nexAccount = nexAccountResult[0]; + await nexAccount.generatePID(); + await nexAccount.generatePassword(); + const primaryPasswordHash = util.nintendoPasswordHash(password, nexAccount.get('pid')); const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); @@ -295,7 +298,7 @@ router.post('/', async (request, response) => { marketing: true, // TODO: Change this off_device: true // TODO: Change this }, - validation: { + identification: { email_code: 1, // will be overwritten before saving email_token: '' // will be overwritten before saving } @@ -318,7 +321,7 @@ router.post('/', async (request, response) => { await session.commitTransaction(); } catch (error) { - logger.error('[POST] /v1/api/people: ' + error); + logger.error('[POST] /v1/register: ' + error); await session.abortTransaction(); diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index 6ccebc2..007737f 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -84,13 +84,14 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons try { const nexAccountResult = await NEXAccount.create([{ - pid: 0, - password: '', - owning_pid: 0, + device_type: 'wiiu', }], { session }); nexAccount = nexAccountResult[0]; + await nexAccount.generatePID(); + await nexAccount.generatePassword(); + const primaryPasswordHash = util.nintendoPasswordHash(person.get('password'), nexAccount.get('pid')); const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); @@ -132,7 +133,7 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons marketing: person.get('marketing_flag') === 'Y', off_device: person.get('off_device_flag') === 'Y' }, - validation: { + identification: { email_code: 1, // will be overwritten before saving email_token: '' // will be overwritten before saving } From 7991038f8a1254c5f099be007b7a5a242b608e08 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 28 Sep 2022 18:40:20 -0400 Subject: [PATCH 045/105] Fixed PNID and NEX account data not saving --- src/middleware/nasc.js | 11 ++++----- src/services/api/routes/v1/register.js | 30 +++++++++++------------- src/services/nnid/routes/people.js | 32 ++++++++++++-------------- 3 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/middleware/nasc.js b/src/middleware/nasc.js index 8367939..4bb91a9 100644 --- a/src/middleware/nasc.js +++ b/src/middleware/nasc.js @@ -115,19 +115,18 @@ async function NASCMiddleware(request, response, next) { try { // Create new NEX account - const nexAccountResult = await NEXAccount.create([{ + const nexAccount = await new NEXAccount({ device_type: '3ds', - }], { session }); - - const nexAccount = nexAccountResult[0]; + password + }); await nexAccount.generatePID(); - await nexAccount.generatePassword(); + + await nexAccount.save({ session }); pid = nexAccount.get('pid'); // Set password - await NEXAccount.updateOne({ pid }, { password }, { session }); if (!device) { device = new Device({ diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 5e1693c..5206e31 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -248,19 +248,26 @@ router.post('/', async (request, response) => { try { // * PNIDs can only be registered from a Wii U // * So assume website users are WiiU NEX accounts - const nexAccountResult = await NEXAccount.create([{ + nexAccount = new NEXAccount({ device_type: 'wiiu', - }], { session }); - - nexAccount = nexAccountResult[0]; + }); await nexAccount.generatePID(); await nexAccount.generatePassword(); + // Quick hack to get the PIDs to match + // TODO: Change this maybe? + // NN with a NNID will always use the NNID PID + // even if the provided NEX PID is different + // To fix this we make them the same PID + nexAccount.owning_pid = nexAccount.get('pid'); + + await nexAccount.save({ session }); + const primaryPasswordHash = util.nintendoPasswordHash(password, nexAccount.get('pid')); const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); - const pnidResult = await PNID.create([{ + pnid = new PNID({ pid: nexAccount.get('pid'), creation_date: creationDate, updated: creationDate, @@ -302,22 +309,13 @@ router.post('/', async (request, response) => { email_code: 1, // will be overwritten before saving email_token: '' // will be overwritten before saving } - }], { session }); - - pnid = pnidResult[0]; + }); await pnid.generateEmailValidationCode(); await pnid.generateEmailValidationToken(); await pnid.generateMiiImages(); - // Quick hack to get the PIDs to match - // TODO: Change this - // NN with a NNID will always use the NNID PID - // even if the provided NEX PID is different - // To fix this we make them the same PID - await NEXAccount.updateOne({ pid: nexAccount.get('pid') }, { - owning_pid: nexAccount.get('pid') - }, { session }); + await pnid.save({ session }); await session.commitTransaction(); } catch (error) { diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index 007737f..eab9b27 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -83,19 +83,26 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons await session.startTransaction(); try { - const nexAccountResult = await NEXAccount.create([{ + nexAccount = new NEXAccount({ device_type: 'wiiu', - }], { session }); - - nexAccount = nexAccountResult[0]; + }); await nexAccount.generatePID(); await nexAccount.generatePassword(); - const primaryPasswordHash = util.nintendoPasswordHash(person.get('password'), nexAccount.get('pid')); + // Quick hack to get the PIDs to match + // TODO: Change this maybe? + // NN with a NNID will always use the NNID PID + // even if the provided NEX PID is different + // To fix this we make them the same PID + nexAccount.owning_pid = nexAccount.get('pid'); + + await nexAccount.save({ session }); + + const primaryPasswordHash = util.nintendoPasswordHash(password, nexAccount.get('pid')); const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); - const pnidResult = await PNID.create([{ + pnid = new PNID({ pid: nexAccount.get('pid'), creation_date: creationDate, updated: creationDate, @@ -137,22 +144,13 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons email_code: 1, // will be overwritten before saving email_token: '' // will be overwritten before saving } - }], { session }); - - pnid = pnidResult[0]; + }); await pnid.generateEmailValidationCode(); await pnid.generateEmailValidationToken(); await pnid.generateMiiImages(); - // Quick hack to get the PIDs to match - // TODO: Change this - // NN with a NNID will always use the NNID PID - // even if the provided NEX PID is different - // To fix this we make them the same PID - await NEXAccount.updateOne({ pid: nexAccount.get('pid') }, { - owning_pid: nexAccount.get('pid') - }, { session }); + await pnid.save({ session }); await session.commitTransaction(); } catch (error) { From ad3b62dd9c4e7744c1dcd3b14cc1fa2f017c60e3 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 28 Sep 2022 18:46:36 -0400 Subject: [PATCH 046/105] Added NEX account migration script --- .../migration.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 migrations/add-console-type-to-nex-account/migration.js diff --git a/migrations/add-console-type-to-nex-account/migration.js b/migrations/add-console-type-to-nex-account/migration.js new file mode 100644 index 0000000..af581b4 --- /dev/null +++ b/migrations/add-console-type-to-nex-account/migration.js @@ -0,0 +1,32 @@ +const database = require('../../src/database'); +const { NEXAccount } = require('../../src/models/nex-account'); + +database.connect().then(async function () { + const nexAccounts = await NEXAccount.find({}); + const nexAccounts3DS = await NEXAccount.find({ device_type: '3ds' }); + const nexAccountsWiiU = await NEXAccount.find({ device_type: 'wiiu' }); + + console.log('NEX accounts:', nexAccounts.length); + console.log('NEX accounts (3DS):', nexAccounts3DS.length); + console.log('NEX accounts (WiiU):', nexAccountsWiiU.length); + + for (const nexAccount of nexAccounts) { + let deviceType = ''; + + if (nexAccount.owning_pid !== nexAccount.pid) { + // 3DS account + deviceType = '3ds'; + } else { + // WiiU account + deviceType = 'wiiu'; + } + + nexAccount.device_type = deviceType; + + await nexAccount.save(); + } + + console.log('Migrated accounts'); + + process.exit(0); +}); \ No newline at end of file From 7310d2a798a3d6d785e6a0248a71fee147a37193 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Thu, 29 Sep 2022 10:10:11 -0400 Subject: [PATCH 047/105] Add catch to main() in server.js --- src/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.js b/src/server.js index 343bf05..5711f6d 100644 --- a/src/server.js +++ b/src/server.js @@ -83,4 +83,4 @@ async function main() { }); } -main(); \ No newline at end of file +main().catch(console.error); \ No newline at end of file From dc77b2f62bd7241b9209906ee55856272544f7b8 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Thu, 29 Sep 2022 10:13:02 -0400 Subject: [PATCH 048/105] Update example config --- example.config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example.config.json b/example.config.json index 7742588..4ad707b 100644 --- a/example.config.json +++ b/example.config.json @@ -24,5 +24,6 @@ }, "hcaptcha": { "secret": "0x0000000000000000000000000000000000000000" - } + }, + "cdn_base": "https://example.com" } \ No newline at end of file From fe4630f344a5ac241b65688a2923c9dfbc5fa1ba Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 30 Sep 2022 21:20:35 -0400 Subject: [PATCH 049/105] Updated generate-keys script --- generate-keys.js | 172 ++++++++++++++++++++++++++++++----------------- 1 file changed, 112 insertions(+), 60 deletions(-) diff --git a/generate-keys.js b/generate-keys.js index 09fce5c..1c262d4 100644 --- a/generate-keys.js +++ b/generate-keys.js @@ -1,79 +1,129 @@ const NodeRSA = require('node-rsa'); const crypto = require('crypto'); const fs = require('fs-extra'); +const yesno = require('yesno'); +const logger = require('./logger'); require('colors'); -const args = process.argv.slice(2); +const ALLOWED_CHARS_REGEX = /[^a-zA-Z0-9_-]/g; -if (args.length < 1) { - usage(); - return; -} - -const [type, name] = args; - -if (!['nex', 'service', 'access'].includes(type)) { - usage(); - return; -} +async function main() { + const args = process.argv.slice(2); -if (type !== 'access' && (!name || name.trim() === '')) { - usage(); - return; -} - -let path; - -if (type === 'access') { - path = `${__dirname}/certs/${type}`; -} else { - path = `${__dirname}/certs/${type}/${name}`; -} + if (args.length < 1) { + logger.error('Must pass in type and optional name'); + usage(); + return; + } -// Ensure the output directories exist -console.log('Creating output directories'.brightGreen); -fs.ensureDirSync(path); + let [type, name] = args; -// Generate new AES key -console.log('Generating AES key'.brightGreen); -const aesKey = crypto.randomBytes(16); + type = type.toLowerCase().trim(); -// Saving AES key -fs.writeFileSync(`${path}/aes.key`, aesKey.toString('hex')); -console.log(`Saved AES key to file ${path}/aes.key`.brightBlue); + if (name) { + name = name.toLowerCase().trim(); -const key = new NodeRSA({ b: 1024}, null, { - environment: 'browser', - encryptionScheme: { - 'hash': 'sha256', + if (ALLOWED_CHARS_REGEX.test(name)) { + logger.error(`Invalid name. Names must only contain [^a-zA-Z0-9_-]. Got ${name}`); + return; + } } -}); -// Generate new key pair -console.log('Generating RSA key pair'.brightGreen, '(this may take a while)'.yellow.bold); -key.generateKeyPair(1024); + if (!['nex', 'service', 'account'].includes(type)) { + logger.error(`Invalid type. Expected nex, service, or account. Got ${type}`); + usage(); + return; + } -// Export the keys -console.log('Exporting public key'.brightGreen); -const publickKey = key.exportKey('public'); + if (type !== 'account' && (!name || name === '')) { + logger.error('If type is not account, a name MUST be passed'); + usage(); + return; + } + -// Saving public key -fs.writeFileSync(`${path}/public.pem`, publickKey); -console.log(`Saved public key to file ${path}/public.pem`.brightBlue); + if (type === 'service' && name === 'account') { + logger.error('Cannot use service name \'account\'. Reserved'); + usage(); + return; + } -console.log('Exporting private key'.brightGreen); -const privatekKey = key.exportKey('private'); + const path = path = `${__dirname}/certs/${type}/${name}`; -// Saving private key -fs.writeFileSync(`${path}/private.pem`, privatekKey); -console.log(`Saved public key to file ${path}/private.pem`.brightBlue); + if (fs.pathExistsSync(path)) { + const overwrite = await yesno({ + question: 'Keys found for type name, overwrite existing keys?' + }); -// Create HMAC secret key -console.log('Generating HMAC secret'.brightGreen); -const secret = crypto.randomBytes(16); -fs.writeFileSync(`${path}/secret.key`, secret.toString('hex')); + if (!overwrite) { + logger.info('Not overwriting existing keys. Exiting program'); + return; + } + } -console.log(`Saved HMAC secret to file ${path}/secret.key`.brightBlue); + const publicKeyPath = `${path}/public.pem`; + const privateKeyPath = `${path}/private.pem`; + const aesKeyPath = `${path}/aes.key`; + const secretKeyPath = `${path}/secret.key`; + + // Ensure the output directories exist + logger.info('Creating output directories...'); + fs.ensureDirSync(path); + logger.success('Created output directories!'); + + const key = new NodeRSA({ b: 1024 }, null, { + environment: 'browser', + encryptionScheme: { + 'hash': 'sha256', + } + }); + + // Generate new key pair + logger.info('Generating RSA key pair...'); + logger.warn('(this may take a while)') + key.generateKeyPair(1024); + logger.success('Generated RSA key pair!'); + + // Export the keys + logger.info('Exporting public key...'); + const publicKey = key.exportKey('public'); + logger.success('Exported public key!'); + + // Saving public key + logger.info('Saving public key to disk...'); + fs.writeFileSync(publicKeyPath, publicKey); + logger.success(`Saved public key to ${publicKeyPath}!`); + + logger.info('Exporting private key...'); + const privateKey = key.exportKey('private'); + logger.success('Exported private key!'); + + // Saving private key + logger.info('Saving private key to disk...'); + fs.writeFileSync(privateKeyPath, privateKey); + logger.success(`Saved private key to ${privateKeyPath}!`); + + // Generate new AES key + logger.info('Generating AES key...'); + const aesKey = crypto.randomBytes(16); + logger.success('Generated AES key!'); + + // Saving AES key + logger.info('Saving AES key to disk...'); + fs.writeFileSync(aesKeyPath, aesKey.toString('hex')); + logger.success(`Saved AES key to ${aesKeyPath}!`); + + // Create HMAC secret key + logger.info('Generating HMAC secret...'); + const secret = crypto.randomBytes(16); + logger.success('Generated RSA key pair!'); + + logger.info('Saving HMAC secret to disk...'); + fs.writeFileSync(secretKeyPath, secret.toString('hex')); + logger.success(`Saved HMAC secret to ${secretKeyPath}!`); + + logger.success('Keys generated successfully'); +} // Display usage information function usage() { @@ -82,7 +132,9 @@ function usage() { console.log('Types:'); console.log(' - nex'); console.log(' - service'); - console.log(' - access'); + console.log(' - account'); + + console.log('Name: Service or NEX server name. Not used in account type'); +} - console.log('Name: service or nex server name. Not used in access type'); -} \ No newline at end of file +main().catch(logger.error); \ No newline at end of file From 14f2331901eaecc9853e18da6dd2cb2439192953 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 30 Sep 2022 21:24:14 -0400 Subject: [PATCH 050/105] Redis cache now auto-reads files --- package-lock.json | 15 ++++- package.json | 3 +- src/cache.js | 80 +++++++++++++++++++++++--- src/database.js | 7 ++- src/services/api/routes/v1/login.js | 15 +---- src/services/api/routes/v1/register.js | 16 ++---- src/services/nasc/routes/ac.js | 13 +---- src/services/nnid/routes/oauth.js | 6 +- src/services/nnid/routes/provider.js | 28 ++------- src/util.js | 34 ++--------- 10 files changed, 114 insertions(+), 103 deletions(-) diff --git a/package-lock.json b/package-lock.json index e51a154..f70fa94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,8 @@ }, "devDependencies": { "node-rsa": "^1.0.7", - "prompt": "^1.0.0" + "prompt": "^1.0.0", + "yesno": "^0.4.0" } }, "node_modules/@colors/colors": { @@ -3664,6 +3665,12 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yesno": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/yesno/-/yesno-0.4.0.tgz", + "integrity": "sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==", + "dev": true } }, "dependencies": { @@ -6576,6 +6583,12 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yesno": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/yesno/-/yesno-0.4.0.tgz", + "integrity": "sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==", + "dev": true } } } diff --git a/package.json b/package.json index 79d5354..bbd7bec 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ }, "devDependencies": { "node-rsa": "^1.0.7", - "prompt": "^1.0.0" + "prompt": "^1.0.0", + "yesno": "^0.4.0" } } diff --git a/src/cache.js b/src/cache.js index f6772a3..4db15bb 100644 --- a/src/cache.js +++ b/src/cache.js @@ -1,6 +1,10 @@ +const fs = require('fs-extra'); const redis = require('redis'); let client; +const SERVICE_CERTS_BASE = `${__dirname}/../certs/service`; +const NEX_CERTS_BASE = `${__dirname}/../certs/nex`; + async function connect() { client = redis.createClient(); client.on('error', (err) => console.log('Redis Client Error', err)); @@ -25,19 +29,49 @@ async function getCachedFile(type, name, fileName, encoding) { // NEX server cache functions async function getNEXPublicKey(name, encoding) { - return await getCachedFile(`nex:${name}:public_key`, encoding); + let publicKey = await getCachedFile(`nex:${name}:public_key`, encoding); + + if (publicKey === null) { + publicKey = await fs.readFile(`${NEX_CERTS_BASE}/${name}/public.pem`, { encoding }); + await setNEXPublicKey(name, publicKey); + } + + return publicKey; } async function getNEXPrivateKey(name, encoding) { - return await getCachedFile(`nex:${name}:private_key`, encoding); + let privateKey = await getCachedFile(`nex:${name}:private_key`, encoding); + + if (privateKey === null) { + privateKey = await fs.readFile(`${NEX_CERTS_BASE}/${name}/private.pem`, { encoding }); + await setNEXPrivateKey(name, privateKey); + } + + return privateKey; } async function getNEXSecretKey(name, encoding) { - return await getCachedFile(`nex:${name}:secret_key`, encoding); + let secretKey = await getCachedFile(`nex:${name}:secret_key`, encoding); + + if (secretKey === null) { + const fileBuffer = await fs.readFile(`${NEX_CERTS_BASE}/${name}/secret.key`, { encoding: 'utf8' }); + secretKey = Buffer.from(fileBuffer, encoding); + await setNEXSecretKey(name, secretKey); + } + + return secretKey; } async function getNEXAESKey(name, encoding) { - return await getCachedFile(`nex:${name}:aes_key`, encoding); + let aesKey = await getCachedFile(`nex:${name}:aes_key`, encoding); + + if (aesKey === null) { + const fileBuffer = await fs.readFile(`${NEX_CERTS_BASE}/${name}/aes.key`, { encoding: 'utf8' }); + aesKey = Buffer.from(fileBuffer, encoding); + await setNEXAESKey(name, aesKey); + } + + return secretKey; } async function setNEXPublicKey(name, value) { @@ -59,19 +93,49 @@ async function setNEXAESKey(name, value) { // 3rd party service cache functions async function getServicePublicKey(name, encoding) { - return await getCachedFile(`service:${name}:public_key`, encoding); + let publicKey = await getCachedFile(`service:${name}:public_key`, encoding); + + if (publicKey === null) { + publicKey = await fs.readFile(`${SERVICE_CERTS_BASE}/${name}/public.pem`, { encoding }); + await setServicePublicKey(name, publicKey); + } + + return publicKey; } async function getServicePrivateKey(name, encoding) { - return await getCachedFile(`service:${name}:private_key`, encoding); + let privateKey = await getCachedFile(`service:${name}:private_key`, encoding); + + if (privateKey === null) { + privateKey = await fs.readFile(`${SERVICE_CERTS_BASE}/${name}/private.pem`, { encoding }); + await setServicePrivateKey(name, privateKey); + } + + return privateKey; } async function getServiceSecretKey(name, encoding) { - return await getCachedFile(`service:${name}:secret_key`, encoding); + let secretKey = await getCachedFile(`service:${name}:secret_key`, encoding); + + if (secretKey === null) { + const fileBuffer = await fs.readFile(`${SERVICE_CERTS_BASE}/${name}/secret.key`, { encoding: 'utf8' }); + secretKey = Buffer.from(fileBuffer, encoding); + await setServiceSecretKey(name, secretKey); + } + + return secretKey; } async function getServiceAESKey(name, encoding) { - return await getCachedFile(`service:${name}:aes_key`, encoding); + let aesKey = await getCachedFile(`service:${name}:aes_key`, encoding); + + if (aesKey === null) { + const fileBuffer = await fs.readFile(`${SERVICE_CERTS_BASE}/${name}/aes.key`, { encoding: 'utf8' }); + aesKey = Buffer.from(fileBuffer, encoding); + await setServiceAESKey(name, aesKey); + } + + return aesKey; } async function setServicePublicKey(name, value) { diff --git a/src/database.js b/src/database.js index c64e543..4f7c67a 100644 --- a/src/database.js +++ b/src/database.js @@ -4,6 +4,7 @@ const joi = require('joi'); const util = require('./util'); const { PNID } = require('./models/pnid'); const { Server } = require('./models/server'); +const logger = require('../logger'); const config = require('../config.json'); const { uri, database, options } = config.mongoose; @@ -16,7 +17,7 @@ let connection; async function connect() { await mongoose.connect(`${uri}/${database}?replicaSet=rs0`, options); - + connection = mongoose.connection; connection.on('error', console.error.bind(console, 'connection error:')); @@ -100,9 +101,9 @@ async function getUserBearer(token) { return user; } catch (error) { // TODO: Handle error + logger.error(error); return null; } - } async function getUserProfileJSONByPID(pid) { @@ -118,7 +119,7 @@ async function getUserProfileJSONByPID(pid) { name, value }; - + if (created_date) { deviceAttributeDocument.created_date = created_date; } diff --git a/src/services/api/routes/v1/login.js b/src/services/api/routes/v1/login.js index 3a04c41..e342ea5 100644 --- a/src/services/api/routes/v1/login.js +++ b/src/services/api/routes/v1/login.js @@ -78,7 +78,7 @@ router.post('/', async (request, response) => { } } - const cryptoPath = `${__dirname}/../../../../../certs/access`; + const cryptoPath = `${__dirname}/../../../../../certs/service/account`; if (!await fs.pathExists(cryptoPath)) { // Need to generate keys @@ -89,17 +89,8 @@ router.post('/', async (request, response) => { }); } - let publicKey= await cache.getServicePublicKey('account'); - if (publicKey === null) { - publicKey = await fs.readFile(`${cryptoPath}/public.pem`); - await cache.setServicePublicKey('account', publicKey); - } - - let secretKey= await cache.getServiceSecretKey('account'); - if (secretKey === null) { - secretKey = await fs.readFile(`${cryptoPath}/secret.key`); - await cache.setServiceSecretKey('account', secretKey); - } + const publicKey = await cache.getServicePublicKey('account'); + const secretKey = await cache.getServiceSecretKey('account'); const cryptoOptions = { public_key: publicKey, diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 5206e31..d823646 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -98,6 +98,7 @@ router.post('/', async (request, response) => { } if (!PNID_VALID_CHARACTERS_REGEX.test(username)) { + console.log(Buffer.from(username)); return response.status(400).json({ app: 'api', status: 400, @@ -334,7 +335,7 @@ router.post('/', async (request, response) => { await session.endSession(); } - const cryptoPath = `${__dirname}/../../../../../certs/access`; + const cryptoPath = `${__dirname}/../../../../../certs/service/account`; if (!await fs.pathExists(cryptoPath)) { // Need to generate keys @@ -345,17 +346,8 @@ router.post('/', async (request, response) => { }); } - let publicKey= await cache.getServicePublicKey('account'); - if (publicKey === null) { - publicKey = await fs.readFile(`${cryptoPath}/public.pem`); - await cache.setServicePublicKey('account', publicKey); - } - - let secretKey= await cache.getServiceSecretKey('account'); - if (secretKey === null) { - secretKey = await fs.readFile(`${cryptoPath}/secret.key`); - await cache.setServiceSecretKey('account', secretKey); - } + const publicKey = await cache.getServicePublicKey('account'); + const secretKey = await cache.getServiceSecretKey('account'); const cryptoOptions = { public_key: publicKey, diff --git a/src/services/nasc/routes/ac.js b/src/services/nasc/routes/ac.js index 6fe6b03..41b7296 100644 --- a/src/services/nasc/routes/ac.js +++ b/src/services/nasc/routes/ac.js @@ -56,17 +56,8 @@ async function processLoginRequest(request) { const cryptoPath = `${__dirname}/../../../../certs/nex/${service_name}`; - let publicKey= await cache.getNEXPublicKey(service_name); - if (publicKey === null) { - publicKey = await fs.readFile(`${cryptoPath}/public.pem`); - await cache.setNEXPublicKey(service_name, publicKey); - } - - let secretKey= await cache.getNEXSecretKey(service_name); - if (secretKey === null) { - secretKey = await fs.readFile(`${cryptoPath}/secret.key`); - await cache.setNEXSecretKey(service_name, secretKey); - } + const publicKey = await cache.getNEXPublicKey(service_name); + const secretKey = await cache.getNEXSecretKey(service_name); const cryptoOptions = { public_key: publicKey, diff --git a/src/services/nnid/routes/oauth.js b/src/services/nnid/routes/oauth.js index b6a9998..21516ad 100644 --- a/src/services/nnid/routes/oauth.js +++ b/src/services/nnid/routes/oauth.js @@ -35,7 +35,7 @@ router.post('/access_token/generate', async (request, response) => { } }).end()); } - + if (!password || password.trim() === '') { response.status(400); return response.send(xmlbuilder.create({ @@ -70,7 +70,7 @@ router.post('/access_token/generate', async (request, response) => { }).end()); } - const cryptoPath = `${__dirname}/../../../../certs/access`; + const cryptoPath = `${__dirname}/../../../../certs/service/account`; if (!await fs.pathExists(cryptoPath)) { // Need to generate keys @@ -78,7 +78,7 @@ router.post('/access_token/generate', async (request, response) => { errors: { error: { code: '0000', - message: 'Could not find access key crypto path' + message: 'Could not find account access key crypto path' } } }).end()); diff --git a/src/services/nnid/routes/provider.js b/src/services/nnid/routes/provider.js index d046772..86fd9d1 100644 --- a/src/services/nnid/routes/provider.js +++ b/src/services/nnid/routes/provider.js @@ -45,17 +45,8 @@ router.get('/service_token/@me', async (request, response) => { }).end()); } - let publicKey= await cache.getServicePublicKey(service_name); - if (publicKey === null) { - publicKey = await fs.readFile(`${cryptoPath}/public.pem`); - await cache.setServicePublicKey(service_name, publicKey); - } - - let secretKey= await cache.getServiceSecretKey(service_name); - if (secretKey === null) { - secretKey = await fs.readFile(`${cryptoPath}/secret.key`); - await cache.setServiceSecretKey(service_name, secretKey); - } + const publicKey = await cache.getServicePublicKey(service_name); + const secretKey = await cache.getServiceSecretKey(service_name); const cryptoOptions = { public_key: publicKey, @@ -122,7 +113,7 @@ router.get('/nex_token/@me', async (request, response) => { const titleId = request.headers['x-nintendo-title-id']; const cryptoPath = `${__dirname}/../../../../certs/${service_type}/${service_name}`; - + if (!await fs.pathExists(cryptoPath)) { // Need to generate keys return response.send(xmlbuilder.create({ @@ -135,17 +126,8 @@ router.get('/nex_token/@me', async (request, response) => { }).end()); } - let publicKey = await cache.getNEXPublicKey(service_name); - if (publicKey === null) { - publicKey = await fs.readFile(`${cryptoPath}/public.pem`); - await cache.setNEXPublicKey(service_name, publicKey); - } - - let secretKey= await cache.getNEXSecretKey(service_name); - if (secretKey === null) { - secretKey = await fs.readFile(`${cryptoPath}/secret.key`); - await cache.setNEXSecretKey(service_name, secretKey); - } + const publicKey = await cache.getNEXPublicKey(service_name); + const secretKey= await cache.getNEXSecretKey(service_name); const cryptoOptions = { public_key: publicKey, diff --git a/src/util.js b/src/util.js index 1ef6a2c..b9f06ab 100644 --- a/src/util.js +++ b/src/util.js @@ -1,6 +1,5 @@ const crypto = require('crypto'); const NodeRSA = require('node-rsa'); -const fs = require('fs-extra'); const aws = require('aws-sdk'); const cache = require('./cache'); const config = require('../config.json'); @@ -41,14 +40,8 @@ async function generateToken(cryptoOptions, tokenOptions) { // Access and refresh tokens use a different format since they must be much smaller // They take no extra crypto options if (!cryptoOptions) { - let aesKey = await cache.getServiceAESKey('account', 'hex'); - - if (aesKey === null) { - const fileBuffer = await fs.readFile(`${__dirname}/../certs/access/aes.key`, { encoding: 'utf8' }); - aesKey = Buffer.from(fileBuffer, 'hex'); - await cache.setServiceAESKey('account', aesKey); - } - + const aesKey = await cache.getServiceAESKey('account', 'hex'); + const dataBuffer = Buffer.alloc(1 + 1 + 4 + 8); dataBuffer.writeUInt8(tokenOptions.system_type, 0x0); @@ -130,18 +123,10 @@ async function generateToken(cryptoOptions, tokenOptions) { } async function decryptToken(token) { - const cryptoPath = `${__dirname}/../certs/access`; - // Access and refresh tokens use a different format since they must be much smaller // Assume a small length means access or refresh token if (token.length <= 32) { - let aesKey = await cache.getServiceAESKey('account', 'hex'); - - if (aesKey === null) { - const fileBuffer = await fs.readFile(`${cryptoPath}/aes.key`, { encoding: 'utf8' }); - aesKey = Buffer.from(fileBuffer, 'hex'); - await cache.setServiceAESKey('account', aesKey); - } + const aesKey = await cache.getServiceAESKey('account', 'hex'); const iv = Buffer.alloc(16); @@ -153,17 +138,8 @@ async function decryptToken(token) { return decryptedBody; } - let privateKeyBytes = await cache.getServicePrivateKey('account'); - if (privateKeyBytes === null) { - privateKeyBytes = await fs.readFile(`${cryptoPath}/private.pem`); - await cache.setServicePrivateKey('account', privateKeyBytes); - } - - let secretKey = await cache.getServiceSecretKey('account'); - if (secretKey === null) { - secretKey = await fs.readFile(`${cryptoPath}/secret.key`); - await cache.setServiceSecretKey('account', secretKey); - } + const privateKeyBytes = await cache.getServicePrivateKey('account'); + const secretKey = await cache.getServiceSecretKey('account'); const privateKey = new NodeRSA(privateKeyBytes, 'pkcs1-private-pem', { environment: 'browser', From cbb580a3b18b3bb3ed7b0adffe8255163d9fb9af Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 30 Sep 2022 21:25:03 -0400 Subject: [PATCH 051/105] Updated docker entrypoint --- docker/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index b77d1a9..1393202 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,7 +1,7 @@ #!/bin/sh # this doesnt check game server specific certs, only static file paths -files='config.json certs/nex/datastore/secret.key certs/access/secret.key certs/access/aes.key certs/access/private.pem certs/access/public.pem' +files='config.json certs/nex/datastore/secret.key certs/service/account/secret.key certs/service/account/aes.key certs/service/account/private.pem certs/service/account/public.pem' for file in $files; do if [ ! -f $file ]; then From 015d2a4e59246a01f09a94bb6a297558e15d602a Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 30 Sep 2022 21:43:09 -0400 Subject: [PATCH 052/105] Added missing xmlbuilder endpoint to xml-parser middleware --- src/middleware/xml-parser.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/middleware/xml-parser.js b/src/middleware/xml-parser.js index 2ab8ff7..5a9fcaa 100644 --- a/src/middleware/xml-parser.js +++ b/src/middleware/xml-parser.js @@ -1,10 +1,11 @@ +const xmlbuilder = require('xmlbuilder'); const { document: xmlParser } = require('xmlbuilder2'); function XMLMiddleware(request, response, next) { if (request.method == 'POST' || request.method == 'PUT') { const headers = request.headers; let body = ''; - + if ( !headers['content-type'] || !headers['content-type'].toLowerCase().includes('xml') From 48bc34a78b35fbfa630bd853cc78bc8837e4362f Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 30 Sep 2022 23:22:43 -0400 Subject: [PATCH 053/105] Added email confirmation code support --- src/database.js | 13 ++++++--- src/middleware/pnid.js | 4 +-- src/middleware/xml-parser.js | 7 +++++ src/models/pnid.js | 10 ++----- src/services/nnid/routes/support.js | 45 +++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/database.js b/src/database.js index 4f7c67a..e46ce89 100644 --- a/src/database.js +++ b/src/database.js @@ -130,7 +130,7 @@ async function getUserProfileJSONByPID(pid) { }); } - return { + const userObject = { //accounts: {}, We need to figure this out, no idea what these values mean or what they do active_flag: user.get('flags.active') ? 'Y' : 'N', birth_date: user.get('birthdate'), @@ -150,9 +150,8 @@ async function getUserProfileJSONByPID(pid) { primary: user.get('email.primary') ? 'Y' : 'N', reachable: user.get('email.reachable') ? 'Y' : 'N', type: 'DEFAULT', - updated_by: 'INTERNAL WS', // Can also be INTERNAL WS, don't know the difference - validated: user.get('email.validated') ? 'Y' : 'N', - //validated_date: user.get('email.validated_date') // not used atm + updated_by: 'USER', // Can also be INTERNAL WS, don't know the difference + validated: user.get('email.validated') ? 'Y' : 'N' }, mii: { status: 'COMPLETED', @@ -177,6 +176,12 @@ async function getUserProfileJSONByPID(pid) { user_id: user.get('username'), utc_offset: user.get('timezone.offset') }; + + if (user.get('email.validated')) { + userObject.email.validated_date = user.get('email.validated_date'); + } + + return userObject; } function getServer(gameServerId, accessMode) { diff --git a/src/middleware/pnid.js b/src/middleware/pnid.js index 262dfa3..d28d745 100644 --- a/src/middleware/pnid.js +++ b/src/middleware/pnid.js @@ -23,7 +23,7 @@ async function PNIDMiddleware(request, response, next) { if (!user) { response.status(401); - + if (type === 'Bearer') { return response.send(xmlbuilder.create({ errors: { @@ -35,7 +35,7 @@ async function PNIDMiddleware(request, response, next) { } }).end()); } - + return response.send(xmlbuilder.create({ errors: { error: { diff --git a/src/middleware/xml-parser.js b/src/middleware/xml-parser.js index 5a9fcaa..323e045 100644 --- a/src/middleware/xml-parser.js +++ b/src/middleware/xml-parser.js @@ -13,6 +13,13 @@ function XMLMiddleware(request, response, next) { return next(); } + if ( + !headers['content-length'] || + parseInt(headers['content-length']) === 0 + ) { + return next(); + } + request.setEncoding('utf-8'); request.on('data', (chunk) => { body += chunk; diff --git a/src/models/pnid.js b/src/models/pnid.js index 9475492..f3a5984 100644 --- a/src/models/pnid.js +++ b/src/models/pnid.js @@ -131,13 +131,9 @@ PNIDSchema.methods.generatePID = async function() { }; PNIDSchema.methods.generateEmailValidationCode = async function() { - let code = Math.random().toFixed(6).split('.')[1]; // Dirty one-liner to generate numbers of 6 length and padded 0 - - const inuse = await PNID.findOne({ - 'identification.email_code': code - }); - - code = (inuse ? await PNID.generateEmailValidationCode() : code); + // WiiU passes the PID along with the email code + // Does not actually need to be unique to all users + const code = Math.random().toFixed(6).split('.')[1]; // Dirty one-liner to generate numbers of 6 length and padded 0 this.set('identification.email_code', code); }; diff --git a/src/services/nnid/routes/support.js b/src/services/nnid/routes/support.js index 78055e9..6cc7a3d 100644 --- a/src/services/nnid/routes/support.js +++ b/src/services/nnid/routes/support.js @@ -1,6 +1,8 @@ const router = require('express').Router(); const dns = require('dns'); const xmlbuilder = require('xmlbuilder'); +const moment = require('moment'); +const database = require('../../../database'); /** * [POST] @@ -41,4 +43,47 @@ router.post('/validate/email', async (request, response) => { }); }); +/** + * [PUT] + * Replacement for: https://account.nintendo.net/v1/api/support/email_confirmation/:pid/:code + * Description: Verifies a users email via 6 digit code + */ +router.put('/email_confirmation/:pid/:code', async (request, response) => { + const { pid, code } = request.params; + + const pnid = await database.getUserByPID(pid); + + if (!pnid) { + return response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0130', + message: 'PID has not been registered yet' + } + } + }).end()); + } + + if (pnid.get('identification.email_code') !== code) { + return response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0116', + message: 'Missing or invalid verification code' + } + } + }).end()); + } + + const validatedDate = moment().format('YYYY-MM-DDTHH:MM:SS'); + + pnid.set('email.reachable', true); + pnid.set('email.validated', true); + pnid.set('email.validated_date', validatedDate); + + await pnid.save(); + + response.status(200).send(''); +}); + module.exports = router; \ No newline at end of file From 29edbab43cb1d7876f7df76cf3c6914446409edb Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 00:53:12 -0400 Subject: [PATCH 054/105] Fixed password not referenced in PNID creation on console --- src/services/nnid/routes/people.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index eab9b27..791e9bb 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -99,7 +99,7 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons await nexAccount.save({ session }); - const primaryPasswordHash = util.nintendoPasswordHash(password, nexAccount.get('pid')); + const primaryPasswordHash = util.nintendoPasswordHash(person.get('password'), nexAccount.get('pid')); const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); pnid = new PNID({ From ee98bb006fb6a30557b69fc4a610990f6c277cb4 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 00:55:39 -0400 Subject: [PATCH 055/105] Fixed email sending --- src/mailer.js | 29 +------------------ src/services/nnid/routes/people.js | 45 +++++++----------------------- src/util.js | 14 ++++++++-- 3 files changed, 23 insertions(+), 65 deletions(-) diff --git a/src/mailer.js b/src/mailer.js index 9180270..1d627f1 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -3,31 +3,4 @@ const config = require('../config.json'); const transporter = nodemailer.createTransport(config.email); -/** - * Sends an email with the specified subject and message to an email address - * @param {String} email the destination email address - * @param {String} subject The Subject of the email - * @param {String} message The body of the email - */ -async function send(email, subject = 'No email subject provided', message = 'No email body provided') { - const options = { - from: config.email.auth.user, - to: email, - subject: subject, - html: message - }; - - return new Promise(resolve => { - transporter.sendMail(options, (error) => { - if (error) { - console.warn(error); - } - - return resolve(); - }); - }); -} - -module.exports = { - send: send -}; \ No newline at end of file +module.exports = transporter; diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index 791e9bb..155d6df 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -8,7 +8,7 @@ const { NEXAccount } = require('../../../models/nex-account'); const deviceCertificateMiddleware = require('../../../middleware/device-certificate'); const ratelimit = require('../../../middleware/ratelimit'); const database = require('../../../database'); -const mailer = require('../../../mailer'); +const util = require('../../../util'); const logger = require('../../../../logger'); require('moment-timezone'); @@ -173,19 +173,7 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons await session.endSession(); } - await mailer.send( - pnid.get('email'), - '[Pretendo Network] Please confirm your e-mail address', - `Hello, - - Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process. - - https://account.pretendo.cc/account/email-confirmation?token=` + pnid.get('identification.email_token') + ` - - If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked. - - <<Confirmation code: ` + pnid.get('identification.email_code') + '>>' - ); + await util.sendConfirmationEmail(pnid); response.send(xmlbuilder.create({ person: { @@ -203,8 +191,7 @@ router.get('/@me/profile', async (request, response) => { response.set('Content-Type', 'text/xml'); response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', new Date().getTime()); - - + const { pnid } = request; const person = await database.getUserProfileJSONByPID(pnid.get('pid')); @@ -246,7 +233,7 @@ router.get('/@me/devices', async (request, response) => { response.set('Content-Type', 'text/xml'); response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', new Date().getTime()); - + const { pnid, headers } = request; response.send(xmlbuilder.create({ @@ -487,30 +474,18 @@ router.put('/@me/emails/@primary', async (request, response) => { }).end()); } - pnid.email.address = email.get('address'); - pnid.email.reachable = false; - pnid.email.validated = false; - pnid.email.id = crypto.randomBytes(4).readUInt32LE(); + pnid.set('email.address', email.get('address')); + pnid.set('email.reachable', false); + pnid.set('email.validated', false); + pnid.set('email.validated_date', ''); + pnid.set('email.id', crypto.randomBytes(4).readUInt32LE()); - // TODO: Change these, they are slow await pnid.generateEmailValidationCode(); await pnid.generateEmailValidationToken(); await pnid.save(); - await mailer.send( - email.get('address'), - '[Pretendo Network] Please confirm your e-mail address', - `Hello, - - Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process. - - https://account.pretendo.cc/account/email-confirmation?token=` + pnid.get('identification.email_token') + ` - - If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked. - - <<Confirmation code: ` + pnid.get('identification.email_code') + '>>' - ); + await util.sendConfirmationEmail(pnid); response.send(''); }); diff --git a/src/util.js b/src/util.js index b9f06ab..afc70bd 100644 --- a/src/util.js +++ b/src/util.js @@ -1,6 +1,7 @@ const crypto = require('crypto'); const NodeRSA = require('node-rsa'); const aws = require('aws-sdk'); +const mailer = require('./mailer'); const cache = require('./cache'); const config = require('../config.json'); @@ -41,7 +42,7 @@ async function generateToken(cryptoOptions, tokenOptions) { // They take no extra crypto options if (!cryptoOptions) { const aesKey = await cache.getServiceAESKey('account', 'hex'); - + const dataBuffer = Buffer.alloc(1 + 1 + 4 + 8); dataBuffer.writeUInt8(tokenOptions.system_type, 0x0); @@ -228,6 +229,14 @@ function nascError(errorCode) { return params; } +async function sendConfirmationEmail(pnid) { + await mailer.sendMail({ + to: pnid.get('email.address'), + subject: '[Pretendo Network] Please confirm your e-mail address', + html: `Hello,\n\nYour Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process.\n\nhttps://account.pretendo.cc/account/email-confirmation?token=${pnid.get('identification.email_token')}\n\nIf you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.\n\n<<Confirmation code: ${pnid.get('identification.email_code')}>>` + }); +} + module.exports = { nintendoPasswordHash, nintendoBase64Decode, @@ -237,5 +246,6 @@ module.exports = { unpackToken, fullUrl, uploadCDNAsset, - nascError + nascError, + sendConfirmationEmail }; \ No newline at end of file From b705e51ec04de5810f56c36b1adb7ce01225922b Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 00:57:17 -0400 Subject: [PATCH 056/105] Updated example config --- example.config.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/example.config.json b/example.config.json index 4ad707b..3a24e56 100644 --- a/example.config.json +++ b/example.config.json @@ -10,11 +10,14 @@ } }, "email": { - "service": "gmail", + "host": "smtp.gmail.com", + "port": 587, + "secure": false, "auth": { - "user": "email@address.com", + "user": "username", "pass": "password" - } + }, + "from": "Company Name " }, "aws": { "spaces": { From 6c0e0ff71af87b2e73355b17fec459b228860db2 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 01:03:36 -0400 Subject: [PATCH 057/105] Updated confirmation email text --- src/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.js b/src/util.js index afc70bd..c90400e 100644 --- a/src/util.js +++ b/src/util.js @@ -233,7 +233,7 @@ async function sendConfirmationEmail(pnid) { await mailer.sendMail({ to: pnid.get('email.address'), subject: '[Pretendo Network] Please confirm your e-mail address', - html: `Hello,\n\nYour Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process.\n\nhttps://account.pretendo.cc/account/email-confirmation?token=${pnid.get('identification.email_token')}\n\nIf you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.\n\n<<Confirmation code: ${pnid.get('identification.email_code')}>>` + html: `Hello,

Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process.

https://account.pretendo.cc/account/email-confirmation?token=${pnid.get('identification.email_token')}

If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.

<<Confirmation code: ${pnid.get('identification.email_code')}>>` }); } From e4edb5e0e53fe3068ea90fa315da5a69f75eb687 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 01:04:04 -0400 Subject: [PATCH 058/105] Added confirmation email to website register --- src/services/api/routes/v1/register.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index d823646..57f91aa 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -335,6 +335,8 @@ router.post('/', async (request, response) => { await session.endSession(); } + await util.sendConfirmationEmail(pnid); + const cryptoPath = `${__dirname}/../../../../../certs/service/account`; if (!await fs.pathExists(cryptoPath)) { From f70164774727d6648be12b86fc84e1b5faae3a45 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 01:15:46 -0400 Subject: [PATCH 059/105] Added email token confirmation --- src/services/api/index.js | 6 +++-- src/services/api/routes/index.js | 5 ++-- src/services/api/routes/v1/email.js | 39 +++++++++++++++++++++++++++++ src/util.js | 2 +- 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/services/api/routes/v1/email.js diff --git a/src/services/api/index.js b/src/services/api/index.js index 8fc08b3..4426397 100644 --- a/src/services/api/index.js +++ b/src/services/api/index.js @@ -17,10 +17,12 @@ api.options('*', cors()); // Setup routes logger.info('[USER API] Applying imported routes'); -api.use('/v1/register', routes.V1.REGISTER); +api.use('/v1/connections', routes.V1.CONNECTIONS); +api.use('/v1/email', routes.V1.EMAIL); api.use('/v1/login', routes.V1.LOGIN); +api.use('/v1/register', routes.V1.REGISTER); api.use('/v1/user', routes.V1.USER); -api.use('/v1/connections', routes.V1.CONNECTIONS); + // Main router for endpoints const router = express.Router(); diff --git a/src/services/api/routes/index.js b/src/services/api/routes/index.js index 3ce4365..2f56b2e 100644 --- a/src/services/api/routes/index.js +++ b/src/services/api/routes/index.js @@ -1,8 +1,9 @@ module.exports = { V1: { - REGISTER: require('./v1/register'), + CONNECTIONS: require('./v1/connections'), + EMAIL: require('./v1/email'), LOGIN: require('./v1/login'), + REGISTER: require('./v1/register'), USER: require('./v1/user'), - CONNECTIONS: require('./v1/connections'), } }; \ No newline at end of file diff --git a/src/services/api/routes/v1/email.js b/src/services/api/routes/v1/email.js new file mode 100644 index 0000000..b3c9ce6 --- /dev/null +++ b/src/services/api/routes/v1/email.js @@ -0,0 +1,39 @@ +const router = require('express').Router(); +const moment = require('moment'); +const { PNID } = require('../../../../models/pnid'); + +router.get('/verify', async (request, response) => { + const { token } = request.query; + + if (!token || token.trim() == '') { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Missing email token' + }); + } + + const pnid = await PNID.findOne({ + 'identification.email_token': token + }); + + if (!pnid) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid email token' + }); + } + + const validatedDate = moment().format('YYYY-MM-DDTHH:MM:SS'); + + pnid.set('email.reachable', true); + pnid.set('email.validated', true); + pnid.set('email.validated_date', validatedDate); + + await pnid.save(); + + response.status(200).send('Email validated. You may close this window'); +}); + +module.exports = router; \ No newline at end of file diff --git a/src/util.js b/src/util.js index c90400e..9518b9e 100644 --- a/src/util.js +++ b/src/util.js @@ -233,7 +233,7 @@ async function sendConfirmationEmail(pnid) { await mailer.sendMail({ to: pnid.get('email.address'), subject: '[Pretendo Network] Please confirm your e-mail address', - html: `Hello,

Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process.

https://account.pretendo.cc/account/email-confirmation?token=${pnid.get('identification.email_token')}

If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.

<<Confirmation code: ${pnid.get('identification.email_code')}>>` + html: `Hello,

Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process.

https://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')}

If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.

<<Confirmation code: ${pnid.get('identification.email_code')}>>` }); } From 48aabe0bfce511c174cfb69c6f6c45df75652cfd Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 01:21:23 -0400 Subject: [PATCH 060/105] Added email resending endpoint --- src/services/nnid/routes/support.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/services/nnid/routes/support.js b/src/services/nnid/routes/support.js index 6cc7a3d..d2a43b2 100644 --- a/src/services/nnid/routes/support.js +++ b/src/services/nnid/routes/support.js @@ -2,6 +2,7 @@ const router = require('express').Router(); const dns = require('dns'); const xmlbuilder = require('xmlbuilder'); const moment = require('moment'); +const util = require('../../../util'); const database = require('../../../database'); /** @@ -86,4 +87,31 @@ router.put('/email_confirmation/:pid/:code', async (request, response) => { response.status(200).send(''); }); +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/support/resend_confirmation + * Description: Resends a users confirmation email + */ +router.get('/resend_confirmation', async (request, response) => { + const pid = request.headers['x-nintendo-pid']; + + const pnid = await database.getUserByPID(pid); + + if (!pnid) { + // TODO - Unsure if this is the right error + return response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0130', + message: 'PID has not been registered yet' + } + } + }).end()); + } + + await util.sendConfirmationEmail(pnid); + + response.status(200).send(''); +}); + module.exports = router; \ No newline at end of file From fd455fae91240954a54de473e6197fc0ec7de82f Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 01:26:00 -0400 Subject: [PATCH 061/105] Added email for when email address is confirmed --- src/services/api/routes/v1/email.js | 3 +++ src/services/nnid/routes/support.js | 2 ++ src/util.js | 15 ++++++++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/services/api/routes/v1/email.js b/src/services/api/routes/v1/email.js index b3c9ce6..561e651 100644 --- a/src/services/api/routes/v1/email.js +++ b/src/services/api/routes/v1/email.js @@ -1,6 +1,7 @@ const router = require('express').Router(); const moment = require('moment'); const { PNID } = require('../../../../models/pnid'); +const util = require('../../../../util'); router.get('/verify', async (request, response) => { const { token } = request.query; @@ -33,6 +34,8 @@ router.get('/verify', async (request, response) => { await pnid.save(); + await util.sendEmailConfirmedEmail(pnid); + response.status(200).send('Email validated. You may close this window'); }); diff --git a/src/services/nnid/routes/support.js b/src/services/nnid/routes/support.js index d2a43b2..4b808a7 100644 --- a/src/services/nnid/routes/support.js +++ b/src/services/nnid/routes/support.js @@ -84,6 +84,8 @@ router.put('/email_confirmation/:pid/:code', async (request, response) => { await pnid.save(); + await util.sendEmailConfirmedEmail(pnid); + response.status(200).send(''); }); diff --git a/src/util.js b/src/util.js index 9518b9e..c265699 100644 --- a/src/util.js +++ b/src/util.js @@ -232,8 +232,16 @@ function nascError(errorCode) { async function sendConfirmationEmail(pnid) { await mailer.sendMail({ to: pnid.get('email.address'), - subject: '[Pretendo Network] Please confirm your e-mail address', - html: `Hello,

Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process.

https://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')}

If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.

<<Confirmation code: ${pnid.get('identification.email_code')}>>` + subject: '[Pretendo Network] Please confirm your email address', + html: `Hello,

Your Pretendo Network ID activation is almost complete.

Please click the link below to confirm your e-mail address and complete the activation process.

https://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')}

If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.

<<Confirmation code: ${pnid.get('identification.email_code')}>>` + }); +} + +async function sendEmailConfirmedEmail(pnid) { + await mailer.sendMail({ + to: pnid.get('email.address'), + subject: '[Pretendo Network] Email address confirmed', + html: 'Your email address has been confirmed!' }); } @@ -247,5 +255,6 @@ module.exports = { fullUrl, uploadCDNAsset, nascError, - sendConfirmationEmail + sendConfirmationEmail, + sendEmailConfirmedEmail }; \ No newline at end of file From 99b8032d98ca73805bfd44a713936566792e1469 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 01:36:42 -0400 Subject: [PATCH 062/105] Made 3DS and Wii U use the same NEX PID pool again --- src/models/nex-account.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/models/nex-account.js b/src/models/nex-account.js index 503d246..fbffd69 100644 --- a/src/models/nex-account.js +++ b/src/models/nex-account.js @@ -10,7 +10,10 @@ const NEXAccountSchema = new Schema({ '3ds', ] }, - pid: Number, + pid: { + type: Number, + unique: true + }, password: String, owning_pid: Number, access_level: { @@ -23,8 +26,6 @@ const NEXAccountSchema = new Schema({ }, }); -NEXAccountSchema.index({ device_type: 1, pid: 1 }, { unique: true }) - NEXAccountSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); /* @@ -41,10 +42,7 @@ NEXAccountSchema.methods.generatePID = async function () { let pid = Math.floor(Math.random() * (max - min + 1) + min); - const inuse = await NEXAccount.findOne({ - pid, - device_type: this.get('device_type') - }); + const inuse = await NEXAccount.findOne({ pid }); pid = (inuse ? await NEXAccount.generatePID() : pid); From 883417c05fa404e1840c0cd91f87591252a39356 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 02:11:31 -0400 Subject: [PATCH 063/105] Removed duplicate path in generate-keys script --- generate-keys.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/generate-keys.js b/generate-keys.js index 1c262d4..c62ae46 100644 --- a/generate-keys.js +++ b/generate-keys.js @@ -40,7 +40,6 @@ async function main() { usage(); return; } - if (type === 'service' && name === 'account') { logger.error('Cannot use service name \'account\'. Reserved'); @@ -48,7 +47,7 @@ async function main() { return; } - const path = path = `${__dirname}/certs/${type}/${name}`; + const path = `${__dirname}/certs/${type}/${name}`; if (fs.pathExistsSync(path)) { const overwrite = await yesno({ From 69e8b84b146b469f9b1add187a8e5b656f3c7b79 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Fri, 30 Sep 2022 22:25:49 +1000 Subject: [PATCH 064/105] docker: Allow option to autogenerate keys While this isn't optimal for prod, for dev environments it can be very helpful to opt-in for things to Just Work. --- docker/entrypoint.sh | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 1393202..2c6aa02 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,7 +1,7 @@ #!/bin/sh # this doesnt check game server specific certs, only static file paths -files='config.json certs/nex/datastore/secret.key certs/service/account/secret.key certs/service/account/aes.key certs/service/account/private.pem certs/service/account/public.pem' +files='config.json' for file in $files; do if [ ! -f $file ]; then @@ -10,4 +10,19 @@ for file in $files; do fi done +# check for keys +keys='certs/nex/datastore/secret.key certs/service/account/secret.key certs/service/account/aes.key certs/service/account/private.pem certs/service/account/public.pem' +for file in $keys; do + if [ ! -f "$file" ]; then + if [ x"${GENERATE_NEW_KEYS}" = "x" ]; then + echo "$PWD/$file file does not exist. Please mount and try again." + exit 1 + else + echo "$PWD/$file file does not exist. Generating a temporary one" + node generate-keys.js nex datastore + node generate-keys.js account + fi + fi +done + exec node src/server.js From 540c11f4aa48b55d411ba7693819b55dced663ab Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 10:53:23 -0400 Subject: [PATCH 065/105] Updated mailer to have proper from address --- src/mailer.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/mailer.js b/src/mailer.js index 1d627f1..6f00665 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -3,4 +3,12 @@ const config = require('../config.json'); const transporter = nodemailer.createTransport(config.email); -module.exports = transporter; +async function sendMail(options) { + options.from = config.email.from; + + await transporter.sendMail(options); +} + +module.exports = { + sendMail +}; From cf292ed661f597a33123f5cdb21b08b9339376ce Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 10:56:06 -0400 Subject: [PATCH 066/105] Fixed path undefined error in generate-keys with account type --- generate-keys.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/generate-keys.js b/generate-keys.js index c62ae46..b1a311b 100644 --- a/generate-keys.js +++ b/generate-keys.js @@ -47,7 +47,13 @@ async function main() { return; } - const path = `${__dirname}/certs/${type}/${name}`; + let path; + + if (type === 'account') { + path = `${__dirname}/certs/service/account`; + } else { + path = `${__dirname}/certs/${type}/${name}`; + } if (fs.pathExistsSync(path)) { const overwrite = await yesno({ From 0649ad46e39d3bc5b6c517c067eb1ee062b2b0dc Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 13:01:11 -0400 Subject: [PATCH 067/105] Implement mii-js lib and fix default Mii on website register --- package-lock.json | 26 ++++++++++++++++++++ package.json | 1 + src/models/pnid.js | 25 +++++++++++++------ src/services/api/routes/v1/register.js | 33 ++++++-------------------- 4 files changed, 52 insertions(+), 33 deletions(-) diff --git a/package-lock.json b/package-lock.json index f70fa94..2906080 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "image-pixels": "^1.1.1", "joi": "^17.6.1", "kaitai-struct": "^0.9.0", + "mii-js": "github:PretendoNetwork/mii-js", "moment": "^2.24.0", "moment-timezone": "^0.5.27", "mongoose": "^5.8.3", @@ -579,6 +580,11 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/bit-buffer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/bit-buffer/-/bit-buffer-0.2.5.tgz", + "integrity": "sha512-x1yGnmXvFg6e3DiyRztElbcn1bsCTFSoM/ncAzY62uE0JdTl5xlKJd0ooqLYoPbhdsnpehSIQrdIvclcZJYwiA==" + }, "node_modules/bl": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", @@ -2098,6 +2104,14 @@ "node": ">= 0.6" } }, + "node_modules/mii-js": { + "version": "1.0.4", + "resolved": "git+ssh://git@github.com/PretendoNetwork/mii-js.git#5d8eb8013514a13b0df6eb4a5bfd8b5a63fb9861", + "license": "GNU AFFERO GPLV3", + "dependencies": { + "bit-buffer": "^0.2.5" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -4106,6 +4120,11 @@ "tweetnacl": "^0.14.3" } }, + "bit-buffer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/bit-buffer/-/bit-buffer-0.2.5.tgz", + "integrity": "sha512-x1yGnmXvFg6e3DiyRztElbcn1bsCTFSoM/ncAzY62uE0JdTl5xlKJd0ooqLYoPbhdsnpehSIQrdIvclcZJYwiA==" + }, "bl": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", @@ -5357,6 +5376,13 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, + "mii-js": { + "version": "git+ssh://git@github.com/PretendoNetwork/mii-js.git#5d8eb8013514a13b0df6eb4a5bfd8b5a63fb9861", + "from": "mii-js@https://github.com/PretendoNetwork/mii-js", + "requires": { + "bit-buffer": "^0.2.5" + } + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", diff --git a/package.json b/package.json index bbd7bec..4bd8c49 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "image-pixels": "^1.1.1", "joi": "^17.6.1", "kaitai-struct": "^0.9.0", + "mii-js": "github:PretendoNetwork/mii-js", "moment": "^2.24.0", "moment-timezone": "^0.5.27", "mongoose": "^5.8.3", diff --git a/src/models/pnid.js b/src/models/pnid.js index f3a5984..5cf0f99 100644 --- a/src/models/pnid.js +++ b/src/models/pnid.js @@ -7,7 +7,7 @@ const TGA = require('tga'); const got = require('got'); const util = require('../util'); const { DeviceSchema } = require('./device'); -const Mii = require('../mii'); +const Mii = require('mii-js'); const PNIDSchema = new Schema({ access_level: { @@ -189,10 +189,12 @@ PNIDSchema.methods.updateMii = async function({name, primary, data}) { PNIDSchema.methods.generateMiiImages = async function() { const miiData = this.get('mii.data'); - const studioMii = new Mii(Buffer.from(miiData, 'base64')); - const converted = studioMii.toStudioMii(); - const encodedStudioMiiData = converted.toString('hex'); - const miiStudioUrl = `https://studio.mii.nintendo.com/miis/image.png?data=${encodedStudioMiiData}&type=face&width=128&instanceCount=1`; + const mii = new Mii(Buffer.from(miiData, 'base64')); + const miiStudioUrl = mii.studioUrl({ + type: 'face', + width: '128', + instanceCount: '1', + }); const miiStudioNormalFaceImageData = await got(miiStudioUrl).buffer(); const pngData = await imagePixels(miiStudioNormalFaceImageData); const tga = TGA.createTgaBuffer(pngData.width, pngData.height, pngData.data); @@ -204,12 +206,21 @@ PNIDSchema.methods.generateMiiImages = async function() { const expressions = ['frustrated', 'smile_open_mouth', 'wink_left', 'sorrow', 'surprise_open_mouth']; for (const expression of expressions) { - const miiStudioExpressionUrl = `https://studio.mii.nintendo.com/miis/image.png?data=${encodedStudioMiiData}&type=face&expression=${expression}&width=128&instanceCount=1`; + const miiStudioExpressionUrl = mii.studioUrl({ + type: 'face', + expression: expression, + width: '128', + instanceCount: '1', + }); const miiStudioExpressionImageData = await got(miiStudioExpressionUrl).buffer(); await util.uploadCDNAsset('pn-cdn', `${userMiiKey}/${expression}.png`, miiStudioExpressionImageData, 'public-read'); } - const miiStudioBodyUrl = `https://studio.mii.nintendo.com/miis/image.png?data=${encodedStudioMiiData}&type=all_body&width=270&instanceCount=1`; + const miiStudioBodyUrl = mii.studioUrl({ + type: 'all_body', + width: '270', + instanceCount: '1', + }); const miiStudioBodyImageData = await got(miiStudioBodyUrl).buffer(); await util.uploadCDNAsset('pn-cdn', `${userMiiKey}/body.png`, miiStudioBodyImageData, 'public-read'); }; diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 57f91aa..95b2d50 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -5,6 +5,7 @@ const moment = require('moment'); const crypto = require('crypto'); const hcaptcha = require('hcaptcha'); const bcrypt = require('bcrypt'); +const Mii = require('mii-js'); const { PNID } = require('../../../../models/pnid'); const { NEXAccount } = require('../../../../models/nex-account'); const database = require('../../../../database'); @@ -24,6 +25,8 @@ const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[\_\-\.]).*/; const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[\_\-\.]).*/; const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; +const DEFAULT_MII_DATA = Buffer.from('AwAAQOlVognnx0GC2/uogAOzuI0n2QAAAEBEAGUAZgBhAHUAbAB0AAAAAAAAAEBAAAAhAQJoRBgmNEYUgRIXaA0AACkAUkhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGm9', 'base64'); + /** * [POST] * Implementation of: https://api.pretendo.cc/v1/register @@ -31,7 +34,7 @@ const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; */ router.post('/', async (request, response) => { const { body } = request; - + const email = body.email?.trim(); const username = body.username?.trim(); const miiName = body.mii_name?.trim(); @@ -214,30 +217,8 @@ router.post('/', async (request, response) => { }); } - // Default Mii data before Mii name - const MII_DATA_FIRST = Buffer.from([ - 0x03, 0x00, 0x00, 0x40, 0xE9, 0x55, 0xA2, 0x09, - 0xE7, 0xC7, 0x41, 0x82, 0xDA, 0xA8, 0xE1, 0x77, - 0x03, 0xB3, 0xB8, 0x8D, 0x27, 0xD9, 0x00, 0x00, - 0x00, 0x60 - ]); - - const MII_DATA_NAME = Buffer.alloc(0x14); // Max Mii name length - - // Default Mii data after Mii name - const MII_DATA_LAST = Buffer.from([ - 0x40, 0x40, 0x00, 0x00, 0x21, 0x01, 0x02, 0x68, - 0x44, 0x18, 0x26, 0x34, 0x46, 0x14, 0x81, 0x12, - 0x17, 0x68, 0x0D, 0x00, 0x00, 0x29, 0x00, 0x52, - 0x48, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7C, 0x2E - ]); - - miiNameBuffer.copy(MII_DATA_NAME); // Move Mii name into padded buffer - - const MII_DATA = Buffer.concat([MII_DATA_FIRST, MII_DATA_NAME, MII_DATA_LAST]); // Build Mii data + const mii = new Mii(DEFAULT_MII_DATA); + mii.miiName = miiName; const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); let pnid; @@ -295,7 +276,7 @@ router.post('/', async (request, response) => { mii: { name: miiName, primary: true, // TODO: Change this - data: MII_DATA.toString('base64'), + data: mii.encode().toString('base64'), id: crypto.randomBytes(4).readUInt32LE(), hash: crypto.randomBytes(7).toString('hex'), image_url: '', // deprecated, will be removed in the future From 93bfb41a4da24e683c10eb2f04dd464ac32c36c0 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 16:59:39 -0400 Subject: [PATCH 068/105] Added password reset endpoints for website --- example.config.json | 3 +- package-lock.json | 16 ++- package.json | 1 + src/database.js | 11 ++ src/services/api/index.js | 2 + src/services/api/routes/index.js | 2 + src/services/api/routes/v1/forgotPassword.js | 36 ++++++ src/services/api/routes/v1/register.js | 2 +- src/services/api/routes/v1/resetPassword.js | 127 +++++++++++++++++++ src/services/nnid/routes/people.js | 4 +- src/util.js | 30 ++++- 11 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 src/services/api/routes/v1/forgotPassword.js create mode 100644 src/services/api/routes/v1/resetPassword.js diff --git a/example.config.json b/example.config.json index 3a24e56..2695feb 100644 --- a/example.config.json +++ b/example.config.json @@ -28,5 +28,6 @@ "hcaptcha": { "secret": "0x0000000000000000000000000000000000000000" }, - "cdn_base": "https://example.com" + "cdn_base": "https://example.com", + "website_base": "https://example.com" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2906080..00a2f1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "nodemailer": "^6.4.2", "redis": "^4.3.1", "tga": "^1.0.4", + "validator": "^13.7.0", "xmlbuilder": "^13.0.2", "xmlbuilder2": "0.0.4" }, @@ -3561,6 +3562,14 @@ "uuid": "bin/uuid" } }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -5378,7 +5387,7 @@ }, "mii-js": { "version": "git+ssh://git@github.com/PretendoNetwork/mii-js.git#5d8eb8013514a13b0df6eb4a5bfd8b5a63fb9861", - "from": "mii-js@https://github.com/PretendoNetwork/mii-js", + "from": "mii-js@github:PretendoNetwork/mii-js", "requires": { "bit-buffer": "^0.2.5" } @@ -6514,6 +6523,11 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, + "validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 4bd8c49..1ef4be4 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "nodemailer": "^6.4.2", "redis": "^4.3.1", "tga": "^1.0.4", + "validator": "^13.7.0", "xmlbuilder": "^13.0.2", "xmlbuilder2": "0.0.4" }, diff --git a/src/database.js b/src/database.js index e46ce89..53b9cdc 100644 --- a/src/database.js +++ b/src/database.js @@ -54,6 +54,16 @@ async function getUserByPID(pid) { return user; } +async function getUserByEmailAddress(email) { + verifyConnected(); + + const user = await PNID.findOne({ + 'email.address': email.toLowerCase() + }); + + return user; +} + async function doesUserExist(username) { verifyConnected(); @@ -252,6 +262,7 @@ module.exports = { connection, getUserByUsername, getUserByPID, + getUserByEmailAddress, doesUserExist, getUserBasic, getUserBearer, diff --git a/src/services/api/index.js b/src/services/api/index.js index 4426397..8db69f5 100644 --- a/src/services/api/index.js +++ b/src/services/api/index.js @@ -19,8 +19,10 @@ api.options('*', cors()); logger.info('[USER API] Applying imported routes'); api.use('/v1/connections', routes.V1.CONNECTIONS); api.use('/v1/email', routes.V1.EMAIL); +api.use('/v1/forgot-password', routes.V1.FORGOT_PASSWORD); api.use('/v1/login', routes.V1.LOGIN); api.use('/v1/register', routes.V1.REGISTER); +api.use('/v1/reset-password', routes.V1.RESET_PASSWORD); api.use('/v1/user', routes.V1.USER); diff --git a/src/services/api/routes/index.js b/src/services/api/routes/index.js index 2f56b2e..217a96d 100644 --- a/src/services/api/routes/index.js +++ b/src/services/api/routes/index.js @@ -2,8 +2,10 @@ module.exports = { V1: { CONNECTIONS: require('./v1/connections'), EMAIL: require('./v1/email'), + FORGOT_PASSWORD: require('./v1/forgotPassword'), LOGIN: require('./v1/login'), REGISTER: require('./v1/register'), + RESET_PASSWORD: require('./v1/resetPassword'), USER: require('./v1/user'), } }; \ No newline at end of file diff --git a/src/services/api/routes/v1/forgotPassword.js b/src/services/api/routes/v1/forgotPassword.js new file mode 100644 index 0000000..7dd4948 --- /dev/null +++ b/src/services/api/routes/v1/forgotPassword.js @@ -0,0 +1,36 @@ +const router = require('express').Router(); +const validator = require('validator'); +const database = require('../../../../database'); +const util = require('../../../../util'); + +router.post('/', async (request, response) => { + const { body } = request; + const { input } = body; + + if (!input || input.trim() === '') { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing input' + }); + } + + let pnid; + + if (validator.isEmail(input)) { + pnid = await database.getUserByEmailAddress(input); + } else { + pnid = await database.getUserByUsername(input); + } + + if (pnid) { + await util.sendForgotPasswordEmail(pnid); + } + + response.json({ + app: 'api', + status: 200 + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 95b2d50..5f91aac 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -261,7 +261,7 @@ router.post('/', async (request, response) => { country: 'US', // TODO: Change this language: 'en', // TODO: Change this email: { - address: email, + address: email.toLowerCase(), primary: true, // TODO: Change this parent: true, // TODO: Change this reachable: false, // TODO: Change this diff --git a/src/services/api/routes/v1/resetPassword.js b/src/services/api/routes/v1/resetPassword.js new file mode 100644 index 0000000..8afb3b1 --- /dev/null +++ b/src/services/api/routes/v1/resetPassword.js @@ -0,0 +1,127 @@ +const router = require('express').Router(); +const bcrypt = require('bcrypt'); +const { PNID } = require('../../../../models/pnid'); +const util = require('../../../../util'); + +// This sucks +const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; +const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[\_\-\.]).*/; +const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[\_\-\.]).*/; +const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; + +router.post('/', async (request, response) => { + const { body } = request; + const password = body.password?.trim(); + const passwordConfirm = body.password_confirm?.trim(); + const token = body.token?.trim(); + + if (!token || token === '') { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Missing token' + }); + } + + let unpackedToken; + try { + const decryptedToken = await util.decryptToken(Buffer.from(token, 'base64')); + unpackedToken = util.unpackToken(decryptedToken); + } catch (error) { + console.log(error); + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid token' + }); + } + + if (unpackedToken.expire_time < Date.now()) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Token expired' + }); + } + + const pnid = await PNID.findOne({ pid: unpackedToken.pid }); + + if (!pnid) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid token. No user found' + }); + } + + + if (!password || password === '') { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Must enter a password' + }); + } + + if (password.length < 6) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Password is too short' + }); + } + + if (password.length > 16) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Password is too long' + }); + } + + if (password.toLowerCase() === pnid.get('usernameLower')) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Password cannot be the same as username' + }); + } + + if (!PASSWORD_WORD_OR_NUMBER_REGEX.test(password) && !PASSWORD_WORD_OR_PUNCTUATION_REGEX.test(password) && !PASSWORD_NUMBER_OR_PUNCTUATION_REGEX.test(password)) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Password must have combination of letters, numbers, and/or punctuation characters' + }); + } + + if (PASSWORD_REPEATED_CHARACTER_REGEX.test(password)) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Password may not have 3 repeating characters' + }); + } + + if (password !== passwordConfirm) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Passwords do not match' + }); + } + + const primaryPasswordHash = util.nintendoPasswordHash(password, pnid.get('pid')); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); + + pnid.password = passwordHash; + + await pnid.save(); + + response.json({ + app: 'api', + status: 200 + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index 155d6df..1eb0467 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -114,7 +114,7 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request, respons country: person.get('country'), language: person.get('language'), email: { - address: person.get('email').get('address'), + address: person.get('email').get('address').toLowerCase(), primary: person.get('email').get('primary') === 'Y', parent: person.get('email').get('parent') === 'Y', reachable: false, @@ -474,7 +474,7 @@ router.put('/@me/emails/@primary', async (request, response) => { }).end()); } - pnid.set('email.address', email.get('address')); + pnid.set('email.address', email.get('address').toLowerCase()); pnid.set('email.reachable', false); pnid.set('email.validated', false); pnid.set('email.validated_date', ''); diff --git a/src/util.js b/src/util.js index c265699..32f3cab 100644 --- a/src/util.js +++ b/src/util.js @@ -245,6 +245,33 @@ async function sendEmailConfirmedEmail(pnid) { }); } +async function sendForgotPasswordEmail(pnid) { + const publicKey = await cache.getServicePublicKey('account'); + const secretKey = await cache.getServiceSecretKey('account'); + + const cryptoOptions = { + public_key: publicKey, + hmac_secret: secretKey + }; + + const tokenOptions = { + system_type: 0xF, // API + token_type: 0x5, // Password reset + pid: pnid.get('pid'), + access_level: pnid.get('access_level'), + title_id: BigInt(0), + expire_time: BigInt(Date.now() + (24 * 60 * 60 * 1000)) // Only valid for 24 hours + }; + + const passwordResetToken = await generateToken(cryptoOptions, tokenOptions); + + await mailer.sendMail({ + to: pnid.get('email.address'), + subject: '[Pretendo Network] Forgot Password', + html: `Visit this link to reset your password ${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}` + }); +} + module.exports = { nintendoPasswordHash, nintendoBase64Decode, @@ -256,5 +283,6 @@ module.exports = { uploadCDNAsset, nascError, sendConfirmationEmail, - sendEmailConfirmedEmail + sendEmailConfirmedEmail, + sendForgotPasswordEmail }; \ No newline at end of file From ced2d4684a4bc861df36ef6da987dea412279c2e Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 17:13:37 -0400 Subject: [PATCH 069/105] Fixed console password change not hashing --- src/services/nnid/routes/people.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js index 1eb0467..7d1287a 100644 --- a/src/services/nnid/routes/people.js +++ b/src/services/nnid/routes/people.js @@ -395,7 +395,10 @@ router.put('/@me', async (request, response) => { const offDeviceFlag = person.get('off_device_flag') ? person.get('off_device_flag') === 'Y' : pnid.get('flags.off_device'); if (person.get('password')) { - pnid.password = person.get('password'); // this gets hashed in the pre-save function, don't worry + const primaryPasswordHash = util.nintendoPasswordHash(person.get('password'), pnid.get('pid')); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); + + pnid.password = passwordHash; } pnid.gender = gender; From ccf4d0eab709985caf5cfd82ec01056598e37451 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 1 Oct 2022 17:37:03 -0400 Subject: [PATCH 070/105] Add password reset NNID endpoint --- src/services/nnid/routes/support.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/services/nnid/routes/support.js b/src/services/nnid/routes/support.js index 4b808a7..d63fea3 100644 --- a/src/services/nnid/routes/support.js +++ b/src/services/nnid/routes/support.js @@ -116,4 +116,33 @@ router.get('/resend_confirmation', async (request, response) => { response.status(200).send(''); }); +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/support/forgotten_password/PID + * Description: Sends the user a password reset email + * NOTE: On NN this was a temp password that expired after 24 hours. We do not do that + */ +router.get('/forgotten_password/:pid', async (request, response) => { + const { pid } = request.params; + + const pnid = await database.getUserByPID(pid); + + if (!pnid) { + // TODO - Better errors + return response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'device_id', + code: '0113', + message: 'Unauthorized device' + } + } + }).end()); + } + + await util.sendForgotPasswordEmail(pnid); + + response.status(200).send(''); +}); + module.exports = router; \ No newline at end of file From 8154c8770eb8fd53f83396b762df683fac0d4446 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Sun, 2 Oct 2022 12:49:17 +1100 Subject: [PATCH 071/105] cache: get Redis configuration from config.json --- example.config.json | 5 +++++ src/cache.js | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/example.config.json b/example.config.json index 2695feb..bfa68f4 100644 --- a/example.config.json +++ b/example.config.json @@ -9,6 +9,11 @@ "useNewUrlParser": true } }, + "redis": { + "client": { + "url": "redis://localhost:6379" + } + }, "email": { "host": "smtp.gmail.com", "port": 587, diff --git a/src/cache.js b/src/cache.js index 4db15bb..df9100f 100644 --- a/src/cache.js +++ b/src/cache.js @@ -1,12 +1,13 @@ const fs = require('fs-extra'); const redis = require('redis'); +const config = require('../config.json'); let client; const SERVICE_CERTS_BASE = `${__dirname}/../certs/service`; const NEX_CERTS_BASE = `${__dirname}/../certs/nex`; async function connect() { - client = redis.createClient(); + client = redis.createClient(config.redis.client); client.on('error', (err) => console.log('Redis Client Error', err)); await client.connect(); From 1f3ff5a16741d049049c8b28881e607a0d7439f3 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 8 Oct 2022 08:11:20 -0400 Subject: [PATCH 072/105] Updated .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c70000a..6ca20ff 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ typings/ # custom sign.js t.js +p.js config.json certs /cdn \ No newline at end of file From 9998c117e3ad5ffd548a89f5b5fedd8dfb8dae4f Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 8 Oct 2022 08:44:34 -0400 Subject: [PATCH 073/105] Fixed getNEXAESKey in cache --- src/cache.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cache.js b/src/cache.js index 4db15bb..64eba66 100644 --- a/src/cache.js +++ b/src/cache.js @@ -71,7 +71,7 @@ async function getNEXAESKey(name, encoding) { await setNEXAESKey(name, aesKey); } - return secretKey; + return aesKey; } async function setNEXPublicKey(name, value) { From 3dceb422c50baf1d64afd1e5deaf8e0767fa16df Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 8 Oct 2022 09:24:03 -0400 Subject: [PATCH 074/105] Added base config manager --- src/cache.js | 2 +- src/config-manager.js | 52 ++++++++++++++++++++++++++ src/database.js | 2 +- src/mailer.js | 2 +- src/server.js | 9 +++-- src/services/api/routes/v1/register.js | 2 +- src/services/api/routes/v1/user.js | 2 +- src/services/nnid/routes/miis.js | 2 +- src/util.js | 2 +- 9 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 src/config-manager.js diff --git a/src/cache.js b/src/cache.js index 7d263e9..6cd90de 100644 --- a/src/cache.js +++ b/src/cache.js @@ -1,6 +1,6 @@ const fs = require('fs-extra'); const redis = require('redis'); -const config = require('../config.json'); +const { config } = require('./config-manager'); let client; const SERVICE_CERTS_BASE = `${__dirname}/../certs/service`; diff --git a/src/config-manager.js b/src/config-manager.js new file mode 100644 index 0000000..bfde2ea --- /dev/null +++ b/src/config-manager.js @@ -0,0 +1,52 @@ +const fs = require('fs-extra'); +const logger = require('../logger'); + +/** + * @typedef {Object} Config + * @property {object} http HTTP server settings + * @property {number} http.port HTTP port the server will listen on + * @property {object} mongoose Mongose connection settings + * @property {string} mongoose.uri URI Mongoose will connect to + * @property {string} mongoose.database MongoDB database name + * @property {object} mongoose.options MongoDB connection options + * @property {object} redis redis settings + * @property {string} redis.client redis client settings + * @property {string} redis.client.url redis server URL + * @property {object} email node-mailer client settings + * @property {string} email.host SMTP server address + * @property {number} email.port SMTP server port + * @property {boolean} email.secure Secure SMTP + * @property {string} email.from Email "from" name/address + * @property {object} email.auth Email authentication settings + * @property {string} email.auth.user Email username + * @property {string} email.auth.pass Email password + * @property {object} aws s3 client settings + * @property {object} aws.spaces Digital Ocean Spaces settings + * @property {string} aws.spaces.key s3 access key + * @property {string} aws.spaces.secret s3 access secret + * @property {object} hcaptcha hCaptcha settings + * @property {string} hcaptcha.secret hCaptcha secret + * @property {string} cdn_base Base URL for CDN location + * @property {string} website_base Base URL for service website (used with emails) + */ + +/** + * @type {Config} + */ +let config = {}; + +function configure() { + if (!fs.pathExistsSync(`${__dirname}/../config.json`)) { + logger.error('Failed to locate config.json file'); + process.exit(0); + } + + config = require(`${__dirname}/../config.json`); + + module.exports.config = config; +} + +module.exports = { + configure, + config +}; \ No newline at end of file diff --git a/src/database.js b/src/database.js index 53b9cdc..fcb136e 100644 --- a/src/database.js +++ b/src/database.js @@ -5,7 +5,7 @@ const util = require('./util'); const { PNID } = require('./models/pnid'); const { Server } = require('./models/server'); const logger = require('../logger'); -const config = require('../config.json'); +const { config } = require('./config-manager'); const { uri, database, options } = config.mongoose; // TODO: Extend this later with more settings diff --git a/src/mailer.js b/src/mailer.js index 6f00665..bf67714 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -1,5 +1,5 @@ const nodemailer = require('nodemailer'); -const config = require('../config.json'); +const { config } = require('./config-manager'); const transporter = nodemailer.createTransport(config.email); diff --git a/src/server.js b/src/server.js index 5711f6d..b3202c6 100644 --- a/src/server.js +++ b/src/server.js @@ -1,5 +1,9 @@ process.title = 'Pretendo - Account'; +const configManager = require('./config-manager'); + +configManager.configure(); + const express = require('express'); const morgan = require('morgan'); const xmlparser = require('./middleware/xml-parser'); @@ -7,7 +11,8 @@ const cache = require('./cache'); const database = require('./database'); const util = require('./util'); const logger = require('../logger'); -const config = require('../config.json'); + +const { config } = configManager; const { http: { port } } = config; const app = express(); @@ -19,8 +24,6 @@ const datastore = require('./services/datastore'); const api = require('./services/api'); // START APPLICATION -app.set('etag', false); -app.disable('x-powered-by'); // Create router logger.info('Setting up Middleware'); diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index 5f91aac..f2bfa06 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -12,7 +12,7 @@ const database = require('../../../../database'); const cache = require('../../../../cache'); const util = require('../../../../util'); const logger = require('../../../../../logger'); -const config = require('../../../../../config.json'); +const { config } = require('../../../../config-manager'); const PNID_VALID_CHARACTERS_REGEX = /^[\w\-\.]*$/gm; const PNID_PUNCTUATION_START_REGEX = /^[\_\-\.]/gm; diff --git a/src/services/api/routes/v1/user.js b/src/services/api/routes/v1/user.js index 07c014d..ee8ad4a 100644 --- a/src/services/api/routes/v1/user.js +++ b/src/services/api/routes/v1/user.js @@ -1,7 +1,7 @@ const router = require('express').Router(); const joi = require('joi'); const { PNID } = require('../../../../models/pnid'); -const config = require('../../../../../config.json'); +const { config } = require('../../../../config-manager'); // TODO: Extend this later with more settings const userSchema = joi.object({ diff --git a/src/services/nnid/routes/miis.js b/src/services/nnid/routes/miis.js index bc99ce9..82ff0d6 100644 --- a/src/services/nnid/routes/miis.js +++ b/src/services/nnid/routes/miis.js @@ -1,7 +1,7 @@ const router = require('express').Router(); const xmlbuilder = require('xmlbuilder'); const { PNID } = require('../../../models/pnid'); -const config = require('../../../../config.json'); +const { config } = require('../../../config-manager'); /** * [GET] diff --git a/src/util.js b/src/util.js index 32f3cab..c7073f6 100644 --- a/src/util.js +++ b/src/util.js @@ -3,7 +3,7 @@ const NodeRSA = require('node-rsa'); const aws = require('aws-sdk'); const mailer = require('./mailer'); const cache = require('./cache'); -const config = require('../config.json'); +const { config } = require('./config-manager'); const spacesEndpoint = new aws.Endpoint('nyc3.digitaloceanspaces.com'); const s3 = new aws.S3({ From 625bab0e25e6eaeefcc03ec8702dfa1a6f0cc3f8 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 8 Oct 2022 09:56:17 -0400 Subject: [PATCH 075/105] Added loading config from env --- example.env | 18 +++++++++++++ package-lock.json | 14 ++++++++++ package.json | 1 + src/config-manager.js | 62 ++++++++++++++++++++++++++++++++++++++----- 4 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 example.env diff --git a/example.env b/example.env new file mode 100644 index 0000000..5c34138 --- /dev/null +++ b/example.env @@ -0,0 +1,18 @@ +PN_ACT_PREFER_ENV_CONFIG=true # Load config from ENV instead of config.json +PN_ACT_CONFIG_HTTP_PORT=7070 +PN_ACT_CONFIG_MONGO_URI=mongodb://localhost:27017 +PN_ACT_CONFIG_MONGO_DB_NAME=database_name +PN_ACT_CONFIG_MONGOOSE_OPTION_useNewUrlParser=true +PN_ACT_CONFIG_MONGOOSE_OPTION_useUnifiedTopology=true +PN_ACT_CONFIG_REDIS_URL=redis://localhost:6379 +PN_ACT_CONFIG_EMAIL_HOST=smtp.gmail.com +PN_ACT_CONFIG_EMAIL_PORT=587 +PN_ACT_CONFIG_EMAIL_SECURE=false +PN_ACT_CONFIG_EMAIL_USERNAME=username +PN_ACT_CONFIG_EMAIL_PASSWORD=password +PN_ACT_CONFIG_EMAIL_FROM=Company Name +PN_ACT_CONFIG_S3_ACCESS_KEY=ACCESS_KEY +PN_ACT_CONFIG_S3_ACCESS_SECRET=ACCESS_SECRET +PN_ACT_CONFIG_HCAPTCHA_SECRET=0x0000000000000000000000000000000000000000 +PN_ACT_CONFIG_CDN_BASE=https://example.com +PN_ACT_CONFIG_WEBSITE_BASE=https://example.com \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 00a2f1b..bc218c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "colors": "^1.4.0", "cors": "^2.8.5", "dicer": "^0.2.5", + "dotenv": "^16.0.3", "email-validator": "^2.0.4", "express": "^4.17.1", "express-form-data": "^2.0.17", @@ -1083,6 +1084,14 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, "node_modules/dtype": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz", @@ -4540,6 +4549,11 @@ } } }, + "dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + }, "dtype": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz", diff --git a/package.json b/package.json index 1ef4be4..6c889d8 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "colors": "^1.4.0", "cors": "^2.8.5", "dicer": "^0.2.5", + "dotenv": "^16.0.3", "email-validator": "^2.0.4", "express": "^4.17.1", "express-form-data": "^2.0.17", diff --git a/src/config-manager.js b/src/config-manager.js index bfde2ea..51e2ec5 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -1,6 +1,8 @@ const fs = require('fs-extra'); const logger = require('../logger'); +require('dotenv').config(); + /** * @typedef {Object} Config * @property {object} http HTTP server settings @@ -16,7 +18,7 @@ const logger = require('../logger'); * @property {string} email.host SMTP server address * @property {number} email.port SMTP server port * @property {boolean} email.secure Secure SMTP - * @property {string} email.from Email "from" name/address + * @property {string} email.from Email 'from' name/address * @property {object} email.auth Email authentication settings * @property {string} email.auth.user Email username * @property {string} email.auth.pass Email password @@ -36,12 +38,60 @@ const logger = require('../logger'); let config = {}; function configure() { - if (!fs.pathExistsSync(`${__dirname}/../config.json`)) { - logger.error('Failed to locate config.json file'); - process.exit(0); - } + if (process.env.PN_ACT_PREFER_ENV_CONFIG === 'true') { + logger.info('Loading config from env'); + + config = { + http: { + port: Number(process.env.PN_ACT_CONFIG_HTTP_PORT) + }, + mongoose: { + uri: process.env.PN_ACT_CONFIG_MONGO_URI, + database: process.env.PN_ACT_CONFIG_MONGO_DB_NAME, + options: Object.keys(process.env) + .filter(key => key.startsWith('PN_ACT_CONFIG_MONGOOSE_OPTION_')) + .reduce((obj, key) => { + obj[key.split('_').pop()] = process.env[key]; + return obj; + }, {}) + }, + redis: { + client: { + url: process.env.PN_ACT_CONFIG_REDIS_URL + } + }, + email: { + host: process.env.PN_ACT_CONFIG_EMAIL_HOST, + port: Number(process.env.PN_ACT_CONFIG_EMAIL_PORT), + secure: Boolean(process.env.PN_ACT_CONFIG_EMAIL_SECURE), + auth: { + user: process.env.PN_ACT_CONFIG_EMAIL_USERNAME, + pass: process.env.PN_ACT_CONFIG_EMAIL_PASSWORD + }, + from: process.env.PN_ACT_CONFIG_EMAIL_FROM + }, + aws: { + spaces: { + key: process.env.PN_ACT_CONFIG_S3_ACCESS_KEY, + secret: process.env.PN_ACT_CONFIG_S3_ACCESS_SECRET + } + }, + hcaptcha: { + secret: process.env.PN_ACT_CONFIG_HCAPTCHA_SECRET + }, + cdn_base: process.env.PN_ACT_CONFIG_CDN_BASE, + website_base: process.env.PN_ACT_CONFIG_WEBSITE_BASE + }; + } else { + logger.info('Loading config from config.json'); - config = require(`${__dirname}/../config.json`); + if (!fs.pathExistsSync(`${__dirname}/../config.json`)) { + logger.error('Failed to locate config.json file'); + process.exit(0); + } + + config = require(`${__dirname}/../config.json`); + } module.exports.config = config; } From 3b6a4eeb076d8213f3eaf1ee6d2f11610a8739ca Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 8 Oct 2022 10:26:48 -0400 Subject: [PATCH 076/105] Added required fields check to config manager --- package-lock.json | 22 ++++++++++++++++++++++ package.json | 2 ++ src/config-manager.js | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/package-lock.json b/package-lock.json index bc218c5..ce5f210 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,8 @@ "image-pixels": "^1.1.1", "joi": "^17.6.1", "kaitai-struct": "^0.9.0", + "lodash.has": "^4.5.2", + "lodash.set": "^4.3.2", "mii-js": "github:PretendoNetwork/mii-js", "moment": "^2.24.0", "moment-timezone": "^0.5.27", @@ -2055,6 +2057,16 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, + "node_modules/lodash.has": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", + "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" + }, + "node_modules/lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -5350,6 +5362,16 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, + "lodash.has": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", + "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" + }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" + }, "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", diff --git a/package.json b/package.json index 6c889d8..931fbaf 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,8 @@ "image-pixels": "^1.1.1", "joi": "^17.6.1", "kaitai-struct": "^0.9.0", + "lodash.has": "^4.5.2", + "lodash.set": "^4.3.2", "mii-js": "github:PretendoNetwork/mii-js", "moment": "^2.24.0", "moment-timezone": "^0.5.27", diff --git a/src/config-manager.js b/src/config-manager.js index 51e2ec5..36dd277 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -1,4 +1,6 @@ const fs = require('fs-extra'); +const has = require('lodash.has'); +const set = require('lodash.set'); const logger = require('../logger'); require('dotenv').config(); @@ -37,6 +39,24 @@ require('dotenv').config(); */ let config = {}; +const requiredFields = [ + ['http.port', 'PN_ACT_CONFIG_HTTP_PORT', Number], + ['mongoose.uri', 'PN_ACT_CONFIG_MONGO_URI'], + ['mongoose.database', 'PN_ACT_CONFIG_MONGO_DB_NAME'], + ['redis.client.url', 'PN_ACT_CONFIG_REDIS_URL'], + ['email.host', 'PN_ACT_CONFIG_EMAIL_HOST'], + ['email.port', 'PN_ACT_CONFIG_EMAIL_PORT', Number], + ['email.secure', 'PN_ACT_CONFIG_EMAIL_SECURE', Boolean], + ['email.auth.user', 'PN_ACT_CONFIG_EMAIL_USERNAME'], + ['email.auth.pass', 'PN_ACT_CONFIG_EMAIL_PASSWORD'], + ['email.from', 'PN_ACT_CONFIG_EMAIL_FROM'], + ['aws.spaces.key', 'PN_ACT_CONFIG_S3_ACCESS_KEY'], + ['aws.spaces.secret', 'PN_ACT_CONFIG_S3_ACCESS_SECRET'], + ['hcaptcha.secret', 'PN_ACT_CONFIG_HCAPTCHA_SECRET'], + ['cdn_base', 'PN_ACT_CONFIG_CDN_BASE'], + ['website_base', 'PN_ACT_CONFIG_WEBSITE_BASE'], +]; + function configure() { if (process.env.PN_ACT_PREFER_ENV_CONFIG === 'true') { logger.info('Loading config from env'); @@ -93,6 +113,26 @@ function configure() { config = require(`${__dirname}/../config.json`); } + logger.info('Config loaded, checking integrity'); + + for (const requiredField of requiredFields) { + const [keyPath, env, convertType] = requiredField; + + if (!has(config, keyPath)) { + if (!process.env[env] || process.env[env].trim() === '') { + logger.error(`Failed to locate required field ${keyPath}. Set ${keyPath} in config.json or the ${env} environment variable`); + + process.exit(0); + } else { + logger.info(`${keyPath} not found in config, using environment variable ${env}`); + + const newValue = process.env[env]; + + set(config, keyPath, convertType ? convertType(newValue) : newValue); + } + } + } + module.exports.config = config; } From 1ed9b4c848095c48080ad6c395e7f3ecee493979 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 13:45:39 -0400 Subject: [PATCH 077/105] Made redis cache optional --- src/cache.js | 32 +++++++++++++++++++++++--------- src/config-manager.js | 24 +++++++++++++++++++++++- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/cache.js b/src/cache.js index 6cd90de..d0b94d8 100644 --- a/src/cache.js +++ b/src/cache.js @@ -1,30 +1,44 @@ const fs = require('fs-extra'); const redis = require('redis'); -const { config } = require('./config-manager'); +const { config, disabledFeatures } = require('./config-manager'); let client; +const memoryCache = {}; + const SERVICE_CERTS_BASE = `${__dirname}/../certs/service`; const NEX_CERTS_BASE = `${__dirname}/../certs/nex`; async function connect() { - client = redis.createClient(config.redis.client); - client.on('error', (err) => console.log('Redis Client Error', err)); + if (!disabledFeatures.redis) { + client = redis.createClient(config.redis.client); + client.on('error', (err) => console.log('Redis Client Error', err)); - await client.connect(); + await client.connect(); + } } async function setCachedFile(type, name, fileName, value) { - await client.set(`${type}:${name}:${fileName}`, value); + if (disabledFeatures.redis) { + memoryCache[`${type}:${name}:${fileName}`] = value; + } else { + await client.set(`${type}:${name}:${fileName}`, value); + } } async function getCachedFile(type, name, fileName, encoding) { - const cachedFile = await client.get(`${type}:${name}:${fileName}`); + let cachedFile; - if (cachedFile !== null) { - return Buffer.from(cachedFile, encoding); + if (disabledFeatures.redis) { + cachedFile = memoryCache[`${type}:${name}:${fileName}`]; } else { - return cachedFile; + cachedFile = await client.get(`${type}:${name}:${fileName}`); } + + if (cachedFile !== null) { + cachedFile = Buffer.from(cachedFile, encoding); + } + + return cachedFile; } // NEX server cache functions diff --git a/src/config-manager.js b/src/config-manager.js index 36dd277..bf95ae0 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -39,11 +39,23 @@ require('dotenv').config(); */ let config = {}; + +/** + * @typedef {Object} DisabledFeatures + * @property {boolean} redis true if redis is disabled + */ + +/** + * @type {DisabledFeatures} + */ +const disabledFeatures = { + redis: false +}; + const requiredFields = [ ['http.port', 'PN_ACT_CONFIG_HTTP_PORT', Number], ['mongoose.uri', 'PN_ACT_CONFIG_MONGO_URI'], ['mongoose.database', 'PN_ACT_CONFIG_MONGO_DB_NAME'], - ['redis.client.url', 'PN_ACT_CONFIG_REDIS_URL'], ['email.host', 'PN_ACT_CONFIG_EMAIL_HOST'], ['email.port', 'PN_ACT_CONFIG_EMAIL_PORT', Number], ['email.secure', 'PN_ACT_CONFIG_EMAIL_SECURE', Boolean], @@ -115,6 +127,7 @@ function configure() { logger.info('Config loaded, checking integrity'); + // * Check for required settings for (const requiredField of requiredFields) { const [keyPath, env, convertType] = requiredField; @@ -133,6 +146,15 @@ function configure() { } } + // * Check for optional settings + if (!has(config, 'redis.client.url')) { + if (!process.env.PN_ACT_CONFIG_REDIS_URL || process.env.PN_ACT_CONFIG_REDIS_URL.trim() === '') { + logger.warning('Failed to find Redis config. Disabling feature and using in-memory cache'); + + disabledFeatures.redis = true; + } + } + module.exports.config = config; } From 566cd987cf56d9b327b20447979cab12cf27f134 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 13:48:02 -0400 Subject: [PATCH 078/105] Fixed redis client cache name issue --- src/cache.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/cache.js b/src/cache.js index d0b94d8..f20a8fe 100644 --- a/src/cache.js +++ b/src/cache.js @@ -17,21 +17,21 @@ async function connect() { } } -async function setCachedFile(type, name, fileName, value) { +async function setCachedFile(fileName, value) { if (disabledFeatures.redis) { - memoryCache[`${type}:${name}:${fileName}`] = value; + memoryCache[fileName] = value; } else { - await client.set(`${type}:${name}:${fileName}`, value); + await client.set(fileName, value); } } -async function getCachedFile(type, name, fileName, encoding) { +async function getCachedFile(fileName, encoding) { let cachedFile; if (disabledFeatures.redis) { - cachedFile = memoryCache[`${type}:${name}:${fileName}`]; + cachedFile = memoryCache[fileName]; } else { - cachedFile = await client.get(`${type}:${name}:${fileName}`); + cachedFile = await client.get(fileName); } if (cachedFile !== null) { @@ -90,19 +90,19 @@ async function getNEXAESKey(name, encoding) { } async function setNEXPublicKey(name, value) { - await setCachedFile('nex', name, 'public_key', value); + await setCachedFile(`nex:${name}:public_key`, value); } async function setNEXPrivateKey(name, value) { - await setCachedFile('nex', name, 'private_key', value); + await setCachedFile(`nex:${name}:private_key`, value); } async function setNEXSecretKey(name, value) { - await setCachedFile('nex', name, 'secret_key', value); + await setCachedFile(`nex:${name}:secret_key`, value); } async function setNEXAESKey(name, value) { - await setCachedFile('nex', name, 'aes_key', value); + await setCachedFile(`nex:${name}:aes_key`, value); } // 3rd party service cache functions @@ -154,19 +154,19 @@ async function getServiceAESKey(name, encoding) { } async function setServicePublicKey(name, value) { - await setCachedFile('service', name, 'public_key', value); + await setCachedFile(`service:${name}:public_key`, value); } async function setServicePrivateKey(name, value) { - await setCachedFile('service', name, 'private_key', value); + await setCachedFile(`service:${name}:private_key`, value); } async function setServiceSecretKey(name, value) { - await setCachedFile('service', name, 'secret_key', value); + await setCachedFile(`service:${name}:secret_key`, value); } async function setServiceAESKey(name, value) { - await setCachedFile('service', name, 'aes_key', value); + await setCachedFile(`service:${name}:aes_key`, value); } module.exports = { From 1b2141ff762d81c0b9ce9d83191e5981b5178848 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 13:54:42 -0400 Subject: [PATCH 079/105] Improved config value set checks --- package-lock.json | 16 +++------------- package.json | 2 +- src/config-manager.js | 19 +++++++++++++------ 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index ce5f210..4fa0176 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "image-pixels": "^1.1.1", "joi": "^17.6.1", "kaitai-struct": "^0.9.0", - "lodash.has": "^4.5.2", + "lodash.get": "^4.4.2", "lodash.set": "^4.3.2", "mii-js": "github:PretendoNetwork/mii-js", "moment": "^2.24.0", @@ -2055,12 +2055,7 @@ "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" }, "node_modules/lodash.set": { "version": "4.3.2", @@ -5360,12 +5355,7 @@ "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" }, "lodash.set": { "version": "4.3.2", diff --git a/package.json b/package.json index 931fbaf..bed4955 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "image-pixels": "^1.1.1", "joi": "^17.6.1", "kaitai-struct": "^0.9.0", - "lodash.has": "^4.5.2", + "lodash.get": "^4.4.2", "lodash.set": "^4.3.2", "mii-js": "github:PretendoNetwork/mii-js", "moment": "^2.24.0", diff --git a/src/config-manager.js b/src/config-manager.js index bf95ae0..009fe4a 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -1,5 +1,5 @@ const fs = require('fs-extra'); -const has = require('lodash.has'); +const get = require('lodash.get'); const set = require('lodash.set'); const logger = require('../logger'); @@ -131,15 +131,18 @@ function configure() { for (const requiredField of requiredFields) { const [keyPath, env, convertType] = requiredField; - if (!has(config, keyPath)) { - if (!process.env[env] || process.env[env].trim() === '') { + const configValue = get(config, keyPath); + const envValue = get(process.env, keyPath); + + if (!configValue || configValue.trim() === '') { + if (!envValue || envValue.trim() === '') { logger.error(`Failed to locate required field ${keyPath}. Set ${keyPath} in config.json or the ${env} environment variable`); process.exit(0); } else { logger.info(`${keyPath} not found in config, using environment variable ${env}`); - const newValue = process.env[env]; + const newValue = envValue; set(config, keyPath, convertType ? convertType(newValue) : newValue); } @@ -147,8 +150,12 @@ function configure() { } // * Check for optional settings - if (!has(config, 'redis.client.url')) { - if (!process.env.PN_ACT_CONFIG_REDIS_URL || process.env.PN_ACT_CONFIG_REDIS_URL.trim() === '') { + + const redisConfigValue = get(config, 'redis.client.url'); + const redisEnvValue = get(process.env, 'redis.client.url'); + + if (!redisConfigValue || redisConfigValue.trim() === '') { + if (!redisEnvValue || redisEnvValue.trim() === '') { logger.warning('Failed to find Redis config. Disabling feature and using in-memory cache'); disabledFeatures.redis = true; From 741a03edd99cbcea057a35681ddacbd07b26fb61 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 14:10:59 -0400 Subject: [PATCH 080/105] Made email sending optional --- src/config-manager.js | 76 +++++++++++++++++++++++++++++++++++++++---- src/mailer.js | 14 +++++--- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/src/config-manager.js b/src/config-manager.js index 009fe4a..7bb46c9 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -43,25 +43,21 @@ let config = {}; /** * @typedef {Object} DisabledFeatures * @property {boolean} redis true if redis is disabled + * @property {boolean} email true if email sending is disabled */ /** * @type {DisabledFeatures} */ const disabledFeatures = { - redis: false + redis: false, + email: false }; const requiredFields = [ ['http.port', 'PN_ACT_CONFIG_HTTP_PORT', Number], ['mongoose.uri', 'PN_ACT_CONFIG_MONGO_URI'], ['mongoose.database', 'PN_ACT_CONFIG_MONGO_DB_NAME'], - ['email.host', 'PN_ACT_CONFIG_EMAIL_HOST'], - ['email.port', 'PN_ACT_CONFIG_EMAIL_PORT', Number], - ['email.secure', 'PN_ACT_CONFIG_EMAIL_SECURE', Boolean], - ['email.auth.user', 'PN_ACT_CONFIG_EMAIL_USERNAME'], - ['email.auth.pass', 'PN_ACT_CONFIG_EMAIL_PASSWORD'], - ['email.from', 'PN_ACT_CONFIG_EMAIL_FROM'], ['aws.spaces.key', 'PN_ACT_CONFIG_S3_ACCESS_KEY'], ['aws.spaces.secret', 'PN_ACT_CONFIG_S3_ACCESS_SECRET'], ['hcaptcha.secret', 'PN_ACT_CONFIG_HCAPTCHA_SECRET'], @@ -162,6 +158,72 @@ function configure() { } } + const emailHostConfigValue = get(config, 'email.host'); + const emailHostEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_HOST'); + + if (!emailHostConfigValue || emailHostConfigValue.trim() === '') { + if (!emailHostEnvValue || emailHostEnvValue.trim() === '') { + logger.warning('Failed to find email SMTP host config. Disabling feature'); + + disabledFeatures.email = true; + } + } + + const emailPortConfigValue = get(config, 'email.port'); + const emailPortEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_PORT'); + + if (!emailPortConfigValue) { + if (!emailPortEnvValue || emailPortEnvValue.trim() === '') { + logger.warning('Failed to find email SMTP port config. Disabling feature'); + + disabledFeatures.email = true; + } + } + + const emailSecureConfigValue = get(config, 'email.secure'); + const emailSecureEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_SECURE'); + + if (emailSecureConfigValue === undefined) { + if (!emailSecureEnvValue || emailSecureEnvValue.trim() === '') { + logger.warning('Failed to find email SMTP secure config. Disabling feature'); + + disabledFeatures.email = true; + } + } + + const emailUsernameConfigValue = get(config, 'email.auth.user'); + const emailUsernameEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_USERNAME'); + + if (!emailUsernameConfigValue || emailUsernameConfigValue.trim() === '') { + if (!emailUsernameEnvValue || emailUsernameEnvValue.trim() === '') { + logger.warning('Failed to find email username config. Disabling feature'); + + disabledFeatures.email = true; + } + } + + const emailPasswordConfigValue = get(config, 'email.auth.pass'); + const emailPasswordEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_PASSWORD'); + + if (!emailPasswordConfigValue || emailPasswordConfigValue.trim() === '') { + if (!emailPasswordEnvValue || emailPasswordEnvValue.trim() === '') { + logger.warning('Failed to find email password config. Disabling feature'); + + disabledFeatures.email = true; + } + } + + const emailFromConfigValue = get(config, 'email.from'); + const emailFromEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_FROM'); + + if (!emailFromConfigValue || emailFromConfigValue.trim() === '') { + if (!emailFromEnvValue || emailFromEnvValue.trim() === '') { + logger.warning('Failed to find email from config. Disabling feature'); + + disabledFeatures.email = true; + } + } + module.exports.config = config; } diff --git a/src/mailer.js b/src/mailer.js index bf67714..d8228e2 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -1,12 +1,18 @@ const nodemailer = require('nodemailer'); -const { config } = require('./config-manager'); +const { config, disabledFeatures } = require('./config-manager'); -const transporter = nodemailer.createTransport(config.email); +let transporter; + +if (!disabledFeatures.email) { + transporter = nodemailer.createTransport(config.email); +} async function sendMail(options) { - options.from = config.email.from; + if (!disabledFeatures.email) { + options.from = config.email.from; - await transporter.sendMail(options); + await transporter.sendMail(options); + } } module.exports = { From 4809618b0206f8bc8be85a85272aaa766f22aefb Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 14:11:27 -0400 Subject: [PATCH 081/105] logger.warning should be logger.warn --- src/config-manager.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/config-manager.js b/src/config-manager.js index 7bb46c9..86a97f1 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -152,7 +152,7 @@ function configure() { if (!redisConfigValue || redisConfigValue.trim() === '') { if (!redisEnvValue || redisEnvValue.trim() === '') { - logger.warning('Failed to find Redis config. Disabling feature and using in-memory cache'); + logger.warn('Failed to find Redis config. Disabling feature and using in-memory cache'); disabledFeatures.redis = true; } @@ -163,7 +163,7 @@ function configure() { if (!emailHostConfigValue || emailHostConfigValue.trim() === '') { if (!emailHostEnvValue || emailHostEnvValue.trim() === '') { - logger.warning('Failed to find email SMTP host config. Disabling feature'); + logger.warn('Failed to find email SMTP host config. Disabling feature'); disabledFeatures.email = true; } @@ -174,7 +174,7 @@ function configure() { if (!emailPortConfigValue) { if (!emailPortEnvValue || emailPortEnvValue.trim() === '') { - logger.warning('Failed to find email SMTP port config. Disabling feature'); + logger.warn('Failed to find email SMTP port config. Disabling feature'); disabledFeatures.email = true; } @@ -185,7 +185,7 @@ function configure() { if (emailSecureConfigValue === undefined) { if (!emailSecureEnvValue || emailSecureEnvValue.trim() === '') { - logger.warning('Failed to find email SMTP secure config. Disabling feature'); + logger.warn('Failed to find email SMTP secure config. Disabling feature'); disabledFeatures.email = true; } @@ -196,7 +196,7 @@ function configure() { if (!emailUsernameConfigValue || emailUsernameConfigValue.trim() === '') { if (!emailUsernameEnvValue || emailUsernameEnvValue.trim() === '') { - logger.warning('Failed to find email username config. Disabling feature'); + logger.warn('Failed to find email username config. Disabling feature'); disabledFeatures.email = true; } @@ -207,7 +207,7 @@ function configure() { if (!emailPasswordConfigValue || emailPasswordConfigValue.trim() === '') { if (!emailPasswordEnvValue || emailPasswordEnvValue.trim() === '') { - logger.warning('Failed to find email password config. Disabling feature'); + logger.warn('Failed to find email password config. Disabling feature'); disabledFeatures.email = true; } @@ -218,7 +218,7 @@ function configure() { if (!emailFromConfigValue || emailFromConfigValue.trim() === '') { if (!emailFromEnvValue || emailFromEnvValue.trim() === '') { - logger.warning('Failed to find email from config. Disabling feature'); + logger.warn('Failed to find email from config. Disabling feature'); disabledFeatures.email = true; } From 272e640a8b015b29c98065834f883f3b78ef0eb5 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 14:12:35 -0400 Subject: [PATCH 082/105] Fixed required features type check --- src/config-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config-manager.js b/src/config-manager.js index 86a97f1..0d55280 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -130,7 +130,7 @@ function configure() { const configValue = get(config, keyPath); const envValue = get(process.env, keyPath); - if (!configValue || configValue.trim() === '') { + if (!configValue || (typeof configValue === 'string' && configValue.trim() === '')) { if (!envValue || envValue.trim() === '') { logger.error(`Failed to locate required field ${keyPath}. Set ${keyPath} in config.json or the ${env} environment variable`); From 9bb83632db5959c75a24e9f3680a20d5ae99e6a7 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 14:12:48 -0400 Subject: [PATCH 083/105] Actually export disabledFeatures --- src/config-manager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config-manager.js b/src/config-manager.js index 0d55280..b719e58 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -229,5 +229,6 @@ function configure() { module.exports = { configure, - config + config, + disabledFeatures }; \ No newline at end of file From 19222bbf2dba8090e8fc3faa5b0d014a50b39f07 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 14:14:33 -0400 Subject: [PATCH 084/105] Fixed redis config env check --- src/config-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config-manager.js b/src/config-manager.js index b719e58..95d5d2f 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -148,7 +148,7 @@ function configure() { // * Check for optional settings const redisConfigValue = get(config, 'redis.client.url'); - const redisEnvValue = get(process.env, 'redis.client.url'); + const redisEnvValue = get(process.env, 'PN_ACT_CONFIG_REDIS_URL'); if (!redisConfigValue || redisConfigValue.trim() === '') { if (!redisEnvValue || redisEnvValue.trim() === '') { From ce46c51c968a2a34aae801099797de99d0198da9 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 14:19:37 -0400 Subject: [PATCH 085/105] Set config fallbacks using env --- src/config-manager.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/config-manager.js b/src/config-manager.js index 95d5d2f..b8cf5e6 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -155,6 +155,10 @@ function configure() { logger.warn('Failed to find Redis config. Disabling feature and using in-memory cache'); disabledFeatures.redis = true; + } else { + logger.info('redis.client.url not found in config, using environment variable PN_ACT_CONFIG_REDIS_URL'); + + set(config, 'redis.client.url', redisEnvValue); } } @@ -166,6 +170,10 @@ function configure() { logger.warn('Failed to find email SMTP host config. Disabling feature'); disabledFeatures.email = true; + } else { + logger.info('email.host not found in config, using environment variable PN_ACT_CONFIG_EMAIL_HOST'); + + set(config, 'email.host', emailHostEnvValue); } } @@ -177,6 +185,10 @@ function configure() { logger.warn('Failed to find email SMTP port config. Disabling feature'); disabledFeatures.email = true; + } else { + logger.info('email.port not found in config, using environment variable PN_ACT_CONFIG_EMAIL_PORT'); + + set(config, 'email.port', Number(emailPortEnvValue)); } } @@ -188,6 +200,10 @@ function configure() { logger.warn('Failed to find email SMTP secure config. Disabling feature'); disabledFeatures.email = true; + } else { + logger.info('email.secure not found in config, using environment variable PN_ACT_CONFIG_EMAIL_SECURE'); + + set(config, 'email.secure', Boolean(emailSecureEnvValue)); } } @@ -199,6 +215,10 @@ function configure() { logger.warn('Failed to find email username config. Disabling feature'); disabledFeatures.email = true; + } else { + logger.info('email.auth.user not found in config, using environment variable PN_ACT_CONFIG_EMAIL_USERNAME'); + + set(config, 'email.auth.user', emailUsernameEnvValue); } } @@ -210,6 +230,10 @@ function configure() { logger.warn('Failed to find email password config. Disabling feature'); disabledFeatures.email = true; + } else { + logger.info('email.pass not found in config, using environment variable PN_ACT_CONFIG_EMAIL_PASSWORD'); + + set(config, 'email.pass', emailPasswordEnvValue); } } @@ -221,6 +245,10 @@ function configure() { logger.warn('Failed to find email from config. Disabling feature'); disabledFeatures.email = true; + } else { + logger.info('email.from not found in config, using environment variable PN_ACT_CONFIG_EMAIL_FROM'); + + set(config, 'email.from', emailFromEnvValue); } } From 8f5dcb2f9ae4f876b868c7d531efaf34c0f4e49a Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 14:23:34 -0400 Subject: [PATCH 086/105] Made captcha verification optional --- src/config-manager.js | 20 ++++++++++++-- src/services/api/routes/v1/register.js | 36 ++++++++++++++------------ 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/config-manager.js b/src/config-manager.js index b8cf5e6..0a8733c 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -44,6 +44,7 @@ let config = {}; * @typedef {Object} DisabledFeatures * @property {boolean} redis true if redis is disabled * @property {boolean} email true if email sending is disabled + * @property {boolean} captcha true if captcha verification is disabled */ /** @@ -51,7 +52,8 @@ let config = {}; */ const disabledFeatures = { redis: false, - email: false + email: false, + captcha: false }; const requiredFields = [ @@ -60,7 +62,6 @@ const requiredFields = [ ['mongoose.database', 'PN_ACT_CONFIG_MONGO_DB_NAME'], ['aws.spaces.key', 'PN_ACT_CONFIG_S3_ACCESS_KEY'], ['aws.spaces.secret', 'PN_ACT_CONFIG_S3_ACCESS_SECRET'], - ['hcaptcha.secret', 'PN_ACT_CONFIG_HCAPTCHA_SECRET'], ['cdn_base', 'PN_ACT_CONFIG_CDN_BASE'], ['website_base', 'PN_ACT_CONFIG_WEBSITE_BASE'], ]; @@ -252,6 +253,21 @@ function configure() { } } + const captchaSecretConfigValue = get(config, 'hcaptcha.secret'); + const captchaSecretEnvValue = get(process.env, 'PN_ACT_CONFIG_HCAPTCHA_SECRET'); + + if (!captchaSecretConfigValue || captchaSecretConfigValue.trim() === '') { + if (!captchaSecretEnvValue || captchaSecretEnvValue.trim() === '') { + logger.warn('Failed to find captcha secret config. Disabling feature'); + + disabledFeatures.email = true; + } else { + logger.info('hcaptcha.secret not found in config, using environment variable PN_ACT_CONFIG_HCAPTCHA_SECRET'); + + set(config, 'hcaptcha.secret', emailFromEnvValue); + } + } + module.exports.config = config; } diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.js index f2bfa06..729bc41 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.js @@ -12,7 +12,7 @@ const database = require('../../../../database'); const cache = require('../../../../cache'); const util = require('../../../../util'); const logger = require('../../../../../logger'); -const { config } = require('../../../../config-manager'); +const { config, disabledFeatures } = require('../../../../config-manager'); const PNID_VALID_CHARACTERS_REGEX = /^[\w\-\.]*$/gm; const PNID_PUNCTUATION_START_REGEX = /^[\_\-\.]/gm; @@ -42,22 +42,24 @@ router.post('/', async (request, response) => { const passwordConfirm = body.password_confirm?.trim(); const hCaptchaResponse = body.hCaptchaResponse?.trim(); - if (!hCaptchaResponse || hCaptchaResponse === '') { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Must fill in captcha' - }); - } - - const captchaVerify = await hcaptcha.verify(config.hcaptcha.secret, hCaptchaResponse); - - if (!captchaVerify.success) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Captcha verification failed' - }); + if (!disabledFeatures.captcha) { + if (!hCaptchaResponse || hCaptchaResponse === '') { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Must fill in captcha' + }); + } + + const captchaVerify = await hcaptcha.verify(config.hcaptcha.secret, hCaptchaResponse); + + if (!captchaVerify.success) { + return response.status(400).json({ + app: 'api', + status: 400, + error: 'Captcha verification failed' + }); + } } if (!email || email === '') { From 8ab51d7f96496ef585c7d4a81c856e5fc52f01a5 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 15:24:15 -0400 Subject: [PATCH 087/105] Made s3 optional --- example.env | 3 +- src/cache.js | 22 +++++++ src/config-manager.js | 89 ++++++++++++++++++++------ src/server.js | 2 + src/services/local-cdn/index.js | 30 +++++++++ src/services/local-cdn/routes/get.js | 16 +++++ src/services/local-cdn/routes/index.js | 3 + src/util.js | 49 +++++++++----- 8 files changed, 177 insertions(+), 37 deletions(-) create mode 100644 src/services/local-cdn/index.js create mode 100644 src/services/local-cdn/routes/get.js create mode 100644 src/services/local-cdn/routes/index.js diff --git a/example.env b/example.env index 5c34138..a5c1007 100644 --- a/example.env +++ b/example.env @@ -14,5 +14,6 @@ PN_ACT_CONFIG_EMAIL_FROM=Company Name PN_ACT_CONFIG_S3_ACCESS_KEY=ACCESS_KEY PN_ACT_CONFIG_S3_ACCESS_SECRET=ACCESS_SECRET PN_ACT_CONFIG_HCAPTCHA_SECRET=0x0000000000000000000000000000000000000000 -PN_ACT_CONFIG_CDN_BASE=https://example.com +PN_ACT_CONFIG_CDN_BASE=https://local-cdn.example.com +PN_ACT_CONFIG_CDN_SUBDOMAIN=local-cdn PN_ACT_CONFIG_WEBSITE_BASE=https://example.com \ No newline at end of file diff --git a/src/cache.js b/src/cache.js index f20a8fe..e889483 100644 --- a/src/cache.js +++ b/src/cache.js @@ -7,6 +7,7 @@ const memoryCache = {}; const SERVICE_CERTS_BASE = `${__dirname}/../certs/service`; const NEX_CERTS_BASE = `${__dirname}/../certs/nex`; +const LOCAL_CDN_BASE = `${__dirname}/../cdn`; async function connect() { if (!disabledFeatures.redis) { @@ -169,6 +170,25 @@ async function setServiceAESKey(name, value) { await setCachedFile(`service:${name}:aes_key`, value); } +// Local CDN cache functions + +async function getLocalCDNFile(name, encoding) { + let file = await getCachedFile(`local_cdn:${name}`, encoding); + + if (file === null) { + if (await fs.pathExists(`${LOCAL_CDN_BASE}/${name}`)) { + file = await fs.readFile(`${LOCAL_CDN_BASE}/${name}`, { encoding }); + await setLocalCDNFile(name, file); + } + } + + return file; +} + +async function setLocalCDNFile(name, value) { + await setCachedFile(`local_cdn:${name}`, value); +} + module.exports = { connect, getNEXPublicKey, @@ -187,4 +207,6 @@ module.exports = { setServicePrivateKey, setServiceSecretKey, setServiceAESKey, + getLocalCDNFile, + setLocalCDNFile }; \ No newline at end of file diff --git a/src/config-manager.js b/src/config-manager.js index 0a8733c..12615ac 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -13,23 +13,24 @@ require('dotenv').config(); * @property {string} mongoose.uri URI Mongoose will connect to * @property {string} mongoose.database MongoDB database name * @property {object} mongoose.options MongoDB connection options - * @property {object} redis redis settings - * @property {string} redis.client redis client settings - * @property {string} redis.client.url redis server URL - * @property {object} email node-mailer client settings - * @property {string} email.host SMTP server address - * @property {number} email.port SMTP server port - * @property {boolean} email.secure Secure SMTP - * @property {string} email.from Email 'from' name/address - * @property {object} email.auth Email authentication settings - * @property {string} email.auth.user Email username - * @property {string} email.auth.pass Email password - * @property {object} aws s3 client settings - * @property {object} aws.spaces Digital Ocean Spaces settings - * @property {string} aws.spaces.key s3 access key - * @property {string} aws.spaces.secret s3 access secret - * @property {object} hcaptcha hCaptcha settings - * @property {string} hcaptcha.secret hCaptcha secret + * @property {object} [redis] redis settings + * @property {string} [redis.client] redis client settings + * @property {string} [redis.client.url] redis server URL + * @property {object} [email] node-mailer client settings + * @property {string} [email.host] SMTP server address + * @property {number} [email.port] SMTP server port + * @property {boolean} [email.secure] Secure SMTP + * @property {string} [email.from] Email 'from' name/address + * @property {object} [email.auth] Email authentication settings + * @property {string} [email.auth.user] Email username + * @property {string} [email.auth.pass] Email password + * @property {object} [aws] s3 client settings + * @property {object} [aws.spaces] Digital Ocean Spaces settings + * @property {string} [aws.spaces.key] s3 access key + * @property {string} [aws.spaces.secret] s3 access secret + * @property {object} [hcaptcha] hCaptcha settings + * @property {string} [hcaptcha.secret] hCaptcha secret + * @property {string} [cdn_subdomain] Subdomain used for serving CDN contents when s3 is disabled * @property {string} cdn_base Base URL for CDN location * @property {string} website_base Base URL for service website (used with emails) */ @@ -45,6 +46,7 @@ let config = {}; * @property {boolean} redis true if redis is disabled * @property {boolean} email true if email sending is disabled * @property {boolean} captcha true if captcha verification is disabled + * @property {boolean} s3 true if s3 services is disabled */ /** @@ -53,15 +55,14 @@ let config = {}; const disabledFeatures = { redis: false, email: false, - captcha: false + captcha: false, + s3: false }; const requiredFields = [ ['http.port', 'PN_ACT_CONFIG_HTTP_PORT', Number], ['mongoose.uri', 'PN_ACT_CONFIG_MONGO_URI'], ['mongoose.database', 'PN_ACT_CONFIG_MONGO_DB_NAME'], - ['aws.spaces.key', 'PN_ACT_CONFIG_S3_ACCESS_KEY'], - ['aws.spaces.secret', 'PN_ACT_CONFIG_S3_ACCESS_SECRET'], ['cdn_base', 'PN_ACT_CONFIG_CDN_BASE'], ['website_base', 'PN_ACT_CONFIG_WEBSITE_BASE'], ]; @@ -268,6 +269,54 @@ function configure() { } } + const s3AccessKeyConfigValue = get(config, 'aws.spaces.key'); + const s3AccessKeyEnvValue = get(process.env, 'PN_ACT_CONFIG_S3_ACCESS_KEY'); + + if (!s3AccessKeyConfigValue || s3AccessKeyConfigValue.trim() === '') { + if (!s3AccessKeyEnvValue || s3AccessKeyEnvValue.trim() === '') { + logger.warn('Failed to find s3 access key config. Disabling feature'); + + disabledFeatures.s3 = true; + } else { + logger.info('aws.spaces.key not found in config, using environment variable PN_ACT_CONFIG_S3_ACCESS_KEY'); + + set(config, 'aws.spaces.key', s3AccessKeyEnvValue); + } + } + + const s3SecretKeyConfigValue = get(config, 'aws.spaces.secret'); + const s3SecretKeyEnvValue = get(process.env, 'PN_ACT_CONFIG_S3_ACCESS_SECRET'); + + if (!s3SecretKeyConfigValue || s3SecretKeyConfigValue.trim() === '') { + if (!s3SecretKeyEnvValue || s3SecretKeyEnvValue.trim() === '') { + logger.warn('Failed to find s3 secret key config. Disabling feature'); + + disabledFeatures.s3 = true; + } else { + logger.info('aws.spaces.secret not found in config, using environment variable PN_ACT_CONFIG_S3_ACCESS_SECRET'); + + set(config, 'aws.spaces.secret', s3AccessKeyEnvValue); + } + } + + if (disabledFeatures.s3) { + const cdnSubdomainConfigValue = get(config, 'cdn_subdomain'); + const cdnSubdomainEnvValue = get(process.env, 'PN_ACT_CONFIG_CDN_SUBDOMAIN'); + + if (!cdnSubdomainConfigValue || cdnSubdomainConfigValue.trim() === '') { + if (!cdnSubdomainEnvValue || cdnSubdomainEnvValue.trim() === '') { + logger.error('s3 file storage is disabled and no CDN subdomain was set. Set cdn_subdomain in config.json or the PN_ACT_CONFIG_CDN_SUBDOMAIN environment variable'); + process.exit(0); + } else { + logger.info('cdn_subdomain not found in config, using environment variable PN_ACT_CONFIG_CDN_SUBDOMAIN'); + + set(config, 'cdn_subdomain', cdnSubdomainEnvValue); + } + } + + logger.warn(`s3 file storage disabled. Using disk-based file storage. Please ensure cdn_base config or PN_ACT_CONFIG_CDN_BASE env variable is set to point to this server with the subdomain being ${config.cdn_subdomain}`); + } + module.exports.config = config; } diff --git a/src/server.js b/src/server.js index b3202c6..c4dcf6b 100644 --- a/src/server.js +++ b/src/server.js @@ -22,6 +22,7 @@ const nnid = require('./services/nnid'); const nasc = require('./services/nasc'); const datastore = require('./services/datastore'); const api = require('./services/api'); +const localcdn = require('./services/local-cdn'); // START APPLICATION @@ -40,6 +41,7 @@ app.use(nnid); app.use(nasc); app.use(datastore); app.use(api); +app.use(localcdn); // 404 handler logger.info('Creating 404 status handler'); diff --git a/src/services/local-cdn/index.js b/src/services/local-cdn/index.js new file mode 100644 index 0000000..1a0a9dc --- /dev/null +++ b/src/services/local-cdn/index.js @@ -0,0 +1,30 @@ +const express = require('express'); +const subdomain = require('express-subdomain'); +const logger = require('../../../logger'); +const { config, disabledFeatures } = require('../../config-manager'); + +if (!disabledFeatures.s3) { + // * s3 enabled, no need for this + + module.exports = express.Router(); + + return; +} + +const routes = require('./routes'); + +// Router to handle the subdomain +const localcdn = express.Router(); + +// Setup routes +logger.info('[LOCAL-CDN] Applying imported routes'); +localcdn.use(routes.GET); + +// Main router for endpoints +const router = express.Router(); + +// Create subdomains +logger.info(`[LOCAL-CDN] Creating '${config.cdn_subdomain}' subdomain`); +router.use(subdomain(config.cdn_subdomain, localcdn)); + +module.exports = router; \ No newline at end of file diff --git a/src/services/local-cdn/routes/get.js b/src/services/local-cdn/routes/get.js new file mode 100644 index 0000000..7ae69b9 --- /dev/null +++ b/src/services/local-cdn/routes/get.js @@ -0,0 +1,16 @@ +const router = require('express').Router(); +const cache = require('../../../cache'); + +router.get('/*', async (request, response) => { + const filePath = request.params[0]; + + const file = await cache.getLocalCDNFile(filePath); + + if (file) { + response.send(file); + } else { + response.sendStatus(404); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/src/services/local-cdn/routes/index.js b/src/services/local-cdn/routes/index.js new file mode 100644 index 0000000..033fca1 --- /dev/null +++ b/src/services/local-cdn/routes/index.js @@ -0,0 +1,3 @@ +module.exports = { + GET: require('./get.js'), +}; \ No newline at end of file diff --git a/src/util.js b/src/util.js index c7073f6..1f298d5 100644 --- a/src/util.js +++ b/src/util.js @@ -1,16 +1,21 @@ const crypto = require('crypto'); +const path = require('path'); const NodeRSA = require('node-rsa'); const aws = require('aws-sdk'); +const fs = require('fs-extra'); const mailer = require('./mailer'); const cache = require('./cache'); -const { config } = require('./config-manager'); +const { config, disabledFeatures } = require('./config-manager'); -const spacesEndpoint = new aws.Endpoint('nyc3.digitaloceanspaces.com'); -const s3 = new aws.S3({ - endpoint: spacesEndpoint, - accessKeyId: config.aws.spaces.key, - secretAccessKey: config.aws.spaces.secret -}); +let s3; + +if (!disabledFeatures.s3) { + s3 = new aws.S3({ + endpoint: new aws.Endpoint('nyc3.digitaloceanspaces.com'), + accessKeyId: config.aws.spaces.key, + secretAccessKey: config.aws.spaces.secret + }); +} function nintendoPasswordHash(password, pid) { const pidBuffer = Buffer.alloc(4); @@ -203,20 +208,32 @@ function unpackToken(token) { function fullUrl(request) { const protocol = request.protocol; const host = request.host; - const path = request.originalUrl; + const opath = request.originalUrl; - return `${protocol}://${host}${path}`; + return `${protocol}://${host}${opath}`; } async function uploadCDNAsset(bucket, key, data, acl) { - const awsPutParams = { - Body: data, - Key: key, - Bucket: bucket, - ACL: acl - }; + if (disabledFeatures.s3) { + await writeLocalCDNFile(key, data); + } else { + const awsPutParams = { + Body: data, + Key: key, + Bucket: bucket, + ACL: acl + }; + + await s3.putObject(awsPutParams).promise(); + } +} + +async function writeLocalCDNFile(key, data) { + const filePath = `${__dirname}/../cdn/${key}`; + const folder = path.dirname(filePath); - await s3.putObject(awsPutParams).promise(); + await fs.ensureDir(folder); + await fs.writeFile(filePath, data); } function nascError(errorCode) { From 15103a62c4d2a92d862a0e67a564c0203e026105 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 15:27:06 -0400 Subject: [PATCH 088/105] Moved website_base config check --- src/config-manager.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/config-manager.js b/src/config-manager.js index 12615ac..bedf103 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -63,8 +63,7 @@ const requiredFields = [ ['http.port', 'PN_ACT_CONFIG_HTTP_PORT', Number], ['mongoose.uri', 'PN_ACT_CONFIG_MONGO_URI'], ['mongoose.database', 'PN_ACT_CONFIG_MONGO_DB_NAME'], - ['cdn_base', 'PN_ACT_CONFIG_CDN_BASE'], - ['website_base', 'PN_ACT_CONFIG_WEBSITE_BASE'], + ['cdn_base', 'PN_ACT_CONFIG_CDN_BASE'] ]; function configure() { @@ -254,6 +253,22 @@ function configure() { } } + if (!disabledFeatures.email) { + const websiteBaseConfigValue = get(config, 'website_base'); + const websiteBaseEnvValue = get(process.env, 'PN_ACT_CONFIG_WEBSITE_BASE'); + + if (!websiteBaseConfigValue || websiteBaseConfigValue.trim() === '') { + if (!websiteBaseEnvValue || websiteBaseEnvValue.trim() === '') { + logger.error('Email sending is not disabled and no website base was set. Set website_base in config.json or the PN_ACT_CONFIG_WEBSITE_BASE environment variable'); + process.exit(0); + } else { + logger.info('website_base not found in config, using environment variable PN_ACT_CONFIG_WEBSITE_BASE'); + + set(config, 'website_base', websiteBaseEnvValue); + } + } + } + const captchaSecretConfigValue = get(config, 'hcaptcha.secret'); const captchaSecretEnvValue = get(process.env, 'PN_ACT_CONFIG_HCAPTCHA_SECRET'); From 1d3fdd3af7b9d705e5df2e6147ee205458da4a64 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 15:28:58 -0400 Subject: [PATCH 089/105] Fixed hcaptcha.secret setting wrong env variable --- src/config-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config-manager.js b/src/config-manager.js index bedf103..b61e8a4 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -280,7 +280,7 @@ function configure() { } else { logger.info('hcaptcha.secret not found in config, using environment variable PN_ACT_CONFIG_HCAPTCHA_SECRET'); - set(config, 'hcaptcha.secret', emailFromEnvValue); + set(config, 'hcaptcha.secret', captchaSecretEnvValue); } } From 64488b061d2dd406500a70d1eebee15a59c3a7c2 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 15:33:02 -0400 Subject: [PATCH 090/105] Added enable message to missing optional config values --- src/config-manager.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/config-manager.js b/src/config-manager.js index b61e8a4..2237783 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -153,7 +153,7 @@ function configure() { if (!redisConfigValue || redisConfigValue.trim() === '') { if (!redisEnvValue || redisEnvValue.trim() === '') { - logger.warn('Failed to find Redis config. Disabling feature and using in-memory cache'); + logger.warn('Failed to find Redis config. Disabling feature and using in-memory cache. To enable feature set redis.client.url in config.json or the PN_ACT_CONFIG_REDIS_URL environment variable'); disabledFeatures.redis = true; } else { @@ -168,7 +168,7 @@ function configure() { if (!emailHostConfigValue || emailHostConfigValue.trim() === '') { if (!emailHostEnvValue || emailHostEnvValue.trim() === '') { - logger.warn('Failed to find email SMTP host config. Disabling feature'); + logger.warn('Failed to find email SMTP host config. Disabling feature. To enable feature set email.host in config.json or the PN_ACT_CONFIG_EMAIL_HOST environment variable'); disabledFeatures.email = true; } else { @@ -183,7 +183,7 @@ function configure() { if (!emailPortConfigValue) { if (!emailPortEnvValue || emailPortEnvValue.trim() === '') { - logger.warn('Failed to find email SMTP port config. Disabling feature'); + logger.warn('Failed to find email SMTP port config. Disabling feature. To enable feature set email.port in config.json or the PN_ACT_CONFIG_EMAIL_PORT environment variable'); disabledFeatures.email = true; } else { @@ -198,7 +198,7 @@ function configure() { if (emailSecureConfigValue === undefined) { if (!emailSecureEnvValue || emailSecureEnvValue.trim() === '') { - logger.warn('Failed to find email SMTP secure config. Disabling feature'); + logger.warn('Failed to find email SMTP secure config. Disabling feature. To enable feature set email.secure in config.json or the PN_ACT_CONFIG_EMAIL_SECURE environment variable'); disabledFeatures.email = true; } else { @@ -213,7 +213,7 @@ function configure() { if (!emailUsernameConfigValue || emailUsernameConfigValue.trim() === '') { if (!emailUsernameEnvValue || emailUsernameEnvValue.trim() === '') { - logger.warn('Failed to find email username config. Disabling feature'); + logger.warn('Failed to find email username config. Disabling feature. To enable feature set email.auth.user in config.json or the auth.user environment variable'); disabledFeatures.email = true; } else { @@ -228,7 +228,7 @@ function configure() { if (!emailPasswordConfigValue || emailPasswordConfigValue.trim() === '') { if (!emailPasswordEnvValue || emailPasswordEnvValue.trim() === '') { - logger.warn('Failed to find email password config. Disabling feature'); + logger.warn('Failed to find email password config. Disabling feature. To enable feature set email.auth.pass in config.json or the PN_ACT_CONFIG_EMAIL_PASSWORD environment variable'); disabledFeatures.email = true; } else { @@ -243,7 +243,7 @@ function configure() { if (!emailFromConfigValue || emailFromConfigValue.trim() === '') { if (!emailFromEnvValue || emailFromEnvValue.trim() === '') { - logger.warn('Failed to find email from config. Disabling feature'); + logger.warn('Failed to find email from config. Disabling feature. To enable feature set email.from in config.json or the PN_ACT_CONFIG_EMAIL_FROM environment variable'); disabledFeatures.email = true; } else { @@ -274,7 +274,7 @@ function configure() { if (!captchaSecretConfigValue || captchaSecretConfigValue.trim() === '') { if (!captchaSecretEnvValue || captchaSecretEnvValue.trim() === '') { - logger.warn('Failed to find captcha secret config. Disabling feature'); + logger.warn('Failed to find captcha secret config. Disabling feature. To enable feature set hcaptcha.secret in config.json or the PN_ACT_CONFIG_HCAPTCHA_SECRET environment variable'); disabledFeatures.email = true; } else { @@ -289,7 +289,7 @@ function configure() { if (!s3AccessKeyConfigValue || s3AccessKeyConfigValue.trim() === '') { if (!s3AccessKeyEnvValue || s3AccessKeyEnvValue.trim() === '') { - logger.warn('Failed to find s3 access key config. Disabling feature'); + logger.warn('Failed to find s3 access key config. Disabling feature. To enable feature set aws.spaces.key in config.json or the PN_ACT_CONFIG_S3_ACCESS_KEY environment variable'); disabledFeatures.s3 = true; } else { @@ -304,7 +304,7 @@ function configure() { if (!s3SecretKeyConfigValue || s3SecretKeyConfigValue.trim() === '') { if (!s3SecretKeyEnvValue || s3SecretKeyEnvValue.trim() === '') { - logger.warn('Failed to find s3 secret key config. Disabling feature'); + logger.warn('Failed to find s3 secret key config. Disabling feature. To enable feature set aws.spaces.secret in config.json or the PN_ACT_CONFIG_S3_ACCESS_SECRET environment variable'); disabledFeatures.s3 = true; } else { From 24fd641cc6f9d1039e6f52e4cfa1f704b0c3f085 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 15:39:26 -0400 Subject: [PATCH 091/105] Changed aws/spaces config to generic s3 config --- example.config.json | 9 ++++---- example.env | 1 + src/config-manager.js | 48 ++++++++++++++++++++++++++++--------------- src/util.js | 6 +++--- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/example.config.json b/example.config.json index bfa68f4..9c1f457 100644 --- a/example.config.json +++ b/example.config.json @@ -24,11 +24,10 @@ }, "from": "Company Name " }, - "aws": { - "spaces": { - "key": "ACCESS_KEY", - "secret": "ACCESS_SECRET" - } + "s3": { + "endpoint": "nyc3.digitaloceanspaces.com", + "key": "ACCESS_KEY", + "secret": "ACCESS_SECRET" }, "hcaptcha": { "secret": "0x0000000000000000000000000000000000000000" diff --git a/example.env b/example.env index a5c1007..57ff506 100644 --- a/example.env +++ b/example.env @@ -11,6 +11,7 @@ PN_ACT_CONFIG_EMAIL_SECURE=false PN_ACT_CONFIG_EMAIL_USERNAME=username PN_ACT_CONFIG_EMAIL_PASSWORD=password PN_ACT_CONFIG_EMAIL_FROM=Company Name +PN_ACT_CONFIG_S3_ENDPOINT=nyc3.digitaloceanspaces.com PN_ACT_CONFIG_S3_ACCESS_KEY=ACCESS_KEY PN_ACT_CONFIG_S3_ACCESS_SECRET=ACCESS_SECRET PN_ACT_CONFIG_HCAPTCHA_SECRET=0x0000000000000000000000000000000000000000 diff --git a/src/config-manager.js b/src/config-manager.js index 2237783..b1d7547 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -24,10 +24,10 @@ require('dotenv').config(); * @property {object} [email.auth] Email authentication settings * @property {string} [email.auth.user] Email username * @property {string} [email.auth.pass] Email password - * @property {object} [aws] s3 client settings - * @property {object} [aws.spaces] Digital Ocean Spaces settings - * @property {string} [aws.spaces.key] s3 access key - * @property {string} [aws.spaces.secret] s3 access secret + * @property {object} [s3] s3 client settings + * @property {object} [s3.endpoint] s3 endpoint URL + * @property {string} [s3.key] s3 access key + * @property {string} [s3.secret] s3 access secret * @property {object} [hcaptcha] hCaptcha settings * @property {string} [hcaptcha.secret] hCaptcha secret * @property {string} [cdn_subdomain] Subdomain used for serving CDN contents when s3 is disabled @@ -99,11 +99,10 @@ function configure() { }, from: process.env.PN_ACT_CONFIG_EMAIL_FROM }, - aws: { - spaces: { - key: process.env.PN_ACT_CONFIG_S3_ACCESS_KEY, - secret: process.env.PN_ACT_CONFIG_S3_ACCESS_SECRET - } + s3: { + endpoint: process.env.PN_ACT_CONFIG_S3_ENDPOINT, + key: process.env.PN_ACT_CONFIG_S3_ACCESS_KEY, + secret: process.env.PN_ACT_CONFIG_S3_ACCESS_SECRET }, hcaptcha: { secret: process.env.PN_ACT_CONFIG_HCAPTCHA_SECRET @@ -284,33 +283,48 @@ function configure() { } } - const s3AccessKeyConfigValue = get(config, 'aws.spaces.key'); + const s3EndpointConfigValue = get(config, 's3.endpoint'); + const s3EndpointEnvValue = get(process.env, 'PN_ACT_CONFIG_S3_ENDPOINT'); + + if (!s3EndpointConfigValue || s3EndpointConfigValue.trim() === '') { + if (!s3EndpointEnvValue || s3EndpointEnvValue.trim() === '') { + logger.warn('Failed to find s3 endpoint config. Disabling feature. To enable feature set s3.endpoint in config.json or the PN_ACT_CONFIG_S3_ENDPOINT environment variable'); + + disabledFeatures.s3 = true; + } else { + logger.info('s3.endpoint not found in config, using environment variable PN_ACT_CONFIG_S3_ENDPOINT'); + + set(config, 's3.endpoint', s3EndpointEnvValue); + } + } + + const s3AccessKeyConfigValue = get(config, 's3.key'); const s3AccessKeyEnvValue = get(process.env, 'PN_ACT_CONFIG_S3_ACCESS_KEY'); if (!s3AccessKeyConfigValue || s3AccessKeyConfigValue.trim() === '') { if (!s3AccessKeyEnvValue || s3AccessKeyEnvValue.trim() === '') { - logger.warn('Failed to find s3 access key config. Disabling feature. To enable feature set aws.spaces.key in config.json or the PN_ACT_CONFIG_S3_ACCESS_KEY environment variable'); + logger.warn('Failed to find s3 access key config. Disabling feature. To enable feature set s3.key in config.json or the PN_ACT_CONFIG_S3_ACCESS_KEY environment variable'); disabledFeatures.s3 = true; } else { - logger.info('aws.spaces.key not found in config, using environment variable PN_ACT_CONFIG_S3_ACCESS_KEY'); + logger.info('s3.key not found in config, using environment variable PN_ACT_CONFIG_S3_ACCESS_KEY'); - set(config, 'aws.spaces.key', s3AccessKeyEnvValue); + set(config, 's3.key', s3AccessKeyEnvValue); } } - const s3SecretKeyConfigValue = get(config, 'aws.spaces.secret'); + const s3SecretKeyConfigValue = get(config, 's3.secret'); const s3SecretKeyEnvValue = get(process.env, 'PN_ACT_CONFIG_S3_ACCESS_SECRET'); if (!s3SecretKeyConfigValue || s3SecretKeyConfigValue.trim() === '') { if (!s3SecretKeyEnvValue || s3SecretKeyEnvValue.trim() === '') { - logger.warn('Failed to find s3 secret key config. Disabling feature. To enable feature set aws.spaces.secret in config.json or the PN_ACT_CONFIG_S3_ACCESS_SECRET environment variable'); + logger.warn('Failed to find s3 secret key config. Disabling feature. To enable feature set s3.secret in config.json or the PN_ACT_CONFIG_S3_ACCESS_SECRET environment variable'); disabledFeatures.s3 = true; } else { - logger.info('aws.spaces.secret not found in config, using environment variable PN_ACT_CONFIG_S3_ACCESS_SECRET'); + logger.info('s3.secret not found in config, using environment variable PN_ACT_CONFIG_S3_ACCESS_SECRET'); - set(config, 'aws.spaces.secret', s3AccessKeyEnvValue); + set(config, 's3.secret', s3AccessKeyEnvValue); } } diff --git a/src/util.js b/src/util.js index 1f298d5..25b4ba6 100644 --- a/src/util.js +++ b/src/util.js @@ -11,9 +11,9 @@ let s3; if (!disabledFeatures.s3) { s3 = new aws.S3({ - endpoint: new aws.Endpoint('nyc3.digitaloceanspaces.com'), - accessKeyId: config.aws.spaces.key, - secretAccessKey: config.aws.spaces.secret + endpoint: new aws.Endpoint(config.s3.endpoint), + accessKeyId: config.s3.key, + secretAccessKey: config.s3.secret }); } From 646916b7a885c4fb422d8beebf02e49fba32a8ad Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 22:07:14 -0400 Subject: [PATCH 092/105] Add redis dump.rdb to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6ca20ff..ce5d611 100644 --- a/.gitignore +++ b/.gitignore @@ -63,4 +63,5 @@ t.js p.js config.json certs -/cdn \ No newline at end of file +/cdn +dump.rdb \ No newline at end of file From 434bcfdc56bacf4974ac2ec1b8fedab538cfc192 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 9 Oct 2022 22:08:33 -0400 Subject: [PATCH 093/105] Added high memory usage warning wen both s3 and redis are disabled --- src/config-manager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config-manager.js b/src/config-manager.js index b1d7547..cbd0e14 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -343,6 +343,10 @@ function configure() { } } + if (disabledFeatures.redis) { + logger.warn('Both s3 and Redis are disabled. Large CDN files will use the in-memory cache, which may result in high memory use. Please enable s3 if you\'re running a production server.'); + } + logger.warn(`s3 file storage disabled. Using disk-based file storage. Please ensure cdn_base config or PN_ACT_CONFIG_CDN_BASE env variable is set to point to this server with the subdomain being ${config.cdn_subdomain}`); } From 4cd1665c1718e7de0034adc87ed3b73fe4fef31f Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 14 Oct 2022 06:50:11 -0400 Subject: [PATCH 094/105] Removed redundant env checks --- src/config-manager.js | 221 ++++++++++++++++++------------------------ 1 file changed, 97 insertions(+), 124 deletions(-) diff --git a/src/config-manager.js b/src/config-manager.js index cbd0e14..f5c6b85 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -67,8 +67,10 @@ const requiredFields = [ ]; function configure() { - if (process.env.PN_ACT_PREFER_ENV_CONFIG === 'true') { - logger.info('Loading config from env'); + const usingEnv = process.env.PN_ACT_PREFER_ENV_CONFIG === 'true'; + + if (usingEnv) { + logger.info('Loading config from environment variable'); config = { http: { @@ -147,200 +149,171 @@ function configure() { // * Check for optional settings - const redisConfigValue = get(config, 'redis.client.url'); - const redisEnvValue = get(process.env, 'PN_ACT_CONFIG_REDIS_URL'); + const redisCheck = get(config, 'redis.client.url'); - if (!redisConfigValue || redisConfigValue.trim() === '') { - if (!redisEnvValue || redisEnvValue.trim() === '') { - logger.warn('Failed to find Redis config. Disabling feature and using in-memory cache. To enable feature set redis.client.url in config.json or the PN_ACT_CONFIG_REDIS_URL environment variable'); + if (!redisCheck || redisCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find Redis connection url. Disabling feature and using in-memory cache. To enable feature set the PN_ACT_CONFIG_REDIS_URL environment variable'); - disabledFeatures.redis = true; } else { - logger.info('redis.client.url not found in config, using environment variable PN_ACT_CONFIG_REDIS_URL'); + logger.warn('Failed to find Redis connection url. Disabling feature and using in-memory cache. To enable feature set redis.client.url in your config.json'); - set(config, 'redis.client.url', redisEnvValue); } - } - const emailHostConfigValue = get(config, 'email.host'); - const emailHostEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_HOST'); + disabledFeatures.redis = true; + } - if (!emailHostConfigValue || emailHostConfigValue.trim() === '') { - if (!emailHostEnvValue || emailHostEnvValue.trim() === '') { - logger.warn('Failed to find email SMTP host config. Disabling feature. To enable feature set email.host in config.json or the PN_ACT_CONFIG_EMAIL_HOST environment variable'); + const emailHostCheck = get(config, 'email.host'); - disabledFeatures.email = true; + if (!emailHostCheck || emailHostCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find email SMTP host. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_HOST environment variable'); } else { - logger.info('email.host not found in config, using environment variable PN_ACT_CONFIG_EMAIL_HOST'); - - set(config, 'email.host', emailHostEnvValue); + logger.warn('Failed to find email SMTP host. Disabling feature. To enable feature set email.host in your config.json'); } - } - const emailPortConfigValue = get(config, 'email.port'); - const emailPortEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_PORT'); - if (!emailPortConfigValue) { - if (!emailPortEnvValue || emailPortEnvValue.trim() === '') { - logger.warn('Failed to find email SMTP port config. Disabling feature. To enable feature set email.port in config.json or the PN_ACT_CONFIG_EMAIL_PORT environment variable'); + disabledFeatures.email = true; + } - disabledFeatures.email = true; - } else { - logger.info('email.port not found in config, using environment variable PN_ACT_CONFIG_EMAIL_PORT'); + const emailPortCheck = get(config, 'email.port'); - set(config, 'email.port', Number(emailPortEnvValue)); + if (!emailPortCheck) { + if (usingEnv) { + logger.warn('Failed to find email SMTP port. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_PORT environment variable'); + } else { + logger.warn('Failed to find email SMTP port. Disabling feature. To enable feature set email.port in your config.json'); } - } - const emailSecureConfigValue = get(config, 'email.secure'); - const emailSecureEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_SECURE'); + disabledFeatures.email = true; + } - if (emailSecureConfigValue === undefined) { - if (!emailSecureEnvValue || emailSecureEnvValue.trim() === '') { - logger.warn('Failed to find email SMTP secure config. Disabling feature. To enable feature set email.secure in config.json or the PN_ACT_CONFIG_EMAIL_SECURE environment variable'); + const emailSecureCheck = get(config, 'email.secure'); - disabledFeatures.email = true; + if (emailSecureCheck === undefined) { + if (usingEnv) { + logger.warn('Failed to find email SMTP secure flag. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_SECURE environment variable'); } else { - logger.info('email.secure not found in config, using environment variable PN_ACT_CONFIG_EMAIL_SECURE'); - set(config, 'email.secure', Boolean(emailSecureEnvValue)); + logger.warn('Failed to find email SMTP secure flag. Disabling feature. To enable feature set email.secure in your config.json'); } - } - const emailUsernameConfigValue = get(config, 'email.auth.user'); - const emailUsernameEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_USERNAME'); + disabledFeatures.email = true; + } - if (!emailUsernameConfigValue || emailUsernameConfigValue.trim() === '') { - if (!emailUsernameEnvValue || emailUsernameEnvValue.trim() === '') { - logger.warn('Failed to find email username config. Disabling feature. To enable feature set email.auth.user in config.json or the auth.user environment variable'); + const emailUsernameCheck = get(config, 'email.auth.user'); - disabledFeatures.email = true; + if (!emailUsernameCheck || emailUsernameCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find email account username. Disabling feature. To enable feature set the auth.user environment variable'); } else { - logger.info('email.auth.user not found in config, using environment variable PN_ACT_CONFIG_EMAIL_USERNAME'); - set(config, 'email.auth.user', emailUsernameEnvValue); + logger.warn('Failed to find email account username. Disabling feature. To enable feature set email.auth.user in your config.json'); } - } - const emailPasswordConfigValue = get(config, 'email.auth.pass'); - const emailPasswordEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_PASSWORD'); + disabledFeatures.email = true; + } - if (!emailPasswordConfigValue || emailPasswordConfigValue.trim() === '') { - if (!emailPasswordEnvValue || emailPasswordEnvValue.trim() === '') { - logger.warn('Failed to find email password config. Disabling feature. To enable feature set email.auth.pass in config.json or the PN_ACT_CONFIG_EMAIL_PASSWORD environment variable'); + const emailPasswordCheck = get(config, 'email.auth.pass'); - disabledFeatures.email = true; + if (!emailPasswordCheck || emailPasswordCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find email account password. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_PASSWORD environment variable'); } else { - logger.info('email.pass not found in config, using environment variable PN_ACT_CONFIG_EMAIL_PASSWORD'); - set(config, 'email.pass', emailPasswordEnvValue); + logger.warn('Failed to find email account password. Disabling feature. To enable feature set email.auth.pass in your config.json'); } - } - const emailFromConfigValue = get(config, 'email.from'); - const emailFromEnvValue = get(process.env, 'PN_ACT_CONFIG_EMAIL_FROM'); + disabledFeatures.email = true; + } - if (!emailFromConfigValue || emailFromConfigValue.trim() === '') { - if (!emailFromEnvValue || emailFromEnvValue.trim() === '') { - logger.warn('Failed to find email from config. Disabling feature. To enable feature set email.from in config.json or the PN_ACT_CONFIG_EMAIL_FROM environment variable'); + const emailFromCheck = get(config, 'email.from'); - disabledFeatures.email = true; + if (!emailFromCheck || emailFromCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find email from config. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_FROM environment variable'); } else { - logger.info('email.from not found in config, using environment variable PN_ACT_CONFIG_EMAIL_FROM'); - set(config, 'email.from', emailFromEnvValue); + logger.warn('Failed to find email from config. Disabling feature. To enable feature set email.from in your config.json'); } + + disabledFeatures.email = true; } if (!disabledFeatures.email) { - const websiteBaseConfigValue = get(config, 'website_base'); - const websiteBaseEnvValue = get(process.env, 'PN_ACT_CONFIG_WEBSITE_BASE'); + const websiteBaseCheck = get(config, 'website_base'); - if (!websiteBaseConfigValue || websiteBaseConfigValue.trim() === '') { - if (!websiteBaseEnvValue || websiteBaseEnvValue.trim() === '') { - logger.error('Email sending is not disabled and no website base was set. Set website_base in config.json or the PN_ACT_CONFIG_WEBSITE_BASE environment variable'); - process.exit(0); + if (!websiteBaseCheck || websiteBaseCheck.trim() === '') { + if (usingEnv) { + logger.error('Email sending is enabled and no website base was configured. Set the PN_ACT_CONFIG_WEBSITE_BASE environment variable'); } else { - logger.info('website_base not found in config, using environment variable PN_ACT_CONFIG_WEBSITE_BASE'); - - set(config, 'website_base', websiteBaseEnvValue); + logger.error('Email sending is enabled and no website base was configured. Set website_base in your config.json'); } + + process.exit(0); } } - const captchaSecretConfigValue = get(config, 'hcaptcha.secret'); - const captchaSecretEnvValue = get(process.env, 'PN_ACT_CONFIG_HCAPTCHA_SECRET'); - - if (!captchaSecretConfigValue || captchaSecretConfigValue.trim() === '') { - if (!captchaSecretEnvValue || captchaSecretEnvValue.trim() === '') { - logger.warn('Failed to find captcha secret config. Disabling feature. To enable feature set hcaptcha.secret in config.json or the PN_ACT_CONFIG_HCAPTCHA_SECRET environment variable'); + const captchaSecretCheck = get(config, 'hcaptcha.secret'); - disabledFeatures.email = true; + if (!captchaSecretCheck || captchaSecretCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find captcha secret config. Disabling feature. To enable feature set the PN_ACT_CONFIG_HCAPTCHA_SECRET environment variable'); } else { - logger.info('hcaptcha.secret not found in config, using environment variable PN_ACT_CONFIG_HCAPTCHA_SECRET'); - - set(config, 'hcaptcha.secret', captchaSecretEnvValue); + logger.warn('Failed to find captcha secret config. Disabling feature. To enable feature set hcaptcha.secret in your config.json'); } - } - const s3EndpointConfigValue = get(config, 's3.endpoint'); - const s3EndpointEnvValue = get(process.env, 'PN_ACT_CONFIG_S3_ENDPOINT'); + disabledFeatures.captcha = true; + } - if (!s3EndpointConfigValue || s3EndpointConfigValue.trim() === '') { - if (!s3EndpointEnvValue || s3EndpointEnvValue.trim() === '') { - logger.warn('Failed to find s3 endpoint config. Disabling feature. To enable feature set s3.endpoint in config.json or the PN_ACT_CONFIG_S3_ENDPOINT environment variable'); + const s3EndpointCheck = get(config, 's3.endpoint'); - disabledFeatures.s3 = true; + if (!s3EndpointCheck || s3EndpointCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find s3 endpoint config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ENDPOINT environment variable'); } else { - logger.info('s3.endpoint not found in config, using environment variable PN_ACT_CONFIG_S3_ENDPOINT'); - - set(config, 's3.endpoint', s3EndpointEnvValue); + logger.warn('Failed to find s3 endpoint config. Disabling feature. To enable feature set s3.endpoint in your config.json'); } - } - const s3AccessKeyConfigValue = get(config, 's3.key'); - const s3AccessKeyEnvValue = get(process.env, 'PN_ACT_CONFIG_S3_ACCESS_KEY'); + disabledFeatures.s3 = true; + } else { + } - if (!s3AccessKeyConfigValue || s3AccessKeyConfigValue.trim() === '') { - if (!s3AccessKeyEnvValue || s3AccessKeyEnvValue.trim() === '') { - logger.warn('Failed to find s3 access key config. Disabling feature. To enable feature set s3.key in config.json or the PN_ACT_CONFIG_S3_ACCESS_KEY environment variable'); + const s3AccessKeyCheck = get(config, 's3.key'); - disabledFeatures.s3 = true; + if (!s3AccessKeyCheck || s3AccessKeyCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find s3 access key config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ACCESS_KEY environment variable'); } else { - logger.info('s3.key not found in config, using environment variable PN_ACT_CONFIG_S3_ACCESS_KEY'); - - set(config, 's3.key', s3AccessKeyEnvValue); + logger.warn('Failed to find s3 access key config. Disabling feature. To enable feature set s3.key in your config.json'); } - } - const s3SecretKeyConfigValue = get(config, 's3.secret'); - const s3SecretKeyEnvValue = get(process.env, 'PN_ACT_CONFIG_S3_ACCESS_SECRET'); + disabledFeatures.s3 = true; + } - if (!s3SecretKeyConfigValue || s3SecretKeyConfigValue.trim() === '') { - if (!s3SecretKeyEnvValue || s3SecretKeyEnvValue.trim() === '') { - logger.warn('Failed to find s3 secret key config. Disabling feature. To enable feature set s3.secret in config.json or the PN_ACT_CONFIG_S3_ACCESS_SECRET environment variable'); + const s3SecretKeyCheck = get(config, 's3.secret'); - disabledFeatures.s3 = true; + if (!s3SecretKeyCheck || s3SecretKeyCheck.trim() === '') { + if (usingEnv) { + logger.warn('Failed to find s3 secret key config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ACCESS_SECRET environment variable'); } else { - logger.info('s3.secret not found in config, using environment variable PN_ACT_CONFIG_S3_ACCESS_SECRET'); - - set(config, 's3.secret', s3AccessKeyEnvValue); + logger.warn('Failed to find s3 secret key config. Disabling feature. To enable feature set s3.secret in your config.json'); } + + disabledFeatures.s3 = true; } if (disabledFeatures.s3) { - const cdnSubdomainConfigValue = get(config, 'cdn_subdomain'); - const cdnSubdomainEnvValue = get(process.env, 'PN_ACT_CONFIG_CDN_SUBDOMAIN'); + const cdnSubdomainCheck = get(config, 'cdn_subdomain'); - if (!cdnSubdomainConfigValue || cdnSubdomainConfigValue.trim() === '') { - if (!cdnSubdomainEnvValue || cdnSubdomainEnvValue.trim() === '') { - logger.error('s3 file storage is disabled and no CDN subdomain was set. Set cdn_subdomain in config.json or the PN_ACT_CONFIG_CDN_SUBDOMAIN environment variable'); - process.exit(0); + if (!cdnSubdomainCheck || cdnSubdomainCheck.trim() === '') { + if (usingEnv) { + logger.error('s3 file storage is disabled and no CDN subdomain was set. Set the PN_ACT_CONFIG_CDN_SUBDOMAIN environment variable'); } else { - logger.info('cdn_subdomain not found in config, using environment variable PN_ACT_CONFIG_CDN_SUBDOMAIN'); - - set(config, 'cdn_subdomain', cdnSubdomainEnvValue); + logger.error('s3 file storage is disabled and no CDN subdomain was set. Set cdn_subdomain in your config.json'); } + + process.exit(0); } if (disabledFeatures.redis) { From 20da652b38428d94d1e8965cf591f3ff199cbcb0 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 14 Oct 2022 07:03:46 -0400 Subject: [PATCH 095/105] Made CDN disk path configurable, updated CDN config, updated examples --- example.config.json | 6 +++++- example.env | 3 ++- src/config-manager.js | 20 ++++++++++++------- src/database.js | 4 ++-- src/services/api/routes/v1/user.js | 4 ++-- src/services/local-cdn/index.js | 4 ++-- src/services/nnid/routes/miis.js | 32 +++++++++++++++--------------- src/util.js | 2 +- 8 files changed, 43 insertions(+), 32 deletions(-) diff --git a/example.config.json b/example.config.json index 9c1f457..b8a86b5 100644 --- a/example.config.json +++ b/example.config.json @@ -32,6 +32,10 @@ "hcaptcha": { "secret": "0x0000000000000000000000000000000000000000" }, - "cdn_base": "https://example.com", + "cdn": { + "base_url": "https://local-cdn.example.com", + "subdomain": "local-cdn", + "disk_path": "/home/jon/pretend-cdn" + }, "website_base": "https://example.com" } \ No newline at end of file diff --git a/example.env b/example.env index 57ff506..84a692a 100644 --- a/example.env +++ b/example.env @@ -15,6 +15,7 @@ PN_ACT_CONFIG_S3_ENDPOINT=nyc3.digitaloceanspaces.com PN_ACT_CONFIG_S3_ACCESS_KEY=ACCESS_KEY PN_ACT_CONFIG_S3_ACCESS_SECRET=ACCESS_SECRET PN_ACT_CONFIG_HCAPTCHA_SECRET=0x0000000000000000000000000000000000000000 -PN_ACT_CONFIG_CDN_BASE=https://local-cdn.example.com +PN_ACT_CONFIG_CDN_BASE_URL=https://local-cdn.example.com PN_ACT_CONFIG_CDN_SUBDOMAIN=local-cdn +PN_ACT_CONFIG_CDN_DISK_PATH=/home/jon/pretend-cdn PN_ACT_CONFIG_WEBSITE_BASE=https://example.com \ No newline at end of file diff --git a/src/config-manager.js b/src/config-manager.js index f5c6b85..3cc79e8 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -30,8 +30,10 @@ require('dotenv').config(); * @property {string} [s3.secret] s3 access secret * @property {object} [hcaptcha] hCaptcha settings * @property {string} [hcaptcha.secret] hCaptcha secret - * @property {string} [cdn_subdomain] Subdomain used for serving CDN contents when s3 is disabled - * @property {string} cdn_base Base URL for CDN location + * @property {object} cdn CDN config settings + * @property {object} [cdn.subdomain] Subdomain used for serving CDN contents when s3 is disabled + * @property {string} [cdn.disk_path] Fully qualified file system path for storing and reading local CDN contents + * @property {string} cdn.base_url Base URL for CDN server * @property {string} website_base Base URL for service website (used with emails) */ @@ -63,7 +65,7 @@ const requiredFields = [ ['http.port', 'PN_ACT_CONFIG_HTTP_PORT', Number], ['mongoose.uri', 'PN_ACT_CONFIG_MONGO_URI'], ['mongoose.database', 'PN_ACT_CONFIG_MONGO_DB_NAME'], - ['cdn_base', 'PN_ACT_CONFIG_CDN_BASE'] + ['cdn.base_url', 'PN_ACT_CONFIG_CDN_BASE_URL'] ]; function configure() { @@ -109,7 +111,11 @@ function configure() { hcaptcha: { secret: process.env.PN_ACT_CONFIG_HCAPTCHA_SECRET }, - cdn_base: process.env.PN_ACT_CONFIG_CDN_BASE, + cdn: { + subdomain: process.env.PN_ACT_CONFIG_CDN_BASE, + disk_path: process.env.PN_ACT_CONFIG_CDN_BASE, + base_url: process.env.PN_ACT_CONFIG_CDN_BASE + }, website_base: process.env.PN_ACT_CONFIG_WEBSITE_BASE }; } else { @@ -304,13 +310,13 @@ function configure() { } if (disabledFeatures.s3) { - const cdnSubdomainCheck = get(config, 'cdn_subdomain'); + const cdnSubdomainCheck = get(config, 'cdn.subdomain'); if (!cdnSubdomainCheck || cdnSubdomainCheck.trim() === '') { if (usingEnv) { logger.error('s3 file storage is disabled and no CDN subdomain was set. Set the PN_ACT_CONFIG_CDN_SUBDOMAIN environment variable'); } else { - logger.error('s3 file storage is disabled and no CDN subdomain was set. Set cdn_subdomain in your config.json'); + logger.error('s3 file storage is disabled and no CDN subdomain was set. Set cdn.subdomain in your config.json'); } process.exit(0); @@ -320,7 +326,7 @@ function configure() { logger.warn('Both s3 and Redis are disabled. Large CDN files will use the in-memory cache, which may result in high memory use. Please enable s3 if you\'re running a production server.'); } - logger.warn(`s3 file storage disabled. Using disk-based file storage. Please ensure cdn_base config or PN_ACT_CONFIG_CDN_BASE env variable is set to point to this server with the subdomain being ${config.cdn_subdomain}`); + logger.warn(`s3 file storage disabled. Using disk-based file storage. Please ensure cdn.base_url config or PN_ACT_CONFIG_CDN_BASE env variable is set to point to this server with the subdomain being ${config.cdn.subdomain}`); } module.exports.config = config; diff --git a/src/database.js b/src/database.js index fcb136e..860e05c 100644 --- a/src/database.js +++ b/src/database.js @@ -172,9 +172,9 @@ async function getUserProfileJSONByPID(pid) { mii_image: { // Images MUST be loaded over HTTPS or console ignores them // Bunny CDN is the only CDN which seems to support TLS 1.0/1.1 (required) - cached_url: `${config.cdn_base}/mii/${user.pid}/standard.tga`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/standard.tga`, id: user.get('mii.image_id'), - url: `${config.cdn_base}/mii/${user.pid}/standard.tga`, + url: `${config.cdn.base_url}/mii/${user.pid}/standard.tga`, type: 'standard' } }, diff --git a/src/services/api/routes/v1/user.js b/src/services/api/routes/v1/user.js index ee8ad4a..7008548 100644 --- a/src/services/api/routes/v1/user.js +++ b/src/services/api/routes/v1/user.js @@ -47,7 +47,7 @@ router.get('/', async (request, response) => { mii: { data: pnid.get('mii.data'), name: pnid.get('mii.name'), - image_url: `${config.cdn_base}/mii/${pnid.get('pid')}/normal_face.png` + image_url: `${config.cdn.base_url}/mii/${pnid.get('pid')}/normal_face.png` }, flags: { marketing: pnid.get('flags.marketing') @@ -111,7 +111,7 @@ router.post('/', async (request, response) => { mii: { data: pnid.get('mii.data'), name: pnid.get('mii.name'), - image_url: `${config.cdn_base}/mii/${pnid.get('pid')}/normal_face.png` + image_url: `${config.cdn.base_url}/mii/${pnid.get('pid')}/normal_face.png` }, flags: { marketing: pnid.get('flags.marketing') diff --git a/src/services/local-cdn/index.js b/src/services/local-cdn/index.js index 1a0a9dc..b0e3985 100644 --- a/src/services/local-cdn/index.js +++ b/src/services/local-cdn/index.js @@ -24,7 +24,7 @@ localcdn.use(routes.GET); const router = express.Router(); // Create subdomains -logger.info(`[LOCAL-CDN] Creating '${config.cdn_subdomain}' subdomain`); -router.use(subdomain(config.cdn_subdomain, localcdn)); +logger.info(`[LOCAL-CDN] Creating '${config.cdn.subdomain}' subdomain`); +router.use(subdomain(config.cdn.subdomain, localcdn)); module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/miis.js b/src/services/nnid/routes/miis.js index 82ff0d6..3c5603c 100644 --- a/src/services/nnid/routes/miis.js +++ b/src/services/nnid/routes/miis.js @@ -20,51 +20,51 @@ router.get('/', async (request, response) => { const miiImages = [ { - cached_url: `${config.cdn_base}/mii/${user.pid}/normal_face.png`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/normal_face.png`, id: mii.id, - url: `${config.cdn_base}/mii/${user.pid}/normal_face.png`, + url: `${config.cdn.base_url}/mii/${user.pid}/normal_face.png`, type: 'standard' }, { - cached_url: `${config.cdn_base}/mii/${user.pid}/frustrated.png`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/frustrated.png`, id: mii.id, - url: `${config.cdn_base}/mii/${user.pid}/frustrated.png`, + url: `${config.cdn.base_url}/mii/${user.pid}/frustrated.png`, type: 'frustrated_face' }, { - cached_url: `${config.cdn_base}/mii/${user.pid}/smile_open_mouth.png`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/smile_open_mouth.png`, id: mii.id, - url: `${config.cdn_base}/mii/${user.pid}/smile_open_mouth.png`, + url: `${config.cdn.base_url}/mii/${user.pid}/smile_open_mouth.png`, type: 'happy_face' }, { - cached_url: `${config.cdn_base}/mii/${user.pid}/wink_left.png`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/wink_left.png`, id: mii.id, - url: `${config.cdn_base}/mii/${user.pid}/wink_left.png`, + url: `${config.cdn.base_url}/mii/${user.pid}/wink_left.png`, type: 'like_face' }, { - cached_url: `${config.cdn_base}/mii/${user.pid}/normal_face.png`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/normal_face.png`, id: mii.id, - url: `${config.cdn_base}/mii/${user.pid}/normal_face.png`, + url: `${config.cdn.base_url}/mii/${user.pid}/normal_face.png`, type: 'normal_face' }, { - cached_url: `${config.cdn_base}/mii/${user.pid}/sorrow.png`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/sorrow.png`, id: mii.id, - url: `${config.cdn_base}/mii/${user.pid}/sorrow.png`, + url: `${config.cdn.base_url}/mii/${user.pid}/sorrow.png`, type: 'puzzled_face' }, { - cached_url: `${config.cdn_base}/mii/${user.pid}/surprised_open_mouth.png`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/surprised_open_mouth.png`, id: mii.id, - url: `${config.cdn_base}/mii/${user.pid}/surprised_open_mouth.png`, + url: `${config.cdn.base_url}/mii/${user.pid}/surprised_open_mouth.png`, type: 'surprised_face' }, { - cached_url: `${config.cdn_base}/mii/${user.pid}/body.png`, + cached_url: `${config.cdn.base_url}/mii/${user.pid}/body.png`, id: mii.id, - url: `${config.cdn_base}/mii/${user.pid}/body.png`, + url: `${config.cdn.base_url}/mii/${user.pid}/body.png`, type: 'whole_body' } ]; diff --git a/src/util.js b/src/util.js index 25b4ba6..5550a70 100644 --- a/src/util.js +++ b/src/util.js @@ -229,7 +229,7 @@ async function uploadCDNAsset(bucket, key, data, acl) { } async function writeLocalCDNFile(key, data) { - const filePath = `${__dirname}/../cdn/${key}`; + const filePath = config.cdn.disk_path; const folder = path.dirname(filePath); await fs.ensureDir(folder); From 0cebd41f5c06da5b6112fc4f0b5273b1b6c76ba5 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Thu, 20 Oct 2022 20:29:23 -0400 Subject: [PATCH 096/105] Removed mongoose.uri and mongoose.database options for single mongoose.connection_string --- example.config.json | 3 +-- example.env | 3 +-- src/config-manager.js | 10 +++------- src/database.js | 4 ++-- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/example.config.json b/example.config.json index b8a86b5..33f7b24 100644 --- a/example.config.json +++ b/example.config.json @@ -3,8 +3,7 @@ "port": 7070 }, "mongoose": { - "uri": "mongodb://localhost:27017", - "database": "database_name", + "connection_string": "mongodb://localhost:27017/database_name", "options": { "useNewUrlParser": true } diff --git a/example.env b/example.env index 84a692a..360615f 100644 --- a/example.env +++ b/example.env @@ -1,7 +1,6 @@ PN_ACT_PREFER_ENV_CONFIG=true # Load config from ENV instead of config.json PN_ACT_CONFIG_HTTP_PORT=7070 -PN_ACT_CONFIG_MONGO_URI=mongodb://localhost:27017 -PN_ACT_CONFIG_MONGO_DB_NAME=database_name +PN_ACT_CONFIG_MONGO_CONNECTION_STRING=mongodb://localhost:27017/database_name PN_ACT_CONFIG_MONGOOSE_OPTION_useNewUrlParser=true PN_ACT_CONFIG_MONGOOSE_OPTION_useUnifiedTopology=true PN_ACT_CONFIG_REDIS_URL=redis://localhost:6379 diff --git a/src/config-manager.js b/src/config-manager.js index 3cc79e8..c141b8a 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -10,8 +10,7 @@ require('dotenv').config(); * @property {object} http HTTP server settings * @property {number} http.port HTTP port the server will listen on * @property {object} mongoose Mongose connection settings - * @property {string} mongoose.uri URI Mongoose will connect to - * @property {string} mongoose.database MongoDB database name + * @property {string} mongoose.connection_string MongoDB connection string * @property {object} mongoose.options MongoDB connection options * @property {object} [redis] redis settings * @property {string} [redis.client] redis client settings @@ -42,7 +41,6 @@ require('dotenv').config(); */ let config = {}; - /** * @typedef {Object} DisabledFeatures * @property {boolean} redis true if redis is disabled @@ -63,8 +61,7 @@ const disabledFeatures = { const requiredFields = [ ['http.port', 'PN_ACT_CONFIG_HTTP_PORT', Number], - ['mongoose.uri', 'PN_ACT_CONFIG_MONGO_URI'], - ['mongoose.database', 'PN_ACT_CONFIG_MONGO_DB_NAME'], + ['mongoose.connection_string', 'PN_ACT_CONFIG_MONGO_CONNECTION_STRING'], ['cdn.base_url', 'PN_ACT_CONFIG_CDN_BASE_URL'] ]; @@ -79,8 +76,7 @@ function configure() { port: Number(process.env.PN_ACT_CONFIG_HTTP_PORT) }, mongoose: { - uri: process.env.PN_ACT_CONFIG_MONGO_URI, - database: process.env.PN_ACT_CONFIG_MONGO_DB_NAME, + connection_string: process.env.PN_ACT_CONFIG_MONGO_CONNECTION_STRING, options: Object.keys(process.env) .filter(key => key.startsWith('PN_ACT_CONFIG_MONGOOSE_OPTION_')) .reduce((obj, key) => { diff --git a/src/database.js b/src/database.js index 860e05c..7df830e 100644 --- a/src/database.js +++ b/src/database.js @@ -6,7 +6,7 @@ const { PNID } = require('./models/pnid'); const { Server } = require('./models/server'); const logger = require('../logger'); const { config } = require('./config-manager'); -const { uri, database, options } = config.mongoose; +const { connection_string, options } = config.mongoose; // TODO: Extend this later with more settings const discordConnectionSchema = joi.object({ @@ -16,7 +16,7 @@ const discordConnectionSchema = joi.object({ let connection; async function connect() { - await mongoose.connect(`${uri}/${database}?replicaSet=rs0`, options); + await mongoose.connect(connection_string, options); connection = mongoose.connection; connection.on('error', console.error.bind(console, 'connection error:')); From 4a66567aa01a1ffaeff1b7d0e9e857ff07b240cf Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Sat, 22 Oct 2022 20:25:30 +0200 Subject: [PATCH 097/105] feat: add assets subdomain, add email assets --- .../emails/emailConfirmationTemplate.html | 203 ++++++++++++++++++ src/assets/emails/genericTemplate.html | 169 +++++++++++++++ ...tendo-wordmark-multicolor-purple+white.png | Bin 0 -> 5299 bytes .../pretendo-wordmark-singlecolor-purple.png | Bin 0 -> 5842 bytes src/server.js | 2 + src/services/assets/index.js | 22 ++ 6 files changed, 396 insertions(+) create mode 100644 src/assets/emails/emailConfirmationTemplate.html create mode 100644 src/assets/emails/genericTemplate.html create mode 100644 src/assets/images/pretendo-wordmark-multicolor-purple+white.png create mode 100644 src/assets/images/pretendo-wordmark-singlecolor-purple.png create mode 100644 src/services/assets/index.js diff --git a/src/assets/emails/emailConfirmationTemplate.html b/src/assets/emails/emailConfirmationTemplate.html new file mode 100644 index 0000000..4c459b9 --- /dev/null +++ b/src/assets/emails/emailConfirmationTemplate.html @@ -0,0 +1,203 @@ + + + + + + + + +
Hello {{username}}! Your Pretendo Network ID activation is almost complete. Please click the link in this email to confirm your e-mail address and complete the activation process.
+ + + + +
+ + + + +
+ + + + + + +
  + + + + + + + +
 
+ + + + + + + + + + + + + + + + + + + +
+ + + +
 
+ + + + + + +
  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ Hello {{username}}! +
 
+ Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process. +
 
 
+ You may also enter the following 6-digit code on your console: +
 
+ {{confirmation-code}} +
 
+ We hope you have fun using our services! +
 
+ The Pretendo Network team +
 
+
 
+
 
+ Note: this email message was auto-generated, please do not respond. For further assistance, please join our Discord server. +
 
+
+
 
+
+
+ + \ No newline at end of file diff --git a/src/assets/emails/genericTemplate.html b/src/assets/emails/genericTemplate.html new file mode 100644 index 0000000..1dd0110 --- /dev/null +++ b/src/assets/emails/genericTemplate.html @@ -0,0 +1,169 @@ + + + + + + + + +
{{preview}}
+ + + + +
+ + + + +
+ + + + + + +
  + + + + + + + +
 
+ + + + + + + + + + + + + + + + + + + +
+ + + +
 
+ + + + + + +
  + + + + + + + + + + + + + + + + + + + + + + +
 
+ Dear {{username}}, +
 
+ {{paragraph}} +
 
+ The Pretendo Network team +
 
+
 
+
 
+ Note: this email message was auto-generated, please do not respond. For further assistance, please join our Discord server. +
 
+
+
 
+
+
+ + \ No newline at end of file diff --git a/src/assets/images/pretendo-wordmark-multicolor-purple+white.png b/src/assets/images/pretendo-wordmark-multicolor-purple+white.png new file mode 100644 index 0000000000000000000000000000000000000000..66c89d53644bb1e7276065b57d3de48f26084364 GIT binary patch literal 5299 zcmbW5WmMEp)W?5I2uLU_EZqvIfPhG|)Y6?UpyUEeODruVNJ_4R)Y9D{(%}MvbcZ6{ zAt@m|{NFs!`)AIXJ9p-M&z*TO_nvb<5n39Gr1$CW0{}p(tOU~m01)!d_aeM^XBT0} z%e#f>t&*V|0I-VuH$n1A{APEDAU7RFS)gKwVe4*#XCtF70|3>r#MkEd06?jv43p9G z0_|luyUr^l_V`MRH8VRXLS=q~;n1M$|4fmHha@S|S z2Fog5PPyLRmBJ(I!U!4I=p*aHWZdlw{Z6zpz!2E+;$!AM6WiUT|2Hs9c=hQkH`pnv z_(j&a7|Y>v*ap47Y23*xM|NeHPQT{%u-g$wKo4wmVCnq}8~_MIW=P*Iv=hP>-aW#@ zSF!st$@*81d>au`ohOAxhN+wkw=qM*2?1a#H~;`i$cgX6(GLsaY$i}aTI6~1W1#Lu#fZ-WCesPpA=Ijym@H(l2F9=O-)x4oy0=Pm~;6V z6_GM7d=dyOagoI=o=TmgU-~$-ha$+K>@P8#65c|O4|d7k$b0*JlRCQ{J{bFUu5>8? zncr5Ep!klllo@yf%S7h}cqf7hUjmr>=?^zeP2SNFE$vxVK4yP{_1%i6t4f;?GCSA3 zt=uES&I=Ss6Z#}9&S`MlH9`Tv%0&)ymE{>q+5YY#q6VEWVy^Aa-$Fe`XV!UUF$-c;Rpv2NLpFFSR4ePg%RJ!5pt$wK3ufxpJMO>BD#Ulz1WHhqx;0BQO-j1JHevACS}S zll@6-_6#FqyFVyE5C{~~!UX8y_=F*i8D}8FM}r406AIjg0R=l=CJcYnep#*4)BpSB0N{XAPL0f5Yo_K+ zr1-l?jc-z)8)h^H00p0L26MQVc@+(-(z1_?7#?ByV&Q2P8Qxj4Y95gC(=-E-WcVqW zDak=sD+ov#eHvtKzTdZ>w!ZB$V?`ohog79ZDb>{6ZZXf3ylsLDEMTZ`ezx#Ex8R&m zQUU>b5m(p*#D@CCY+Gq32M>Mq&|N0JHNec;ovmi9T%U?;_ehAV7?imsmEr=xx~&?f zQZ?-Uq7(5fyC-d_OsBs=9lj0A)2OTN<*W3P8^#1}0DuUxjnvu}Ba*TGonzTp{;v{A zp}$$9$pEt`MbeRYPZ4{k+;6E7_@ptWZz`gL?h;N|YloqKR?vu2g*8hi9RxH?ILUCf zt?m=dnQ4vF0$K$1#v@E9zqz++NrHFPH=CTg*D+B3@@GJREGa1QCh63T6j1PlcQV7909#M?FcXBjHw;gHqehADz_?saxeHRe~g`88Ul z@Akv*hkSZ=;L;=v0$%^-e>}-o3)w*C<1=#ZM}sCi{B`hbdnI%uX{XDOR`OM)-wR!@ zvmv~Ar`m=LPN{?Y<@KQL?CsX>GK|R7P@}@%fX;Apeo4MCG_0edpEc<5^fEH^xIWlGf zsgtfN!9V*PEY1`1#glkB=Ux4E1&mHv4A4`u$Gf!SKo53TPcS@@#m+_+W~evh=r)2c z0ad!dZDgo)t-WQ&IIQ}?S3N}7hGh0UD9XK@{{UFvFk%@I_&kDu*;|*05j~A=A%(cB zV9GWnaR77yzBYr&-+zbxF#8YXo2CzVyMtduIsf}>N_}&FyK{}GPN%zdz}m!4bWL9R z35@FwP{%W>G!lH+8%mZBDcZwPNg!#{9$>c102$`I;nke%x^c;>n3tMT&90KEH-%Df z&2+Ixsb})K-L8s4{b9fkK}_SI%Q6up)Yu1ZYy@QR8Fb>K@7(nz8h%(sw5(LN^OymNnAO1F{er1Jd;d zqVG_L!@#3Z?)|YNwFZzOMm}O#KCb$+)cG5^deW!~J{y`x&h|bybj4O>p{c{&em3~08Q7DH zCLSp*jg!-k`88337A9uTHL&er^|5Ha>vYPb^KzZEs;IBv+YfnSCe?A`n(l4cgPjHE z0n+#*2DDOS_t4ST;&jMn<4UIVKrjxEvO|LOJd7t@*KI=7zC}~70%-ucr*}i{L&b|NsjSPX z_j=F=qO%+LBOqs%Ypn-5&3$e_U%IYo2S_ID8<)}P=)78My^(UZq!;V+AI}X92Rz#I zZ#U=%PH33oL+zD}b%dP4!zo_jHZSzJIl`lT4DUT~#iu0~_YUV0{SvS(l(*z8wCl3D zmVjiomcF1FN2O$IPI|n>tqHJGnkV0K#2MK0Q>nmqUZ-ggyDNH`g5L&zg}+ME{#(>3 zqDQ}T_Ex#Y1ttNGMRU*WYVbv)QjCu_#XS8kMi4>;mJp@Gt_~E7g#X!=h5W zv3=Y}R;o)!o^CYrTgwDuNuMjhi&e38x{kA#zN&VYrY@+;a@Np_zv{KKO{#WIR+G=AUrKbu1R-6% zb0g14SL-%1^N>k-4t^w&P|lXKTHQ>NZDe8$Ujn7_bBO&R9pWYFZwqQXo~yX{&Qb-p zk@iT3?;d=hSv5nr#vXdth!p;)`4b)Z1BP~|u#^*b5G&<&=rN9-eo9YN!l=o$;k@iY z8Ac)JN@B>jsyI@fs&1(z;2XvBjZu|VFjQmBr5*;^!P9##G(F{8!(In3ECRXPeKk?S zR((A1 zg&$cS`>qapG?1T65xR^0DFG9XRx=vj1oNtIpS-C^j5lI3R^UpRnQ+4^$qzrIenM}~ zKH@!ZaeOk$6tsSnDRuVT&*;U$WtOiV-y37DCFN}|2R!n}(7rY!CNA@edJ7tWYDtAB z{q-JFKBqsRkN1ke6PclOFj&^iRr4gG0sev9Dr>_fqIU|#R}h?<^{nX1v(DBYHc1|z zmKPyhdPp2X2ytPa-Ic05+^Fd{W*u>mziWU<8j;ZQpp{q2&dU_o7z@?`vhA7p{13#eX5qPcwhfo`;phfos%juAkG}wBt#)3=41IY1TEQ29OV{Evc`{6$Wd?Ec`~Vr ztk#Gn`To@C8?J!XXonMHl~O7UC3K$uq)a!7%RLXA(#R8Ju5UTl;uNM{=*sR_rH@Sz z;l2FXY1%s+yT2asiRW9o$dz7jJ61oN#oJ6?$vR+-9_5x^;rbIvJYR6{C1*IA9H~)4 zYgLY^Jz$eFCOi3qFr0t=z6()4xa|>_cIe$ue9@J!%Uq^HIhy1++yCymncxGevDPbh z&ZRMj5jsnK!8~|d_>woq9&s@Je&7MBNxX!@1~u@pjaf`e+rfVHJ&fZPYRbvHnvk=3 z)Wp@MX>vj%uwS5yHZ4DTym*l1$hJv&4h&)D7ktYKWT=zUgXZM|gMAE5S$oy{s^UymoS z{Y2^@GOsmXJg^rJ%Iz_Yy2(`b039IVNksTs3 zsd;Ls^`gU$r&@m{7r)iL&rGm5LjE&-X%4UQ*2|DGr0yB-$%qHv?6UAi6VsJy!;W@0 zs#IS*X**lZI@g(vc_r$2PL^0q{?hdOzG$;VNqC}lX)2G~;~}a+1Zd|g(Fwkz_;Iu5 z_m!u{Dc%aFo+OTD*~G;-Cv7Ii6`7DP+uCg_w2e%>#s5}Vzk;M3VS3LM2gF(-#O{&1 z@A4PO`$xP6GQGvr6OS>%gLRe+Nz(iy*R(L4HU!V zESL8id@!@R?6JoB;yxBKVO5#*VZ@uY!~C(2Z7mG5Z}Y2)?AqT-Q*{WJ)s;TT2uswL z{ms^7AS|VhMxkInL`5uasBU6)yL3=6V)+3>f7CgpRsJ*}eN$J^r~_2u*&ap+BL zk&+^s@OPj}POgKOss6v7YczVxX%3(cQ|;Sav^a|HF#1jWW>~08mR6fzR^{G^tD-3K z6=CnztF3*S&36iV(Qyg0P$SNvCv$7v@9W6d*z;Cr*h>h1B{T6s^X~hD$Ke28ldQ!{ zI@0N$%O!fFMHu%)A>xejXv1M}cQu9EY|^tZ19th3^;6kW=iX><_Y{3p0AeO2)&@4+ z3)UG(1^1k!TX$v^_A+Tp?$K(Exy;pt8MgE|G}yYOWEgX~`2Vx;nx35*n~#a{w$7@M zIzQu9E3Zgv)DYV9Iudv_-Ie9*3sGmEqReKi+~`{{Lh3FpB3ArHb^;0TS%;k1w=-0$ zT>jJQSRpO-Hy8897V&vw5*{r_%g6xIryaq((F}=)Gv)kuz^DjB=+24|q#Cz*9(L}0 zYRLg$Onxu-MNqo0Mr^GlcN09c0i?@2f*TYR7!<;muYkY;WGFt*WM2__=d+MXj5kYM zxpnvp0HZv&yi5~te&#<6P7I6C8XhyXUuQP=@6)EE7knlRU>?`?W2>_eTc>}WH3H*x zb|daT8yRGK(I>v9Y;xC#hT#E#eO^6ubEEr;{ZwE%Rli_@hzkND@_7_q>-{b1r^zZj zfpD^eSyP8r77YS;M=xb$_k2Y1zg{fE>o_MeK4qLh3d(hEc3sp=+`}r^8hHSKw>Dmz z!N^Mv2MC0`7r8@tZz&1ydO?x}M#H1z!oNe~qlhPWdj0H7?d K0jrQT3;rKUTjt3C literal 0 HcmV?d00001 diff --git a/src/assets/images/pretendo-wordmark-singlecolor-purple.png b/src/assets/images/pretendo-wordmark-singlecolor-purple.png new file mode 100644 index 0000000000000000000000000000000000000000..99039475c6c9f0a90b726c286ff9d75c9797c5fb GIT binary patch literal 5842 zcmcIoWmME((EcGxiUt6r-61Uv0*iDb4NERahjh2} z%m35+;r;y1xp(f|dCs|W&wQ9O&xCwbl_$Uh;Q;_Zpr|0D4geUI54IZ))`MP@vAlXX za2*tM;Q&A<_}|8mP2@IuaALsK<)wh~ValzC%VP^k6-fZ7jKaV9@&o|LEEHuVHQg}w zGCUngrjmM4_4DgVMeQ=Bw8l@8Nogy9>PH{kCi1MY!bpv@z78HlePDe4_diny!~6*g zTd=z(LHn2(99;VsM|ZpBHWspSUF7)TZ=%!nS#tqOjFA2zx#wz6MLL?~)7XYlg`f*PW_F5q}oh5@4j_QqT zF4>BV%g^Lcc+K#fd3cV`jq-+LCIA>IP8eiON>R@oCVrVAvS4gX0wHPV+J#*FZsi7- zSe))#=Iaqs0PvI6nsp?Gg`_4tz*99|Pm^S#gK2qxas8B_6beX8PAFx4O708tOe|8t zN5-GLCELl&G!SI~fWogcIHzIFQDAmh8Xn!YpCByk>*xVF1@GL-m)sAnHP@x$_(%mVIm3Ug(wYHLeH@#WF{^Ybs|3P(7Dq()Gk2}#3jROntU}i~Tp7w8 zn>Lfj9XDEtw!FFhrE&Oxtf$s=BPeRb=DRe#K0QUl0K*WvS|fo%oA&+M^Nq5vyNNp1 z+~a4vXcrr`&NB>vMM>;&!!7JvpyBuXu^4?=3|D1p(0+3E;E4vfHV|AMRlUwdrQp zB)8QgNyur}6_=)p*4#nKoC{;DgJXu=fB1YC90Pl1_0|AT($kOYG?@~ZDpp8D-%(JJ ze(0%p+#*GggblPMB|P6`RkIs47IMT-mTyrbA6BWhr_cUQC<6kPq|2T(7^DQwx!!LH z86L0l8dg!bjw>As_oW6YU;<->WfD)ntzui|OU% zeaR`cV!DWvgb5&~R?K?E0vF#t2pqU_Qll>CWMW*r&us&iFaV~aGKrEb0!G9NRvn3U z5s!T0n!_kP86!%jXaO-`am@e~mdyjV94~=lbpgOcDRXMH8Qg%f?Rg~V!ft(i+(FAgtloH)mIzi!L|rPHrS=NwPujH2}J5o#9{#~Y^)=1 z`fa2msy+%xZ`BAY)Wyk`jvHs3@uXnSj-#(?wdxXe_@WM+IXjv$fM6X~U#&0C7!b%h z4@z%xf2D>2|3=qmoD1Ji7UVLv4KRW2b|swCl|XmU`)oNWJRs}CwjsNspZxDeuOxpk zgx@#=129w5^VKT()7u@kdnQ=S)GVT;UJ8#b!2|#%-DHV-4dM7S?}KRlVlHMowVxR; zY_rLOhgZDCZX13SFUr2d1KRupahxU+m83{ZK#9+Wz^MZ!S~%1ln*h-A3Ih1rSfb}3 zA=Sny=Z2#Hcm=So3@qS_wkJ9{{E!Kf#I)xYz*nvWy^%^TA%qI_skJaBP@Lt6Kl5=U zkB@oiAtPT!*}HxpiDl8>-uQ@T1z`bMytE@`#)G+wGnutG0H9x-!=l)gm`J ziW6WE3Dv;_B#5LSuX8MMe`xP#Hb-N@l|v%0pLb`dS0QVTL9%hC(zm084+RtNqx*}V zlk*<^P`2hza+Do%Q76ATLwgF3`seauC88t&2{o-bzr+@^7JW^e11C=B`3k!fDXK2q zH)4+f_6!R`@jY_%-H($Zlg9dlGf9!K%eKQqNQzc5Ud{EOEvKYT&GGjio+LmP)-==u z%yj#aKvxlerh7l!tN80Ij3{sKRF!pWVkp$R<>K#G9$G+N+>*j(A zJv@lj4*Sbe%O{cv ziCGctK3sB%nYJ>ALvL4e^0(NxYZb;YvOYiH;MduoMM27CG4%17K~z{!s4RE{N5-Ht z7As3sODb!!rgHEJ*%{r-(A~G|!d^7IcZ^^1xeovYxb&-pvX6v6Cr3(l8Uu^Kv6#*X z(RR|^YWs%XV}NB4PX?B}z?Grw1$k#J3!RV}cI)e|xIfcANxCodN=|@pj11}e7%6L~ z7UIah?D z(t|%9OguGMbKgdw@9JJ_5l<0InTW)hy>R-F*xSrCHwN#@U8h{F)ZuZ1x56)zm82@Z zjRZ~2*KBu_M>!+JzZowESIV1t8-hORn<(u)@#rnU)+7l+x4i2{vS7dD_amDW9}ETW zJ9D0|->4bBcROFw=$Q}j#HAtD9rYMjos#0VA(kfNP>f;<5F6fgIv{dwj|wAxn;DIL zWkA-l_Be;MRofpkm+(~->=bs{ffcdb98O*!Vs~#Lrnnb}{YJ?*AZl)CVTJsfq*ZEY zlk^8w?fZw-W9K8B(m`9cDM*s}wFObBf3fqo6jd0V_{a8bX2j}KsxXS$?xhP|%T@)2 z^?$E6g=#DsZ}%>pOzgM#ayO3cYwbSeLy_Ci4@LE1(pO>WxZ^nfn;nCJYYooKsGj+P zG!LF1p?QaabKb7aNArOFQZkCzf*+ zjQ-!RfZLD`+5rf~zp2289VQDB%ZvC4H13G2XESwI2EKB73Ax;#`N-4i6)!Gphs%sO z4}4xl+tLkg`r{x+S|l|Ya)oKwdxn2sZjkhvgScf7ezX%i=Cp?Qc~73pdbkDa zPE1G^-X?UiUF8yxGK7jN7;1cM-9pxEFwL#PDEM4OML)wfW-I!_{}!<1MgQp}SQbY` z`1B%FF64bk!nAe$9F>>1FJM!lUc23JT7w>XrlO}(qKamq9>oc@BEMfQxs`4p9g9`L z*bjZSW0Zr*Kdq_EU;ey|k>Ch6(f6lf+pWZFZQGwK*ZHEzXt8iVsAhiwzv<(p+39T z|Fp*}UT_8O1O#uL&kyJ4Znavn^WlpfIk3r;ZJ0-Ns;CR}+EeEKpi1(HtJt2AWI4{; zd;~QW3!4fkVx)T}1ybz^7WlN}#iZY9jcej0Uo^k+&|OR3R3 z=saEG{q;eV$X{65Rvi9`!}V~uSKVTL;Z)x*lxc#fD5-YT-khL0Ib-hCapQhS{()M9 z+vnN>5%27UM?=50>`U5)9JK?{iQT(t!pb{JTlcnD_4N9~;_dT4RRQWqyQ=!b5#(69 zlX!^g8})~x>ku8QFg}8t-Oud5Olt{?Zi+bgTcGvp8q8*uX2pHToOVMk{Y{c|ik>qhOkpmu#Pj@C(NT4k+s)k!7~12{P^HsHeK8|> zuf73?>5y}pj@qQiv@G}=&wr|lcX39`^89I7UO#CDdlQOM>($H8GkppMJB244a@B(4 zTd3UIRQi1n9yuuZo1{q_ucZ5$;zM>I(ahVSu$~Wm4CBor4p(vJ?dG~K&M3a|GV@jJ zt5L4X20)BT|KvCQMKWn&3T4+dUWt>gGAMh#?MrzY_i{aJOm-)*r=MqICUf~^>&Nk% zAW{Jhe!;%0`0n`cpPl!`{Aq6y!9($TyCg>^YXk46B=I2D;|6zOxN%s6qYE z#QWZB%QYeyVft?r$e@oACY6%ERWjWrWjV~>aSyBy{1>)d@=<5S$Z;*Ext%4i>`t&j6_kVLu7 z*4r~05Di3M8ww?Rru$@ZF_$p*5>Kw?$38DYchuUIZXLZ_3xvK)5uc3v;0*!4Ym72o z8kSemREeawELu%=qALrKh~mkt`o}!L@FrHB_6%*^J05zdyz%}DNx#|E!|SuG`r5)< ze7Z@l#BZ9gE5x8DP6Rutd?YpZZUwm+;*QH%9UP}pC2#o0VR{OJR&)rGQiY{^UI{W$ zc$R)BzG(VMXr2QH?rC(9f8Q~s_ue(|4V9#+|pOg}nZPMPMY_2qAzhF_=-5-1PG`BZR zwSymKg?bUD^3s3bg_A}tP{GJ^I3cl4#f@$z^ES^mX9xY7dsTJAG08euRdX<&rFeBA z$tpup4t*lNCZW$VlfcAL-^FYzPW??@_fh3y0AaaiB|}D8)r)J+jsU@j!ftrUs~s(> zz>Je?8ZLw1^Xi19s5Bokt!4$*-%z+31(C}hZthYuPcmF5*BD4cBCOe#I?<5GO@=E|Z??cX*V4Z<~&6^gV?M!X^!qk%V*N zJ!bFuARYCCmdZ_bMqBqcf8TFF)VE8JfBkpm0$rKNzPH?nZH{(nNW40TQWaF3GJL%c zy(sEbvr^vQF;2LbN_9aW5bQ!cj^aBGxkP%7DeSJ!S~ zkgfH8vKpJFaVC3uHKw0J2NkxuFivw((vVWq5{!~zV+>L+7PLC@ECxvZkbyM~ZI!b1 zry(-TJS5<;gmBqRzkL^ei>op1vEQ)oz27zigf;I^D?KMXrOij+Q5jxdH;~=SD@~O*^9NFRn5}LW>*E?GpI<7QGt&xa|Lu zi-B~HZ!$R6!i!Yc{KTom?0pc)Gf(MAH^yLgS@aunJu74uwV0J$Vdnzr4CPj0$=3nD zTsSIDv79>^H^^`egbhb#)y}v^X`Dkgp`&m3HBvLVUV5}Cvw$AIBd#Z(3*0ALR;qkf z(`}DFd8LO~6T^dYn50!}uJc+86_8$4ycRzCUDk9=@8zs^Inkydt-REo=p?kEg9ZTKtqgfJmK$m;OmV>e9VQ&ntUU8WNUEZOLI$$Dar`btZDI zX-mLaGzt}VVvu!DuiJa}dqi!t6g5gvyF-?7!SRG6ME?Z==aL6`pn?8qINvWdhTgNk zJvL>M#*xUbwg%J6NQk^XdB(V2`rL2{bERjoJZUyb!8zf?ZX5C_TrOb;#P;XfgSsLp z6)JI~kUqctC`>X=B>khnpv+)(&}_z7_tBe48uDtp>p0SgOSA{&_%+SQ&)QNPQZeQr z8+ety)hPUtFQ+eim?8iy;Uh+#_zFG{>__68bCzk$xponp7=XkRi7YtXEghl#!og?Z zhf!7`PMzSpoXRke5}*FWV*u#KB0~y{)xtKmsWE`IM>@FpkVdg2@|(<~S+En`$1?L^ z9>6H3G&JmW|MPL19G$|FGImlp)1Wr566Smf1`uYR|Cut^CP)9a7A&Xc!o>5F^X!4R zC-(MVW%X<|rK<7fWyvP$bvg0vR}FlZjs7bW%*Uabrg=`=4}2A_JPr$ZJ=Hn7$!wgC zReaB{u@}yJHWs^OKVn5=hYv_(=nk+%#vGnMyr}i6OY(vFtN2R%|LUU8S>Jd?A2J1` zJeUs?DjInExrSVwG5{QAR6c)+eX_(KbIOXHxOIdAb5Rom0K(!e2hJYSmUWtFnPT6E q!fKWWwpc~Euw(PzzyFUI&0qS6W5$yQ4;aY)2P(>{%9KkP`TY-+!c#;5 literal 0 HcmV?d00001 diff --git a/src/server.js b/src/server.js index c4dcf6b..9372a3a 100644 --- a/src/server.js +++ b/src/server.js @@ -23,6 +23,7 @@ const nasc = require('./services/nasc'); const datastore = require('./services/datastore'); const api = require('./services/api'); const localcdn = require('./services/local-cdn'); +const assets = require('./services/assets'); // START APPLICATION @@ -42,6 +43,7 @@ app.use(nasc); app.use(datastore); app.use(api); app.use(localcdn); +app.use(assets); // 404 handler logger.info('Creating 404 status handler'); diff --git a/src/services/assets/index.js b/src/services/assets/index.js new file mode 100644 index 0000000..2059739 --- /dev/null +++ b/src/services/assets/index.js @@ -0,0 +1,22 @@ +// handles serving assets + +const express = require('express'); +const subdomain = require('express-subdomain'); +const logger = require('../../../logger'); +const path = require('path'); + +// Router to handle the subdomain restriction +const assets = express.Router(); + +// Setup public folder +logger.info('[assets] Setting up public folder'); +assets.use(express.static(path.join(__dirname, '../../assets'))); + +// Main router for endpoints +const router = express.Router(); + +// Create subdomains +logger.info('[conntest] Creating \'assets\' subdomain'); +router.use(subdomain('assets', assets)); + +module.exports = router; \ No newline at end of file From 734486d94aea5a513f36795e39314d7560c633d8 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Sat, 22 Oct 2022 20:56:35 +0200 Subject: [PATCH 098/105] feat: add html mailer --- src/mailer.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/mailer.js b/src/mailer.js index d8228e2..6bca5ec 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -1,5 +1,8 @@ const nodemailer = require('nodemailer'); const { config, disabledFeatures } = require('./config-manager'); +const path = require('path'); +const fs = require("fs"); +const genericEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/genericTemplate.html'), 'utf8'); let transporter; @@ -15,6 +18,35 @@ async function sendMail(options) { } } +/** + @param {Object} options + @param {String} options.to The address to send the email to + @param {String} options.subject The subject of the email + @param {String} options.username The username of the user (shown in the greeting) + @param {String} options.paragraph The main content of the email + @param {String} options.preview The preview text of the email (shown in the inbox by the email client) +*/ +async function sendHtmlMail(options) { + if (!disabledFeatures.email) { + const { to, subject, username, paragraph, preview } = options; + + let html = genericEmailTemplate; + + html = html.replace(/{{username}}/g, username); + html = html.replace(/{{paragraph}}/g, paragraph); + html = html.replace(/{{preview}}/g, preview); + + const transporterOptions = { + to, + subject, + html + } + await transporter.sendMail(transporterOptions); + } +} + + module.exports = { - sendMail + sendMail, + sendHtmlMail }; From 29d25f414f030c4be0b9015de7721fd00dbc7946 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Sat, 22 Oct 2022 21:49:15 +0200 Subject: [PATCH 099/105] feat: add buttons, confirmation email to sendMail, add new props --- ...emplate.html => confirmationTemplate.html} | 2 +- src/assets/emails/genericTemplate.html | 1 + src/mailer.js | 50 ++++++++++++------- src/util.js | 20 ++++++-- 4 files changed, 50 insertions(+), 23 deletions(-) rename src/assets/emails/{emailConfirmationTemplate.html => confirmationTemplate.html} (99%) diff --git a/src/assets/emails/emailConfirmationTemplate.html b/src/assets/emails/confirmationTemplate.html similarity index 99% rename from src/assets/emails/emailConfirmationTemplate.html rename to src/assets/emails/confirmationTemplate.html index 4c459b9..e8eebe2 100644 --- a/src/assets/emails/emailConfirmationTemplate.html +++ b/src/assets/emails/confirmationTemplate.html @@ -127,7 +127,7 @@ - + Confirm email address diff --git a/src/assets/emails/genericTemplate.html b/src/assets/emails/genericTemplate.html index 1dd0110..5f189c9 100644 --- a/src/assets/emails/genericTemplate.html +++ b/src/assets/emails/genericTemplate.html @@ -122,6 +122,7 @@ {{paragraph}} +   diff --git a/src/mailer.js b/src/mailer.js index 6bca5ec..b4e5ce8 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -3,6 +3,7 @@ const { config, disabledFeatures } = require('./config-manager'); const path = require('path'); const fs = require("fs"); const genericEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/genericTemplate.html'), 'utf8'); +const confirmationEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/confirmationTemplate.html'), 'utf8'); let transporter; @@ -10,43 +11,54 @@ if (!disabledFeatures.email) { transporter = nodemailer.createTransport(config.email); } -async function sendMail(options) { - if (!disabledFeatures.email) { - options.from = config.email.from; - - await transporter.sendMail(options); - } -} - /** @param {Object} options @param {String} options.to The address to send the email to @param {String} options.subject The subject of the email + @param {String} options.username The username of the user (shown in the greeting) - @param {String} options.paragraph The main content of the email @param {String} options.preview The preview text of the email (shown in the inbox by the email client) + @param {String} options.text The text version of the email + + @param {String} options.paragraph The main content of the email + + @param {Object} options.confirmation Whether or not the email is a confirmation email + @param {String} options.confirmation.href The link to the confirmation page + @param {String} options.confirmation.code The confirmation code + + @param {Object} options.link An object containing the link to be shown in the email + @param {String} options.link.href The URL of the link + @param {String} options.link.text The text of the link + */ -async function sendHtmlMail(options) { +async function sendMail(options) { if (!disabledFeatures.email) { - const { to, subject, username, paragraph, preview } = options; + const { to, subject, username, paragraph, preview, text, link, confirmation } = options; - let html = genericEmailTemplate; + let html = confirmation ? confirmationEmailTemplate : genericEmailTemplate; html = html.replace(/{{username}}/g, username); html = html.replace(/{{paragraph}}/g, paragraph); - html = html.replace(/{{preview}}/g, preview); + html = html.replace(/{{preview}}/g, (preview || "")); + html = html.replace(/{{confirmation-href}}/g, (confirmation?.href || "")); + html = html.replace(/{{confirmation-code}}/g, (confirmation?.code || "")); + + if (link) { + const { href, text } = link; - const transporterOptions = { + const button = ` ${text}` + html = html.replace(//g, button); + } + + await transporter.sendMail({ to, subject, + text, html - } - await transporter.sendMail(transporterOptions); + }); } } - module.exports = { - sendMail, - sendHtmlMail + sendMail }; diff --git a/src/util.js b/src/util.js index 5550a70..0050b38 100644 --- a/src/util.js +++ b/src/util.js @@ -250,15 +250,23 @@ async function sendConfirmationEmail(pnid) { await mailer.sendMail({ to: pnid.get('email.address'), subject: '[Pretendo Network] Please confirm your email address', - html: `Hello,

Your Pretendo Network ID activation is almost complete.

Please click the link below to confirm your e-mail address and complete the activation process.

https://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')}

If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.

<<Confirmation code: ${pnid.get('identification.email_code')}>>` + username: pnid.get('username'), + confirmation: { + href: `https://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')}`, + code: pnid.get('identification.email_code') + }, + text: `Hello ${pnid.get('username')}! \r\n\r\nYour Pretendo Network ID activation is almost complete. Please click the link to confirm your e-mail address and complete the activation process: \r\nhttps://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')} \r\n\r\nYou may also enter the following 6-digit code on your console: ${pnid.get('identification.email_code')}` }); + } async function sendEmailConfirmedEmail(pnid) { await mailer.sendMail({ to: pnid.get('email.address'), subject: '[Pretendo Network] Email address confirmed', - html: 'Your email address has been confirmed!' + username: pnid.get('username'), + paragraph: 'your email address has been confirmed. We hope you have fun on Pretendo Network!', + text: `Dear ${pnid.get('username')}, \r\n\r\nYour email address has been confirmed. We hope you have fun on Pretendo Network!` }); } @@ -285,7 +293,13 @@ async function sendForgotPasswordEmail(pnid) { await mailer.sendMail({ to: pnid.get('email.address'), subject: '[Pretendo Network] Forgot Password', - html: `Visit this link to reset your password ${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}` + username: pnid.get('username'), + paragraph: 'a password reset has been requested from this account. If you did not request the password reset, please ignore this email. If you did request this password reset, please click the link below to reset your password.', + link: { + text: 'Reset password', + href: `${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}` + }, + text: `Dear ${pnid.get('username')}, a password reset has been requested from this account. \r\n\r\nIf you did not request the password reset, please ignore this email. \r\nIf you did request this password reset, please click the link to reset your password: ${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}` }); } From 7f5fcbb28da0cf935f1a805986a9b3a2a5a5a03d Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Feb 2023 09:22:16 -0500 Subject: [PATCH 100/105] Updated package-lock --- package-lock.json | 4060 +++++++++++++++++++++++++++------------------ 1 file changed, 2421 insertions(+), 1639 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4fa0176..79df13e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,6 +71,25 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, "node_modules/@oozcitak/dom": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-0.0.11.tgz", @@ -179,36 +198,39 @@ "node": ">=6.0" } }, + "node_modules/@oozcitak/uts46/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, "node_modules/@redis/bloom": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz", - "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", + "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.3.0.tgz", - "integrity": "sha512-XCFV60nloXAefDsPnYMjHGtvbtHR8fV5Om8cQ0JYqTNbWcQo/4AryzJ2luRj4blveWazRK/j40gES8M7Cp6cfQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.5.tgz", + "integrity": "sha512-fuMnpDYSjT5JXR9rrCW1YWA4L8N/9/uS4ImT3ZEC/hcaQRI1D/9FvwjriRj1UvepIgzZXthFVKMNRzP/LNL7BQ==", "dependencies": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", "yallist": "4.0.0" }, "engines": { "node": ">=14" } }, - "node_modules/@redis/client/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@redis/graph": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz", - "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", + "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", "peerDependencies": { "@redis/client": "^1.0.0" } @@ -222,17 +244,17 @@ } }, "node_modules/@redis/search": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", - "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.1.tgz", + "integrity": "sha512-pqCXTc5e7wJJgUuJiC3hBgfoFRoPxYzwn0BEfKgejTM7M/9zP3IpUcqcjgfp8hF+LoV8rHZzcNTz7V+pEIY7LQ==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/time-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", - "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "peerDependencies": { "@redis/client": "^1.0.0" } @@ -246,9 +268,9 @@ } }, "node_modules/@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" }, "node_modules/@sideway/pinpoint": { "version": "2.0.0", @@ -256,9 +278,9 @@ "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" }, "node_modules/@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "engines": { "node": ">=10" }, @@ -286,14 +308,14 @@ } }, "node_modules/@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", "dependencies": { "@types/http-cache-semantics": "*", - "@types/keyv": "*", + "@types/keyv": "^3.1.4", "@types/node": "*", - "@types/responselike": "*" + "@types/responselike": "^1.0.0" } }, "node_modules/@types/http-cache-semantics": { @@ -302,9 +324,9 @@ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, "node_modules/@types/keyv": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", - "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", "dependencies": { "@types/node": "*" } @@ -319,9 +341,9 @@ } }, "node_modules/@types/node": { - "version": "16.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.1.tgz", - "integrity": "sha512-ncRdc45SoYJ2H4eWU9ReDfp3vtFqDYhjOsKlFFUDEn8V1Bgr2RjYal8YT5byfadWIRluhPFU6JiDOl0H6Sl87A==" + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" }, "node_modules/@types/responselike": { "version": "1.0.0", @@ -337,12 +359,12 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" @@ -377,6 +399,38 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -393,30 +447,54 @@ } }, "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "node_modules/are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "dependencies": { "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/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==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/are-we-there-yet/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" } }, "node_modules/arr-flatten": { @@ -430,12 +508,12 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-from": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" + "integrity": "sha512-GQTc6Uupx1FCavi5mPzBvVT7nEOeWMmUA9P95wpfpW1XwMSKs+KaymD5C2Up7KAUKg/mYwbsUYzdZWcoajlNZg==" }, "node_modules/arraybuffer-to-string": { "version": "1.0.2", @@ -443,9 +521,9 @@ "integrity": "sha512-WbIYlLVmvIAyUBdQRRuyGOJRriOQy9OAsWcyURmsRQp9+g647hdMSS2VFKXbJLVw0daUu06hqwLXm9etVrXI9A==" }, "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dependencies": { "safer-buffer": "~2.1.0" } @@ -453,7 +531,7 @@ "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "engines": { "node": ">=0.8" } @@ -467,7 +545,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -480,59 +558,56 @@ "node_modules/atob-lite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=" + "integrity": "sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/aws-sdk": { - "version": "2.978.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.978.0.tgz", - "integrity": "sha512-UO1HP2b9FFtPhc5KbzEJ9oMBdzCmVv9nQTb+yIEh6SajcaErmK/ryleLOuPq9EsirE6wgb6mtf2qodRFucUA3g==", - "hasInstallScript": true, + "version": "2.1313.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1313.0.tgz", + "integrity": "sha512-8GMdtV2Uch3HL2c6+P3lNZFTcg/fqq9L3EWYRLb6ljCZvWKTssjdkjSJFDyTReNgeiKV224YRPYQbKpOEz4flQ==", "dependencies": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", - "jmespath": "0.15.0", + "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", - "uuid": "3.3.2", + "util": "^0.12.4", + "uuid": "8.0.0", "xml2js": "0.4.19" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/aws-sdk/node_modules/sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" - }, - "node_modules/aws-sdk/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" + "node": ">= 10.0.0" } }, "node_modules/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": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "engines": { "node": "*" } }, "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -564,13 +639,19 @@ "node": ">= 0.8" } }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "hasInstallScript": true, "dependencies": { - "node-addon-api": "^3.0.0", - "node-pre-gyp": "0.15.0" + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" }, "engines": { "node": ">= 10.0.0" @@ -579,7 +660,7 @@ "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dependencies": { "tweetnacl": "^0.14.3" } @@ -598,6 +679,33 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", @@ -606,26 +714,29 @@ "node_modules/bmp-js": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", - "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==" }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/brace-expansion": { @@ -672,7 +783,7 @@ "node_modules/buffer-equal": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==", "engines": { "node": ">=0.4.0" } @@ -685,17 +796,17 @@ "node_modules/buffer-to-arraybuffer": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + "integrity": "sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==" }, "node_modules/buffer-to-uint8array": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-to-uint8array/-/buffer-to-uint8array-1.1.0.tgz", - "integrity": "sha1-z29BKHwCL0WNp1LDkcGo1TXsX3I=" + "integrity": "sha512-JVTSbtA6YuOGdu5NL0ffizsBwuwbTXfV7OC91FhazMz9UKP/KlDS+Z7wuiSRClbnTQz52fJgVXI9YDXQRVl2sQ==" }, "node_modules/busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", "dependencies": { "dicer": "0.2.5", "readable-stream": "1.1.x" @@ -704,31 +815,10 @@ "node": ">=0.8.0" } }, - "node_modules/busboy/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/busboy/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/busboy/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } @@ -758,15 +848,30 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } }, "node_modules/clip-pixels": { "version": "1.0.1", @@ -774,27 +879,30 @@ "integrity": "sha512-nJ22fZvCwkJfMppkOEE7GciLX08rDnVzEJ+U46kBFZtwNzH2V4tNxMWa9Tc365WspCxy1c3NtGJ5EeT4SgjmCA==" }, "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "dependencies": { "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", "engines": { "node": ">=0.10.0" } }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "engines": { - "node": ">=0.10.0" + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" } }, "node_modules/colors": { @@ -819,7 +927,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -835,6 +943,33 @@ "typedarray": "^0.0.6" } }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/connect-multiparty": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/connect-multiparty/-/connect-multiparty-2.2.0.tgz", @@ -850,10 +985,65 @@ "node": ">=0.10.0" } }, + "node_modules/connect-multiparty/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/connect-multiparty/node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/connect-multiparty/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/connect-multiparty/node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/connect-multiparty/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/connect-multiparty/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/connect-multiparty/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", "engines": { "node": ">=0.6" } @@ -861,39 +1051,36 @@ "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } }, "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dependencies": { - "safe-buffer": "~5.1.1" - } + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -901,12 +1088,12 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -923,7 +1110,7 @@ "node_modules/cycle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -946,7 +1133,7 @@ "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dependencies": { "assert-plus": "^1.0.0" }, @@ -987,14 +1174,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1011,7 +1190,7 @@ "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { "node": ">=0.4.0" } @@ -1019,7 +1198,7 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "node_modules/denque": { "version": "1.5.1", @@ -1030,33 +1209,34 @@ } }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", "engines": { - "node": ">=0.10" + "node": ">=8" } }, "node_modules/dicer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", "dependencies": { "readable-stream": "1.1.x", "streamsearch": "0.1.2" @@ -1065,27 +1245,6 @@ "node": ">=0.8.0" } }, - "node_modules/dicer/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/dicer/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/dicer/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "node_modules/dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -1097,7 +1256,7 @@ "node_modules/dtype": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz", - "integrity": "sha1-zQUjI84GFETs0uj1dI9popvihDQ=", + "integrity": "sha512-s2YVcLKdFGS0hpFqJaTwscsyt0E8nNFdmo73Ocd81xNPj4URI4rj6D60A+vFMIw7BXWlb4yRkEwfBqcZzPGiZg==", "engines": { "node": ">= 0.8.0" } @@ -1105,15 +1264,42 @@ "node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "dependencies": { "readable-stream": "^2.0.2" } }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -1122,7 +1308,7 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/email-validator": { "version": "2.0.4", @@ -1132,10 +1318,15 @@ "node": ">4.0" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } @@ -1149,9 +1340,9 @@ } }, "node_modules/es5-ext": { - "version": "0.10.61", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", - "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", @@ -1165,7 +1356,7 @@ "node_modules/es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "dependencies": { "d": "1", "es5-ext": "^0.10.35", @@ -1175,7 +1366,7 @@ "node_modules/es6-map": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "integrity": "sha512-mz3UqCh0uPCIqsw1SSAkB/p0rOzF/M0V++vyN7JqlPtSW/VsYgQBvVvqMLmfBuyMzTpLnNqi6JmcSizs4jy19A==", "dependencies": { "d": "1", "es5-ext": "~0.10.14", @@ -1186,25 +1377,25 @@ } }, "node_modules/es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.6.tgz", + "integrity": "sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==", "dependencies": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "es6-iterator": "~2.0.3", + "es6-symbol": "^3.1.3", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" } }, - "node_modules/es6-set/node_modules/es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } + "node_modules/es6-set/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" }, "node_modules/es6-symbol": { "version": "3.1.3", @@ -1229,7 +1420,7 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escodegen": { "version": "1.14.3", @@ -1288,7 +1479,7 @@ "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } @@ -1296,7 +1487,7 @@ "node_modules/event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "dependencies": { "d": "1", "es5-ext": "~0.10.14" @@ -1305,43 +1496,44 @@ "node_modules/events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", "engines": { "node": ">=0.4.x" } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -1351,12 +1543,13 @@ } }, "node_modules/express-form-data": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/express-form-data/-/express-form-data-2.0.17.tgz", - "integrity": "sha512-gsF61uGRAzRw4HXWiJ1dzjl1igpRzankTYv1An6uOd0WiySKi7HJ0ng88qaGM3kjZyKsaPcucrMnTLcmXdoVjw==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/express-form-data/-/express-form-data-2.0.19.tgz", + "integrity": "sha512-QWulRIYvZV/ZOuO0+SNpCs9Gl0st9SssYtm5Icfm17p2MU4HASLpd4K5w8fwnXB/lPPskecVSeqjVWi2SwIb1A==", "dependencies": { "connect-multiparty": "^2.2.0", - "fs-extra": "^9.1.0" + "fs-extra": "^9.1.0", + "signal-exit": "^3.0.7" }, "engines": { "node": ">=5.0.0" @@ -1396,27 +1589,27 @@ } }, "node_modules/express-rate-limit": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.3.0.tgz", - "integrity": "sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==" + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", + "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==" }, "node_modules/express-subdomain": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.5.tgz", - "integrity": "sha1-mQ75eUC39MKCPZWTZIt5voWKY4s=" + "integrity": "sha512-tpYy7MPgDoouxA4r+BnGI43yxYakbSSpQn7MjEYM0ssHeipTM1YiIoK3i4pCAgoXoks22Yb5C4QFkOYBYczZcw==" }, "node_modules/ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "dependencies": { - "type": "^2.5.0" + "type": "^2.7.2" } }, "node_modules/ext/node_modules/type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" }, "node_modules/extend": { "version": "3.0.2", @@ -1426,7 +1619,7 @@ "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "engines": [ "node >=0.6.0" ] @@ -1434,7 +1627,7 @@ "node_modules/eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", "dev": true, "engines": { "node": "> 0.1.90" @@ -1453,7 +1646,7 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/file-type": { "version": "10.11.0", @@ -1464,16 +1657,16 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -1493,10 +1686,18 @@ "resolved": "https://registry.npmjs.org/flip-pixels/-/flip-pixels-1.0.2.tgz", "integrity": "sha512-oXbJGbjDnfJRWPC7Va38EFhd+A8JWE5/hCiKcK8qjCdbLj9DTpsq6MEudwpRTH+V4qq+Jw7d3pUgQdSr3x3mTA==" }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "engines": { "node": "*" } @@ -1515,17 +1716,18 @@ } }, "node_modules/formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", "funding": { "url": "https://ko-fi.com/tunnckoCore/commissions" } }, "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "engines": { "node": ">= 0.6" } @@ -1533,7 +1735,7 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } @@ -1552,17 +1754,31 @@ } }, "node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dependencies": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/function-bind": { "version": "1.1.1", @@ -1570,24 +1786,28 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "dependencies": { - "aproba": "^1.0.3", + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" } }, "node_modules/generic-pool": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", - "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "engines": { "node": ">= 4" } @@ -1597,6 +1817,19 @@ "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -1614,38 +1847,52 @@ "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dependencies": { "assert-plus": "^1.0.0" } }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", @@ -1660,14 +1907,14 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "engines": { "node": ">=4" } @@ -1696,40 +1943,65 @@ "node": ">= 0.4.0" } }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, "node_modules/hcaptcha": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/hcaptcha/-/hcaptcha-0.1.0.tgz", - "integrity": "sha512-mVRkhNcOuP7QJO50nYdu3vS+uaOg6Ku2HpMy50C2EckjB9DlnwX24iePi912IXuVIq5L8ukjISG4Ea6MimZ5+w==" + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/hcaptcha/-/hcaptcha-0.1.1.tgz", + "integrity": "sha512-iMrDmH2VpIEKOrcKWidVjI89FdDKTEdZ7PfPWkP27sTazIIkob8YfdY2ezaufAnWBiUUcvzsn0qF+dyXtBH2Vw==" }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -1752,6 +2024,39 @@ "node": ">=10.19.0" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1768,14 +2073,6 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, - "node_modules/ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dependencies": { - "minimatch": "^3.0.4" - } - }, "node_modules/image-pixels": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/image-pixels/-/image-pixels-1.1.1.tgz", @@ -1823,30 +2120,40 @@ "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "engines": { "node": ">= 0.10" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-base64": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/is-base64/-/is-base64-0.0.6.tgz", @@ -1890,10 +2197,21 @@ "node": ">=4" } }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dependencies": { "has": "^1.0.3" }, @@ -1902,20 +2220,31 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dependencies": { - "number-is-nan": "^1.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "engines": { "node": ">=0.10.0" } @@ -1925,10 +2254,28 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "node_modules/is-url": { "version": "1.2.4", @@ -1938,30 +2285,30 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, "node_modules/jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", "engines": { "node": ">= 0.6.0" } }, "node_modules/joi": { - "version": "17.6.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.1.tgz", - "integrity": "sha512-Hl7/iBklIX345OCM1TiFSCZRVaAOLDGlWCp0Df2vWYgBgjkezaR7Kvm3joBciBHQjZj5sxXs859r6eqsRSlG8w==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.7.1.tgz", + "integrity": "sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA==", "dependencies": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", + "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, @@ -1973,7 +2320,7 @@ "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, "node_modules/json-buffer": { "version": "3.0.1", @@ -1993,13 +2340,13 @@ "node_modules/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": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dependencies": { + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { "graceful-fs": "^4.1.6" } }, @@ -2028,9 +2375,9 @@ "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" }, "node_modules/keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", "dependencies": { "json-buffer": "3.0.1" } @@ -2038,7 +2385,7 @@ "node_modules/levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -2047,10 +2394,16 @@ "node": ">= 0.8.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "node_modules/lodash.foreach": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==" }, "node_modules/lodash.get": { "version": "4.4.2", @@ -2070,6 +2423,17 @@ "node": ">=8" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/magic-string": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", @@ -2078,10 +2442,32 @@ "sourcemap-codec": "^1.4.1" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -2095,12 +2481,12 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/merge-source-map": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", - "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", + "integrity": "sha512-PGSmS0kfnTnMJCzJ16BLLCEe6oeYCamKFFdQKshi4BmM6FUwipjVOcBFGxqtQtirtAG4iZvHlqST9CpZKqlRjA==", "dependencies": { "source-map": "^0.5.6" } @@ -2108,7 +2494,7 @@ "node_modules/merge-source-map/node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "engines": { "node": ">=0.10.0" } @@ -2116,7 +2502,7 @@ "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -2141,19 +2527,19 @@ } }, "node_modules/mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.42.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -2168,9 +2554,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2179,50 +2565,67 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", + "integrity": "sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==", + "engines": { + "node": ">=8" } }, "node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dependencies": { - "minipass": "^2.9.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dependencies": { - "minimist": "^1.2.5" + "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "engines": { "node": "*" } }, "node_modules/moment-timezone": { - "version": "0.5.27", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz", - "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==", + "version": "0.5.40", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz", + "integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==", "dependencies": { "moment": ">= 2.9.0" }, @@ -2280,9 +2683,9 @@ } }, "node_modules/mongoose": { - "version": "5.13.13", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.13.tgz", - "integrity": "sha512-M55tpCr/p5i6vdJ54nm4MG6/7SKV4JqlWnqbx6yCRuAuW05CZ7u+gNuHVPQVF9dZ59ALXjOtPEUl+OXklAa7ng==", + "version": "5.13.15", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz", + "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==", "dependencies": { "@types/bson": "1.x || 4.0.x", "@types/mongodb": "^3.5.27", @@ -2310,7 +2713,10 @@ "node_modules/mongoose-legacy-pluralize": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "peerDependencies": { + "mongoose": "*" + } }, "node_modules/mongoose-unique-validator": { "version": "2.0.3", @@ -2319,6 +2725,9 @@ "dependencies": { "lodash.foreach": "^4.1.0", "lodash.get": "^4.0.2" + }, + "peerDependencies": { + "mongoose": "^5.2.1" } }, "node_modules/mongoose/node_modules/ms": { @@ -2326,40 +2735,32 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/mongoose/node_modules/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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/morgan": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", - "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", "dependencies": { - "basic-auth": "~2.0.0", + "basic-auth": "~2.0.1", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "~2.0.0", "on-finished": "~2.3.0", - "on-headers": "~1.0.1" + "on-headers": "~1.0.2" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/mpath": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", @@ -2391,15 +2792,21 @@ "ms": "2.0.0" } }, + "node_modules/mquery/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/multer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", - "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", "dependencies": { "append-field": "^1.0.0", "busboy": "^0.2.11", @@ -2415,11 +2822,11 @@ } }, "node_modules/multiparty": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.2.tgz", - "integrity": "sha512-NtZLjlvsjcoGrzojtwQwn/Tm90aWJ6XXtPppYF4WmOk/6ncdwMMKggFY2NlRRN9yiCEIVxpOfPWahVEG2HAG8Q==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", + "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", "dependencies": { - "http-errors": "~1.8.0", + "http-errors": "~1.8.1", "safe-buffer": "5.2.1", "uid-safe": "2.1.5" }, @@ -2427,49 +2834,36 @@ "node": ">= 0.10" } }, + "node_modules/multiparty/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/multiparty/node_modules/http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.6" } }, - "node_modules/multiparty/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/multiparty/node_modules/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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/multiparty/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/multiparty/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } }, "node_modules/mute-stream": { "version": "0.0.8", @@ -2477,39 +2871,10 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "node_modules/needle": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", - "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/needle/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } @@ -2520,58 +2885,58 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, "node_modules/node-addon-api": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", - "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==" - }, - "node_modules/node-pre-gyp": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", - "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", - "dependencies": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.3", - "needle": "^2.5.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "dependencies": { + "whatwg-url": "^5.0.0" }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/node-rsa": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.0.7.tgz", - "integrity": "sha512-idwRXma6scFufZmbaKkHpJoLL93yynRefP6yur13wZ5i9FR35ex451KCoF2OORDeJanyRVahmjjiwmUlCnTqJA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", + "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", "dev": true, "dependencies": { "asn1": "^0.2.4" } }, "node_modules/nodemailer": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.3.tgz", - "integrity": "sha512-faZFufgTMrphYoDjvyVpbpJcYzwyFnbAMmQtj1lVBYAUSm3SOy2fIdd9+Mr4UxPosBa0JRw9bJoIwQn+nswiew==", - "license": "MIT", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz", + "integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==", "engines": { "node": ">=6.0.0" } }, "node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/normalize-url": { @@ -2585,46 +2950,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "dependencies": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "node_modules/npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "dependencies": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "engines": { - "node": ">=0.10.0" + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" } }, "node_modules/oauth-sign": { @@ -2638,15 +2972,15 @@ "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2657,9 +2991,9 @@ "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -2678,7 +3012,7 @@ "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dependencies": { "wrappy": "1" } @@ -2707,31 +3041,6 @@ "node": ">= 0.8.0" } }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -2759,7 +3068,7 @@ "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "engines": { "node": ">=0.10.0" } @@ -2772,17 +3081,17 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "node_modules/pick-by-alias": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pick-by-alias/-/pick-by-alias-1.2.0.tgz", - "integrity": "sha1-X3yysfIabh6ISgyHhVqko3NhEHs=" + "integrity": "sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw==" }, "node_modules/pngjs": { "version": "3.4.0", @@ -2795,7 +3104,7 @@ "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "engines": { "node": ">= 0.8.0" } @@ -2827,21 +3136,21 @@ } }, "node_modules/proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { "node": ">= 0.10" } }, "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, "node_modules/pump": { "version": "3.0.0", @@ -2853,25 +3162,31 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", "engines": { "node": ">=0.4.x" @@ -2891,7 +3206,7 @@ "node_modules/quote-stream": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", - "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", + "integrity": "sha512-kKr2uQ2AokadPjvTyKJQad9xELbZwYzWlNfI3Uz2j/ib5u6H9lDP7fUUR//rMycd0gv4Z5P1qXMfXR8YpIxrjQ==", "dependencies": { "buffer-equal": "0.0.1", "minimist": "^1.1.3", @@ -2904,7 +3219,7 @@ "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", "engines": { "node": ">= 0.8" } @@ -2918,12 +3233,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -2931,24 +3246,10 @@ "node": ">= 0.8" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, "node_modules/read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", "dev": true, "dependencies": { "mute-stream": "~0.0.4" @@ -2958,30 +3259,32 @@ } }, "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "dependencies": { "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, "node_modules/redis": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.3.1.tgz", - "integrity": "sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA==", + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.4.tgz", + "integrity": "sha512-wi2tgDdQ+Q8q+PR5FLRx4QvDiWaA+PoJbrzsyFqlClN5R4LplHqN3scs/aGjE//mbz++W19SgxiEnQ27jnCRaA==", "dependencies": { - "@redis/bloom": "1.0.2", - "@redis/client": "1.3.0", - "@redis/graph": "1.0.1", + "@redis/bloom": "1.2.0", + "@redis/client": "1.5.5", + "@redis/graph": "1.1.0", "@redis/json": "1.0.4", - "@redis/search": "1.1.0", - "@redis/time-series": "1.0.3" + "@redis/search": "1.1.1", + "@redis/time-series": "1.0.4" } }, "node_modules/regexp-clone": { @@ -3021,13 +3324,22 @@ } }, "node_modules/request/node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "engines": { "node": ">=0.6" } }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/require-at": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", @@ -3037,11 +3349,11 @@ } }, "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dependencies": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -3053,42 +3365,67 @@ } }, "node_modules/resolve-alpn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.0.tgz", - "integrity": "sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "node_modules/responselike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", - "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", "dependencies": { "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restructure": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", + "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" + }, "node_modules/revalidator": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", + "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", "dev": true, "engines": { "node": ">= 0.4.0" } }, "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -3108,9 +3445,9 @@ } }, "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, "node_modules/scope-analyzer": { "version": "2.1.2", @@ -3127,50 +3464,56 @@ } }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" @@ -3179,17 +3522,30 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/shallow-copy": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + "integrity": "sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/sift": { "version": "13.5.2", @@ -3197,14 +3553,14 @@ "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" }, "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sliced": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" }, "node_modules/source-map": { "version": "0.6.1", @@ -3218,21 +3574,22 @@ "node_modules/sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" }, "node_modules/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "optional": true, "dependencies": { "memory-pager": "^1.0.2" } }, "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -3256,7 +3613,7 @@ "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", "dev": true, "engines": { "node": "*" @@ -3291,29 +3648,53 @@ "through2": "~2.0.3" } }, + "node_modules/static-module/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/static-module/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/static-module/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/streamsearch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", "engines": { "node": ">=0.8.0" } }, "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, "node_modules/string-to-arraybuffer": { "version": "1.0.2", @@ -3330,35 +3711,27 @@ "integrity": "sha512-WRRyllsGXJM7ZN7gPTCCQ/6wNPTRDwiWdPK66l5sJzcU/oOzcIcRRf0Rux8bkpox/1yjt0F6VJRsQOIG2qz5sg==" }, "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -3373,47 +3746,39 @@ } }, "node_modules/tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "dependencies": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^4.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "engines": { - "node": ">=4.5" + "node": ">=10" } }, - "node_modules/tar/node_modules/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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } }, "node_modules/tga": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tga/-/tga-1.0.4.tgz", - "integrity": "sha512-UdYjLm6XDhH0czfel87opaoynxIWI6AXMLkaUvZyl8AzJnAvOH1bHmHjdcolTzi4RjbBU8rgd7ys7sHxFAY1WA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tga/-/tga-1.0.7.tgz", + "integrity": "sha512-GFVJwov5aJTMgh8U1QfaRheIELXo+dYc1qYIvQEIqZX4n+S6Fj/SDWsdbelHt7WP08xOR6W1z5aJQ+Ilh5gIeA==", "dependencies": { - "debug": "^2.6.1" + "debug": "^2.6.1", + "restructure": "^2.0.0" }, "engines": { "node": ">=6.0.0" @@ -3428,6 +3793,33 @@ "xtend": "~4.0.1" } }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/to-array-buffer": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/to-array-buffer/-/to-array-buffer-2.2.2.tgz", @@ -3439,9 +3831,9 @@ } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } @@ -3458,10 +3850,15 @@ "node": ">=0.8" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -3472,7 +3869,7 @@ "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, "node_modules/type": { "version": "1.2.0", @@ -3482,7 +3879,7 @@ "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dependencies": { "prelude-ls": "~1.1.2" }, @@ -3505,7 +3902,7 @@ "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/uid-safe": { "version": "2.1.5", @@ -3529,7 +3926,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -3545,7 +3942,7 @@ "node_modules/url": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" @@ -3554,34 +3951,45 @@ "node_modules/url/node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } }, "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", "bin": { - "uuid": "bin/uuid" + "uuid": "dist/bin/uuid" } }, "node_modules/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", + "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", "engines": { "node": ">= 0.10" } @@ -3589,7 +3997,7 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } @@ -3597,7 +4005,7 @@ "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "engines": [ "node >=0.6.0" ], @@ -3607,21 +4015,59 @@ "extsprintf": "^1.2.0" } }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dependencies": { - "string-width": "^1.0.2 || 2" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "node_modules/winston": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", - "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==", + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", + "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", "dev": true, "dependencies": { - "async": "^3.2.3", + "async": "^2.6.4", "colors": "1.0.x", "cycle": "1.0.x", "eyes": "0.1.x", @@ -3632,10 +4078,19 @@ "node": ">= 0.10.0" } }, + "node_modules/winston/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, "node_modules/winston/node_modules/colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", "dev": true, "engines": { "node": ">=0.1.90" @@ -3652,7 +4107,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/xml2js": { "version": "0.4.19", @@ -3666,7 +4121,7 @@ "node_modules/xml2js/node_modules/xmlbuilder": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", "engines": { "node": ">=4.0" } @@ -3701,9 +4156,9 @@ } }, "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yesno": { "version": "0.4.0", @@ -3732,6 +4187,22 @@ "@hapi/hoek": "^9.0.0" } }, + "@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + } + }, "@oozcitak/dom": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-0.0.11.tgz", @@ -3814,36 +4285,34 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" } } }, "@redis/bloom": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz", - "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", + "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", "requires": {} }, "@redis/client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.3.0.tgz", - "integrity": "sha512-XCFV60nloXAefDsPnYMjHGtvbtHR8fV5Om8cQ0JYqTNbWcQo/4AryzJ2luRj4blveWazRK/j40gES8M7Cp6cfQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.5.tgz", + "integrity": "sha512-fuMnpDYSjT5JXR9rrCW1YWA4L8N/9/uS4ImT3ZEC/hcaQRI1D/9FvwjriRj1UvepIgzZXthFVKMNRzP/LNL7BQ==", "requires": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", "yallist": "4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } } }, "@redis/graph": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz", - "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", + "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", "requires": {} }, "@redis/json": { @@ -3853,15 +4322,15 @@ "requires": {} }, "@redis/search": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", - "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.1.tgz", + "integrity": "sha512-pqCXTc5e7wJJgUuJiC3hBgfoFRoPxYzwn0BEfKgejTM7M/9zP3IpUcqcjgfp8hF+LoV8rHZzcNTz7V+pEIY7LQ==", "requires": {} }, "@redis/time-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", - "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "requires": {} }, "@sideway/address": { @@ -3873,9 +4342,9 @@ } }, "@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" }, "@sideway/pinpoint": { "version": "2.0.0", @@ -3883,9 +4352,9 @@ "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" }, "@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==" }, "@szmarczak/http-timer": { "version": "4.0.6", @@ -3904,14 +4373,14 @@ } }, "@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", "requires": { "@types/http-cache-semantics": "*", - "@types/keyv": "*", + "@types/keyv": "^3.1.4", "@types/node": "*", - "@types/responselike": "*" + "@types/responselike": "^1.0.0" } }, "@types/http-cache-semantics": { @@ -3920,9 +4389,9 @@ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, "@types/keyv": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", - "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", "requires": { "@types/node": "*" } @@ -3937,9 +4406,9 @@ } }, "@types/node": { - "version": "16.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.1.tgz", - "integrity": "sha512-ncRdc45SoYJ2H4eWU9ReDfp3vtFqDYhjOsKlFFUDEn8V1Bgr2RjYal8YT5byfadWIRluhPFU6JiDOl0H6Sl87A==" + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" }, "@types/responselike": { "version": "1.0.0", @@ -3955,12 +4424,12 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, "acorn": { @@ -3983,6 +4452,29 @@ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -3995,27 +4487,47 @@ } }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "requires": { "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "readable-stream": "^3.6.0" + }, + "dependencies": { + "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" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + } } }, "arr-flatten": { @@ -4026,12 +4538,12 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "array-from": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=" + "integrity": "sha512-GQTc6Uupx1FCavi5mPzBvVT7nEOeWMmUA9P95wpfpW1XwMSKs+KaymD5C2Up7KAUKg/mYwbsUYzdZWcoajlNZg==" }, "arraybuffer-to-string": { "version": "1.0.2", @@ -4039,9 +4551,9 @@ "integrity": "sha512-WbIYlLVmvIAyUBdQRRuyGOJRriOQy9OAsWcyURmsRQp9+g647hdMSS2VFKXbJLVw0daUu06hqwLXm9etVrXI9A==" }, "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "requires": { "safer-buffer": "~2.1.0" } @@ -4049,7 +4561,7 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" }, "async": { "version": "3.2.3", @@ -4060,7 +4572,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "at-least-node": { "version": "1.0.0", @@ -4070,50 +4582,44 @@ "atob-lite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=" + "integrity": "sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==" + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "aws-sdk": { - "version": "2.978.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.978.0.tgz", - "integrity": "sha512-UO1HP2b9FFtPhc5KbzEJ9oMBdzCmVv9nQTb+yIEh6SajcaErmK/ryleLOuPq9EsirE6wgb6mtf2qodRFucUA3g==", + "version": "2.1313.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1313.0.tgz", + "integrity": "sha512-8GMdtV2Uch3HL2c6+P3lNZFTcg/fqq9L3EWYRLb6ljCZvWKTssjdkjSJFDyTReNgeiKV224YRPYQbKpOEz4flQ==", "requires": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", - "jmespath": "0.15.0", + "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", - "uuid": "3.3.2", + "util": "^0.12.4", + "uuid": "8.0.0", "xml2js": "0.4.19" - }, - "dependencies": { - "sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - } } }, "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": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" }, "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", @@ -4126,21 +4632,28 @@ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "requires": { "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", "requires": { - "node-addon-api": "^3.0.0", - "node-pre-gyp": "0.15.0" + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" } }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "requires": { "tweetnacl": "^0.14.3" } @@ -4157,6 +4670,35 @@ "requires": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "bluebird": { @@ -4167,23 +4709,25 @@ "bmp-js": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", - "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==" }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" } }, "brace-expansion": { @@ -4224,7 +4768,7 @@ "buffer-equal": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==" }, "buffer-from": { "version": "1.1.2", @@ -4234,49 +4778,26 @@ "buffer-to-arraybuffer": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + "integrity": "sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==" }, "buffer-to-uint8array": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-to-uint8array/-/buffer-to-uint8array-1.1.0.tgz", - "integrity": "sha1-z29BKHwCL0WNp1LDkcGo1TXsX3I=" + "integrity": "sha512-JVTSbtA6YuOGdu5NL0ffizsBwuwbTXfV7OC91FhazMz9UKP/KlDS+Z7wuiSRClbnTQz52fJgVXI9YDXQRVl2sQ==" }, "busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", "requires": { "dicer": "0.2.5", "readable-stream": "1.1.x" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } } }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "cacheable-lookup": { "version": "5.0.4", @@ -4297,15 +4818,24 @@ "responselike": "^2.0.0" } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, "clip-pixels": { "version": "1.0.1", @@ -4313,22 +4843,22 @@ "integrity": "sha512-nJ22fZvCwkJfMppkOEE7GciLX08rDnVzEJ+U46kBFZtwNzH2V4tNxMWa9Tc365WspCxy1c3NtGJ5EeT4SgjmCA==" }, "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "requires": { "mimic-response": "^1.0.0" } }, "cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "colors": { "version": "1.4.0", @@ -4346,7 +4876,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "concat-stream": { "version": "1.6.2", @@ -4357,6 +4887,35 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "connect-multiparty": { @@ -4371,53 +4930,90 @@ "type-is": "~1.6.16" }, "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "requires": { + "ee-first": "1.1.1" + } + }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" } } }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "requires": { - "safe-buffer": "~5.1.1" - } + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cors": { "version": "2.8.5", @@ -4431,7 +5027,7 @@ "cycle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", "dev": true }, "d": { @@ -4451,7 +5047,7 @@ "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "requires": { "assert-plus": "^1.0.0" } @@ -4479,11 +5075,6 @@ } } }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -4497,12 +5088,12 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "denque": { "version": "1.5.1", @@ -4510,50 +5101,27 @@ "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" }, "dicer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", "requires": { "readable-stream": "1.1.x", "streamsearch": "0.1.2" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } } }, "dotenv": { @@ -4564,20 +5132,49 @@ "dtype": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz", - "integrity": "sha1-zQUjI84GFETs0uj1dI9popvihDQ=" + "integrity": "sha512-s2YVcLKdFGS0hpFqJaTwscsyt0E8nNFdmo73Ocd81xNPj4URI4rj6D60A+vFMIw7BXWlb4yRkEwfBqcZzPGiZg==" }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "requires": { "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -4586,17 +5183,22 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "email-validator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==" }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "end-of-stream": { "version": "1.4.4", @@ -4607,9 +5209,9 @@ } }, "es5-ext": { - "version": "0.10.61", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", - "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", "requires": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", @@ -4619,7 +5221,7 @@ "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "requires": { "d": "1", "es5-ext": "^0.10.35", @@ -4629,7 +5231,7 @@ "es6-map": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "integrity": "sha512-mz3UqCh0uPCIqsw1SSAkB/p0rOzF/M0V++vyN7JqlPtSW/VsYgQBvVvqMLmfBuyMzTpLnNqi6JmcSizs4jy19A==", "requires": { "d": "1", "es5-ext": "~0.10.14", @@ -4640,25 +5242,22 @@ } }, "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.6.tgz", + "integrity": "sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==", "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "es6-iterator": "~2.0.3", + "es6-symbol": "^3.1.3", + "event-emitter": "^0.3.5", + "type": "^2.7.2" }, "dependencies": { - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" } } }, @@ -4685,7 +5284,7 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escodegen": { "version": "1.14.3", @@ -4722,12 +5321,12 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "requires": { "d": "1", "es5-ext": "~0.10.14" @@ -4736,52 +5335,54 @@ "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "express-form-data": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/express-form-data/-/express-form-data-2.0.17.tgz", - "integrity": "sha512-gsF61uGRAzRw4HXWiJ1dzjl1igpRzankTYv1An6uOd0WiySKi7HJ0ng88qaGM3kjZyKsaPcucrMnTLcmXdoVjw==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/express-form-data/-/express-form-data-2.0.19.tgz", + "integrity": "sha512-QWulRIYvZV/ZOuO0+SNpCs9Gl0st9SssYtm5Icfm17p2MU4HASLpd4K5w8fwnXB/lPPskecVSeqjVWi2SwIb1A==", "requires": { "connect-multiparty": "^2.2.0", - "fs-extra": "^9.1.0" + "fs-extra": "^9.1.0", + "signal-exit": "^3.0.7" }, "dependencies": { "fs-extra": { @@ -4812,27 +5413,27 @@ } }, "express-rate-limit": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.3.0.tgz", - "integrity": "sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==" + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", + "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==" }, "express-subdomain": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.5.tgz", - "integrity": "sha1-mQ75eUC39MKCPZWTZIt5voWKY4s=" + "integrity": "sha512-tpYy7MPgDoouxA4r+BnGI43yxYakbSSpQn7MjEYM0ssHeipTM1YiIoK3i4pCAgoXoks22Yb5C4QFkOYBYczZcw==" }, "ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "requires": { - "type": "^2.5.0" + "type": "^2.7.2" }, "dependencies": { "type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" } } }, @@ -4844,12 +5445,12 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" }, "eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", "dev": true }, "fast-deep-equal": { @@ -4865,7 +5466,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "file-type": { "version": "10.11.0", @@ -4873,16 +5474,16 @@ "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==" }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" } }, @@ -4899,10 +5500,18 @@ "resolved": "https://registry.npmjs.org/flip-pixels/-/flip-pixels-1.0.2.tgz", "integrity": "sha512-oXbJGbjDnfJRWPC7Va38EFhd+A8JWE5/hCiKcK8qjCdbLj9DTpsq6MEudwpRTH+V4qq+Jw7d3pUgQdSr3x3mTA==" }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" }, "form-data": { "version": "2.3.3", @@ -4915,19 +5524,19 @@ } }, "formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==" }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs-extra": { "version": "8.1.0", @@ -4940,17 +5549,27 @@ } }, "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "function-bind": { "version": "1.1.1", @@ -4958,30 +5577,41 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "requires": { - "aproba": "^1.0.3", + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" } }, "generic-pool": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", - "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" }, "get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" }, + "get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -4993,35 +5623,43 @@ "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "requires": { "assert-plus": "^1.0.0" } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "requires": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", @@ -5030,14 +5668,14 @@ } }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" }, "har-validator": { "version": "5.1.5", @@ -5056,37 +5694,50 @@ "function-bind": "^1.1.1" } }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, "hcaptcha": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/hcaptcha/-/hcaptcha-0.1.0.tgz", - "integrity": "sha512-mVRkhNcOuP7QJO50nYdu3vS+uaOg6Ku2HpMy50C2EckjB9DlnwX24iePi912IXuVIq5L8ukjISG4Ea6MimZ5+w==" + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/hcaptcha/-/hcaptcha-0.1.1.tgz", + "integrity": "sha512-iMrDmH2VpIEKOrcKWidVjI89FdDKTEdZ7PfPWkP27sTazIIkob8YfdY2ezaufAnWBiUUcvzsn0qF+dyXtBH2Vw==" }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -5102,6 +5753,30 @@ "resolve-alpn": "^1.0.0" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -5115,14 +5790,6 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "requires": { - "minimatch": "^3.0.4" - } - }, "image-pixels": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/image-pixels/-/image-pixels-1.1.1.tgz", @@ -5167,26 +5834,30 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } }, "is-base64": { "version": "0.0.6", @@ -5208,36 +5879,58 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, "is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "requires": { "has": "^1.0.3" } }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "requires": { - "number-is-nan": "^1.0.0" + "has-tostringtag": "^1.0.0" } }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==" }, "is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" }, + "is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "is-url": { "version": "1.2.4", @@ -5247,27 +5940,27 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, "jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" }, "joi": { - "version": "17.6.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.1.tgz", - "integrity": "sha512-Hl7/iBklIX345OCM1TiFSCZRVaAOLDGlWCp0Df2vWYgBgjkezaR7Kvm3joBciBHQjZj5sxXs859r6eqsRSlG8w==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.7.1.tgz", + "integrity": "sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA==", "requires": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", + "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, @@ -5279,7 +5972,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, "json-buffer": { "version": "3.0.1", @@ -5299,12 +5992,12 @@ "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": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "requires": { "graceful-fs": "^4.1.6" } @@ -5331,9 +6024,9 @@ "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" }, "keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", "requires": { "json-buffer": "3.0.1" } @@ -5341,16 +6034,22 @@ "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "lodash.foreach": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==" }, "lodash.get": { "version": "4.4.2", @@ -5367,6 +6066,14 @@ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, "magic-string": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", @@ -5375,10 +6082,25 @@ "sourcemap-codec": "^1.4.1" } }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memory-pager": { "version": "1.5.0", @@ -5389,12 +6111,12 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "merge-source-map": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", - "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", + "integrity": "sha512-PGSmS0kfnTnMJCzJ16BLLCEe6oeYCamKFFdQKshi4BmM6FUwipjVOcBFGxqtQtirtAG4iZvHlqST9CpZKqlRjA==", "requires": { "source-map": "^0.5.6" }, @@ -5402,14 +6124,14 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" } } }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "mii-js": { "version": "git+ssh://git@github.com/PretendoNetwork/mii-js.git#5d8eb8013514a13b0df6eb4a5bfd8b5a63fb9861", @@ -5424,16 +6146,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.42.0" + "mime-db": "1.52.0" } }, "mimic-response": { @@ -5442,52 +6164,59 @@ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", + "integrity": "sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==" }, "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "requires": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } } }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "requires": { - "minimist": "^1.2.5" + "minimist": "^1.2.6" } }, "moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "moment-timezone": { - "version": "0.5.27", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz", - "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==", + "version": "0.5.40", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz", + "integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==", "requires": { "moment": ">= 2.9.0" } @@ -5516,9 +6245,9 @@ } }, "mongoose": { - "version": "5.13.13", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.13.tgz", - "integrity": "sha512-M55tpCr/p5i6vdJ54nm4MG6/7SKV4JqlWnqbx6yCRuAuW05CZ7u+gNuHVPQVF9dZ59ALXjOtPEUl+OXklAa7ng==", + "version": "5.13.15", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz", + "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==", "requires": { "@types/bson": "1.x || 4.0.x", "@types/mongodb": "^3.5.27", @@ -5540,18 +6269,14 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "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==" } } }, "mongoose-legacy-pluralize": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "requires": {} }, "mongoose-unique-validator": { "version": "2.0.3", @@ -5563,15 +6288,25 @@ } }, "morgan": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", - "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", "requires": { - "basic-auth": "~2.0.0", + "basic-auth": "~2.0.1", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "~2.0.0", "on-finished": "~2.3.0", - "on-headers": "~1.0.1" + "on-headers": "~1.0.2" + }, + "dependencies": { + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "requires": { + "ee-first": "1.1.1" + } + } } }, "mpath": { @@ -5598,18 +6333,23 @@ "requires": { "ms": "2.0.0" } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "multer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", - "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", "requires": { "append-field": "^1.0.0", "busboy": "^0.2.11", @@ -5622,41 +6362,36 @@ } }, "multiparty": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.2.tgz", - "integrity": "sha512-NtZLjlvsjcoGrzojtwQwn/Tm90aWJ6XXtPppYF4WmOk/6ncdwMMKggFY2NlRRN9yiCEIVxpOfPWahVEG2HAG8Q==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", + "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", "requires": { - "http-errors": "~1.8.0", + "http-errors": "~1.8.1", "safe-buffer": "5.2.1", "uid-safe": "2.1.5" }, "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, "http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "requires": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" } }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "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==" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" } } }, @@ -5666,35 +6401,10 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "needle": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", - "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "next-tick": { "version": "1.1.0", @@ -5702,48 +6412,38 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, "node-addon-api": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", - "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==" - }, - "node-pre-gyp": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", - "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.3", - "needle": "^2.5.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "requires": { + "whatwg-url": "^5.0.0" } }, "node-rsa": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.0.7.tgz", - "integrity": "sha512-idwRXma6scFufZmbaKkHpJoLL93yynRefP6yur13wZ5i9FR35ex451KCoF2OORDeJanyRVahmjjiwmUlCnTqJA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", + "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", "dev": true, "requires": { "asn1": "^0.2.4" } }, "nodemailer": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.3.tgz", - "integrity": "sha512-faZFufgTMrphYoDjvyVpbpJcYzwyFnbAMmQtj1lVBYAUSm3SOy2fIdd9+Mr4UxPosBa0JRw9bJoIwQn+nswiew==" + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz", + "integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==" }, "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1" } }, "normalize-url": { @@ -5751,45 +6451,17 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -5798,12 +6470,12 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" }, "omggif": { "version": "1.0.10", @@ -5811,9 +6483,9 @@ "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -5826,7 +6498,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } @@ -5849,25 +6521,6 @@ "word-wrap": "~1.2.3" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -5889,7 +6542,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-parse": { "version": "1.0.7", @@ -5899,17 +6552,17 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "pick-by-alias": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pick-by-alias/-/pick-by-alias-1.2.0.tgz", - "integrity": "sha1-X3yysfIabh6ISgyHhVqko3NhEHs=" + "integrity": "sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw==" }, "pngjs": { "version": "3.4.0", @@ -5919,7 +6572,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" }, "primitive-pool": { "version": "1.1.0", @@ -5945,18 +6598,18 @@ } }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" } }, "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, "pump": { "version": "3.0.0", @@ -5968,19 +6621,22 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" }, "quick-lru": { "version": "5.1.1", @@ -5990,7 +6646,7 @@ "quote-stream": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", - "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", + "integrity": "sha512-kKr2uQ2AokadPjvTyKJQad9xELbZwYzWlNfI3Uz2j/ib5u6H9lDP7fUUR//rMycd0gv4Z5P1qXMfXR8YpIxrjQ==", "requires": { "buffer-equal": "0.0.1", "minimist": "^1.1.3", @@ -6000,7 +6656,7 @@ "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" }, "range-parser": { "version": "1.2.1", @@ -6008,61 +6664,54 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", "dev": true, "requires": { "mute-stream": "~0.0.4" } }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "requires": { "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + } } }, "redis": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.3.1.tgz", - "integrity": "sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA==", + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.4.tgz", + "integrity": "sha512-wi2tgDdQ+Q8q+PR5FLRx4QvDiWaA+PoJbrzsyFqlClN5R4LplHqN3scs/aGjE//mbz++W19SgxiEnQ27jnCRaA==", "requires": { - "@redis/bloom": "1.0.2", - "@redis/client": "1.3.0", - "@redis/graph": "1.0.1", + "@redis/bloom": "1.2.0", + "@redis/client": "1.5.5", + "@redis/graph": "1.1.0", "@redis/json": "1.0.4", - "@redis/search": "1.1.0", - "@redis/time-series": "1.0.3" + "@redis/search": "1.1.1", + "@redis/time-series": "1.0.4" } }, "regexp-clone": { @@ -6098,9 +6747,14 @@ }, "dependencies": { "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" } } }, @@ -6110,46 +6764,51 @@ "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" }, "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "requires": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-alpn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.0.tgz", - "integrity": "sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "responselike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", - "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", "requires": { "lowercase-keys": "^2.0.0" } }, + "restructure": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", + "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" + }, "revalidator": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", + "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", "dev": true }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -6166,9 +6825,9 @@ } }, "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, "scope-analyzer": { "version": "2.1.2", @@ -6185,62 +6844,75 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "requires": { + "lru-cache": "^6.0.0" + } }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" } }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "shallow-copy": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + "integrity": "sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } }, "sift": { "version": "13.5.2", @@ -6248,14 +6920,14 @@ "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "sliced": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" }, "source-map": { "version": "0.6.1", @@ -6271,16 +6943,16 @@ "sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "optional": true, "requires": { "memory-pager": "^1.0.2" } }, "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -6296,7 +6968,7 @@ "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", "dev": true }, "static-eval": { @@ -6326,25 +6998,51 @@ "shallow-copy": "~0.0.1", "static-eval": "^2.0.5", "through2": "~2.0.3" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "streamsearch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==" }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, "string-to-arraybuffer": { "version": "1.0.2", @@ -6363,60 +7061,55 @@ } }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "requires": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, - "dependencies": { - "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==" + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^4.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" } } }, "tga": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tga/-/tga-1.0.4.tgz", - "integrity": "sha512-UdYjLm6XDhH0czfel87opaoynxIWI6AXMLkaUvZyl8AzJnAvOH1bHmHjdcolTzi4RjbBU8rgd7ys7sHxFAY1WA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tga/-/tga-1.0.7.tgz", + "integrity": "sha512-GFVJwov5aJTMgh8U1QfaRheIELXo+dYc1qYIvQEIqZX4n+S6Fj/SDWsdbelHt7WP08xOR6W1z5aJQ+Ilh5gIeA==", "requires": { - "debug": "^2.6.1" + "debug": "^2.6.1", + "restructure": "^2.0.0" } }, "through2": { @@ -6426,6 +7119,35 @@ "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "to-array-buffer": { @@ -6439,9 +7161,9 @@ } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "tough-cookie": { "version": "2.5.0", @@ -6452,10 +7174,15 @@ "punycode": "^2.1.1" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "requires": { "safe-buffer": "^5.0.1" } @@ -6463,7 +7190,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, "type": { "version": "1.2.0", @@ -6473,7 +7200,7 @@ "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "requires": { "prelude-ls": "~1.1.2" } @@ -6490,7 +7217,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "uid-safe": { "version": "2.1.5", @@ -6508,7 +7235,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "uri-js": { "version": "4.4.1", @@ -6521,7 +7248,7 @@ "url": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", "requires": { "punycode": "1.3.2", "querystring": "0.2.0" @@ -6530,60 +7257,106 @@ "punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" } } }, + "util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==" }, "validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", + "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==" }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + } + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" } }, "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "requires": { - "string-width": "^1.0.2 || 2" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "winston": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", - "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==", + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", + "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", "dev": true, "requires": { - "async": "^3.2.3", + "async": "^2.6.4", "colors": "1.0.x", "cycle": "1.0.x", "eyes": "0.1.x", @@ -6591,10 +7364,19 @@ "stack-trace": "0.0.x" }, "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, "colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", "dev": true } } @@ -6607,7 +7389,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "xml2js": { "version": "0.4.19", @@ -6621,7 +7403,7 @@ "xmlbuilder": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==" } } }, @@ -6646,9 +7428,9 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yesno": { "version": "0.4.0", From 0201347e26ad23646b0aaa9fd70c5b458b6859ae Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Feb 2023 09:22:41 -0500 Subject: [PATCH 101/105] Removed extra line break in NASC --- src/services/nasc/routes/ac.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/nasc/routes/ac.js b/src/services/nasc/routes/ac.js index 41b7296..66d08d4 100644 --- a/src/services/nasc/routes/ac.js +++ b/src/services/nasc/routes/ac.js @@ -28,7 +28,6 @@ router.post('/', async (request, response) => { response.status(200).send(responseData.toString()); }); - /** * * @param {express.Request} request From 37caa67851288fa627511857195cb3896e9c45a4 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Feb 2023 09:23:53 -0500 Subject: [PATCH 102/105] Updated cdn config in manager --- src/config-manager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config-manager.js b/src/config-manager.js index c141b8a..6376355 100644 --- a/src/config-manager.js +++ b/src/config-manager.js @@ -108,9 +108,9 @@ function configure() { secret: process.env.PN_ACT_CONFIG_HCAPTCHA_SECRET }, cdn: { - subdomain: process.env.PN_ACT_CONFIG_CDN_BASE, - disk_path: process.env.PN_ACT_CONFIG_CDN_BASE, - base_url: process.env.PN_ACT_CONFIG_CDN_BASE + subdomain: process.env.PN_ACT_CONFIG_CDN_SUBDOMAIN, + disk_path: process.env.PN_ACT_CONFIG_CDN_DISK_PATH, + base_url: process.env.PN_ACT_CONFIG_CDN_BASE_URL }, website_base: process.env.PN_ACT_CONFIG_WEBSITE_BASE }; From 4868596b71a3ae44882f7b64f8bb2d2757b3070d Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Feb 2023 09:25:12 -0500 Subject: [PATCH 103/105] Set memory cache default to null when not using redis --- src/cache.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cache.js b/src/cache.js index e889483..6cd89e2 100644 --- a/src/cache.js +++ b/src/cache.js @@ -30,7 +30,7 @@ async function getCachedFile(fileName, encoding) { let cachedFile; if (disabledFeatures.redis) { - cachedFile = memoryCache[fileName]; + cachedFile = memoryCache[fileName] || null; } else { cachedFile = await client.get(fileName); } From 314833e3b376c60b61d592a34703c75a2cc6d2c2 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Feb 2023 09:34:48 -0500 Subject: [PATCH 104/105] Added start of the README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..80fc5d8 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Account server + +## What is this? +The account server is a replacement for several account-based services used by the WiiU and 3DS. It replaces the NNID api as well as NASC for the 3DS. It also contains a dedicated PNID api service for getting details of PNIDs outside of the consoles + +## Setup +TODO \ No newline at end of file From 3954d7588b0605d6e3e67737223ab2448d85c020 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 15 Feb 2023 16:26:15 -0500 Subject: [PATCH 105/105] Ignore case in getUserByEmailAddress --- src/database.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database.js b/src/database.js index 7df830e..bfce6ef 100644 --- a/src/database.js +++ b/src/database.js @@ -58,7 +58,7 @@ async function getUserByEmailAddress(email) { verifyConnected(); const user = await PNID.findOne({ - 'email.address': email.toLowerCase() + 'email.address': new RegExp(email, 'i') // * Ignore case }); return user;