From 2680efa34b4360f454d2807b55bcdcd0744d4328 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Tue, 24 Aug 2021 16:35:20 +0200 Subject: :construction: gateway --- gateway/src/listener/listener.ts | 10 +++--- gateway/src/opcodes/Identify.ts | 43 +++++++---------------- gateway/src/opcodes/LazyRequest.ts | 70 ++++++++++++++++++-------------------- 3 files changed, 52 insertions(+), 71 deletions(-) (limited to 'gateway/src') diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index 51082586..633580e3 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -1,10 +1,10 @@ import { db, Event, - UserModel, + User, getPermission, Permissions, - ChannelModel, + Channel, RabbitMQ, EVENT, listenEvent, @@ -27,11 +27,11 @@ import { Channel } from "amqplib"; // TODO: use already queried guilds/channels of Identify and don't fetch them again export async function setupListener(this: WebSocket) { - const user = await UserModel.findOne({ id: this.user_id }, { guilds: true }).exec(); - const channels = await ChannelModel.find( + const user = await User.findOneOrFail({ id: this.user_id }, { guilds: true }); + const channels = await Channel.find( { $or: [{ recipient_ids: this.user_id }, { guild_id: { $in: user.guilds } }] }, { id: true, permission_overwrites: true } - ).exec(); + ); const dm_channels = channels.filter((x) => !x.guild_id); const guild_channels = channels.filter((x) => x.guild_id); diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index 91f7f675..464d584c 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -1,18 +1,6 @@ import { CLOSECODES, Payload, OPCODES } from "../util/Constants"; import WebSocket from "../util/WebSocket"; -import { - ChannelModel, - checkToken, - GuildModel, - Intents, - MemberDocument, - MemberModel, - ReadyEventData, - UserModel, - toObject, - EVENTEnum, - Config, -} from "@fosscord/util"; +import { Channel, checkToken, Guild, Intents, Member, ReadyEventData, User, EVENTEnum, Config } from "@fosscord/util"; import { setupListener } from "../listener/listener"; import { IdentifySchema } from "../schema/Identify"; import { Send } from "../util/Send"; @@ -54,7 +42,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { } } - const members = toObject(await MemberModel.find({ id: this.user_id }).exec()); + const members = await Member.find({ id: this.user_id }); const merged_members = members.map((x: any) => { const y = { ...x, user_id: x.id }; delete y.settings; @@ -63,8 +51,8 @@ export async function onIdentify(this: WebSocket, data: Payload) { }) as MemberDocument[][]; const user_guild_settings_entries = members.map((x) => x.settings); - const channels = await ChannelModel.find({ recipient_ids: this.user_id }).exec(); - const user = await UserModel.findOne({ id: this.user_id }).exec(); + const channels = await Channel.find({ recipient_ids: this.user_id }); + const user = await User.findOneOrFail({ id: this.user_id }); if (!user) return this.close(CLOSECODES.Authentication_failed); const public_user = { @@ -76,10 +64,10 @@ export async function onIdentify(this: WebSocket, data: Payload) { bot: user.bot, }; - const guilds = await GuildModel.find({ id: { $in: user.guilds } }) - .populate({ path: "joined_at", match: { id: this.user_id } }) - .exec(); - + const guilds = await Guild.find({ id: { $in: user.guilds } }).populate({ + path: "joined_at", + match: { id: this.user_id }, + }); const privateUser = { avatar: user.avatar, mobile: user.mobile, @@ -104,9 +92,9 @@ export async function onIdentify(this: WebSocket, data: Payload) { const d: ReadyEventData = { v: 8, user: privateUser, - user_settings: user.user_settings, + user_settings: user.settings, // @ts-ignore - guilds: toObject(guilds).map((x) => { + guilds: guilds.map((x) => { // @ts-ignore x.guild_hashes = { channels: { omitted: false, hash: "y4PV2fZ0gmo" }, @@ -131,7 +119,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { version: 642, }, // @ts-ignore - private_channels: toObject(channels).map((x: ChannelDocument) => { + private_channels: channels.map((x): ChannelDocument => { x.recipient_ids = x.recipients.map((y: any) => y.id); delete x.recipients; return x; @@ -144,17 +132,12 @@ export async function onIdentify(this: WebSocket, data: Payload) { consented: false, // TODO }, }, - country_code: user.user_settings.locale, + country_code: user.settings.locale, friend_suggestion_count: 0, // TODO // @ts-ignore experiments: experiments, // TODO guild_join_requests: [], // TODO what is this? - users: [ - public_user, - ...toObject(channels) - .map((x: any) => x.recipients) - .flat(), - ].unique(), // TODO + users: [public_user, ...channels.map((x: any) => x.recipients).flat()].unique(), // TODO merged_members: merged_members, // shard // TODO: only for bots sharding // application // TODO for applications diff --git a/gateway/src/opcodes/LazyRequest.ts b/gateway/src/opcodes/LazyRequest.ts index 63075e5a..9f514f5f 100644 --- a/gateway/src/opcodes/LazyRequest.ts +++ b/gateway/src/opcodes/LazyRequest.ts @@ -18,45 +18,43 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) { permissions.hasThrow("VIEW_CHANNEL"); // MongoDB query to retrieve all hoisted roles and join them with the members and users collection - const roles = toObject( - await db - .collection("roles") - .aggregate([ - { - $match: { - guild_id, - // hoist: true // TODO: also match @everyone role - }, + const roles = await db + .collection("roles") + .aggregate([ + { + $match: { + guild_id, + // hoist: true // TODO: also match @everyone role }, - { $sort: { position: 1 } }, - { - $lookup: { - from: "members", - let: { id: "$id" }, - pipeline: [ - { $match: { $expr: { $in: ["$$id", "$roles"] } } }, - { $limit: 100 }, - { - $lookup: { - from: "users", - let: { user_id: "$id" }, - pipeline: [ - { $match: { $expr: { $eq: ["$id", "$$user_id"] } } }, - { $project: PublicUserProjection }, - ], - as: "user", - }, - }, - { - $unwind: "$user", + }, + { $sort: { position: 1 } }, + { + $lookup: { + from: "members", + let: { id: "$id" }, + pipeline: [ + { $match: { $expr: { $in: ["$$id", "$roles"] } } }, + { $limit: 100 }, + { + $lookup: { + from: "users", + let: { user_id: "$id" }, + pipeline: [ + { $match: { $expr: { $eq: ["$id", "$$user_id"] } } }, + { $project: PublicUserProjection }, + ], + as: "user", }, - ], - as: "members", - }, + }, + { + $unwind: "$user", + }, + ], + as: "members", }, - ]) - .toArray() - ); + }, + ]) + .toArray(); const groups = roles.map((x) => ({ id: x.id === guild_id ? "online" : x.id, count: x.members.length })); const member_count = roles.reduce((a, b) => b.members.length + a, 0); -- cgit 1.5.1 From 845e77eed21d5e03994978ddee0ca0c613234b3f Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 27 Aug 2021 11:11:16 +0200 Subject: :construction: typeorm --- gateway/src/opcodes/Identify.ts | 2 +- util/package-lock.json | 845 +++++++++++++++++++++++++++++- util/package.json | 1 + util/patches/test-performance+1.1.3.patch | 381 -------------- util/src/entities/BaseClass.ts | 17 +- util/src/entities/Config.ts | 2 +- util/src/entities/ReadState.ts | 4 + util/src/entities/Template.ts | 7 +- util/src/entities/User.ts | 4 +- util/src/entities/schema.json | 543 ++++++++++++++++++- util/src/util/Config.ts | 19 + util/src/util/Database.ts | 14 +- util/src/util/checkToken.ts | 7 +- util/src/util/index.ts | 10 +- util/src/util/toBigInt.ts | 4 - util/tests/User.test.js | 31 ++ util/tests/validate.test.js | 16 +- util/util/Config.ts | 290 ---------- 18 files changed, 1465 insertions(+), 732 deletions(-) delete mode 100644 util/patches/test-performance+1.1.3.patch create mode 100644 util/src/util/Config.ts delete mode 100644 util/src/util/toBigInt.ts create mode 100644 util/tests/User.test.js delete mode 100644 util/util/Config.ts (limited to 'gateway/src') diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index 464d584c..644d0984 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -106,7 +106,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { }), guild_experiments: [], // TODO geo_ordered_rtc_regions: [], // TODO - relationships: user.user_data.relationships, + relationships: user.data.relationships, read_state: { // TODO entries: [], diff --git a/util/package-lock.json b/util/package-lock.json index 0ecdaea9..f30fcf47 100644 --- a/util/package-lock.json +++ b/util/package-lock.json @@ -16,6 +16,7 @@ "dot-prop": "^6.0.1", "env-paths": "^2.2.1", "jsonwebtoken": "^8.5.1", + "lambert-server": "^1.2.8", "missing-native-js-functions": "^1.2.10", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", @@ -1256,6 +1257,18 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "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==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -1413,6 +1426,11 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, "node_modules/asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -1594,6 +1612,34 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "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==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1719,6 +1765,14 @@ "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -1933,6 +1987,30 @@ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, + "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==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/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/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==", + "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", @@ -1948,6 +2026,19 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -2066,6 +2157,19 @@ "node": ">=0.10" } }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -2134,6 +2238,11 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, "node_modules/electron-to-chromium": { "version": "1.3.814", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.814.tgz", @@ -2157,6 +2266,14 @@ "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=", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -2225,6 +2342,11 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -2255,6 +2377,14 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -2264,6 +2394,67 @@ "node": ">= 0.8.0" } }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.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", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-async-errors": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", + "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==", + "peerDependencies": { + "express": "^4.16.2" + } + }, + "node_modules/express/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/express/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/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2324,6 +2515,23 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/find-yarn-workspace-root": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", @@ -2366,6 +2574,22 @@ "node": ">= 6" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -2706,6 +2930,14 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "node_modules/helmet": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz", + "integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -2720,6 +2952,26 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "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==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, "node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -2899,6 +3151,14 @@ "node": ">= 0.4" } }, + "node_modules/ipaddr.js": { + "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-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -5837,6 +6097,19 @@ "node": ">=6" } }, + "node_modules/lambert-server": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.8.tgz", + "integrity": "sha512-vi/Ku/QudY+WIdGO9bc0qLfVhfuJFWXk1+etesPW1vW29sPbmevLL6IwfvCtw+/MyzRAJLOyCBfQ310a68+2QQ==", + "dependencies": { + "body-parser": "^1.19.0", + "chalk": "^4.1.1", + "express": "^4.17.1", + "express-async-errors": "^3.1.1", + "helmet": "^4.4.1", + "missing-native-js-functions": "^1.1.8" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -5937,6 +6210,14 @@ "tmpl": "1.0.x" } }, + "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=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", @@ -5944,12 +6225,25 @@ "optional": true, "peer": true }, + "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=" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", @@ -5962,11 +6256,21 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.49.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", - "devOptional": true, "engines": { "node": ">= 0.6" } @@ -5975,7 +6279,6 @@ "version": "2.1.32", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", - "devOptional": true, "dependencies": { "mime-db": "1.49.0" }, @@ -6131,6 +6434,14 @@ "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==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -6477,6 +6788,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -6620,6 +6942,14 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/patch-package": { "version": "6.4.7", "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.4.7.tgz", @@ -6724,6 +7054,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "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=" + }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -6841,6 +7176,18 @@ "node": ">= 6" } }, + "node_modules/proxy-addr": { + "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.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", @@ -6869,6 +7216,28 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -7082,11 +7451,58 @@ "semver": "bin/semver" } }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "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==" + }, + "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==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "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=" }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -7240,6 +7656,14 @@ "node": ">=0.10.0" } }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -7445,6 +7869,14 @@ "node": ">=8.0" } }, + "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" + } + }, "node_modules/tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -7514,6 +7946,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -7746,6 +8190,14 @@ "node": ">= 4.0.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -7786,6 +8238,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -7827,6 +8287,14 @@ "node": ">= 0.10" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -9140,6 +9608,15 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "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==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -9271,6 +9748,11 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -9427,6 +9909,30 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -9524,6 +10030,11 @@ "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -9695,6 +10206,26 @@ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "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==" + } + } + }, + "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==" + }, "convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", @@ -9712,6 +10243,16 @@ } } }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -9809,6 +10350,16 @@ "optional": true, "peer": true }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -9856,6 +10407,11 @@ "safe-buffer": "^5.0.1" } }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, "electron-to-chromium": { "version": "1.3.814", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.814.tgz", @@ -9873,6 +10429,11 @@ "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=" + }, "env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -9923,6 +10484,11 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -9940,12 +10506,72 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.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", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "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==" + } + } + }, + "express-async-errors": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", + "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==", + "requires": {} + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -9997,6 +10623,20 @@ "to-regex-range": "^5.0.1" } }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, "find-yarn-workspace-root": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", @@ -10033,6 +10673,16 @@ "mime-types": "^2.1.12" } }, + "forwarded": { + "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=" + }, "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -10301,6 +10951,11 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "helmet": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz", + "integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg==" + }, "highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -10312,6 +10967,25 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "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==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, "http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -10443,6 +11117,11 @@ "side-channel": "^1.0.4" } }, + "ipaddr.js": { + "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-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -12693,6 +13372,19 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "lambert-server": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.8.tgz", + "integrity": "sha512-vi/Ku/QudY+WIdGO9bc0qLfVhfuJFWXk1+etesPW1vW29sPbmevLL6IwfvCtw+/MyzRAJLOyCBfQ310a68+2QQ==", + "requires": { + "body-parser": "^1.19.0", + "chalk": "^4.1.1", + "express": "^4.17.1", + "express-async-errors": "^3.1.1", + "helmet": "^4.4.1", + "missing-native-js-functions": "^1.1.8" + } + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -12786,6 +13478,11 @@ "tmpl": "1.0.x" } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, "memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", @@ -12793,12 +13490,22 @@ "optional": true, "peer": true }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, "micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", @@ -12808,17 +13515,20 @@ "picomatch": "^2.2.3" } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, "mime-db": { "version": "1.49.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", - "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", - "devOptional": true + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==" }, "mime-types": { "version": "2.1.32", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", - "devOptional": true, "requires": { "mime-db": "1.49.0" } @@ -12930,6 +13640,11 @@ } } }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -13206,6 +13921,14 @@ "es-abstract": "^1.18.0-next.2" } }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -13315,6 +14038,11 @@ } } }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, "patch-package": { "version": "6.4.7", "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.4.7.tgz", @@ -13397,6 +14125,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "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=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -13489,6 +14222,15 @@ "sisteransi": "^1.0.5" } }, + "proxy-addr": { + "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.2.0", + "ipaddr.js": "1.9.1" + } + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -13511,6 +14253,22 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "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==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "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", @@ -13675,11 +14433,54 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "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==" + } + } + }, + "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==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, "sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -13796,6 +14597,11 @@ "tweetnacl": "~0.14.0" } }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -13954,6 +14760,11 @@ "is-number": "^7.0.0" } }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -14005,6 +14816,15 @@ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -14125,6 +14945,11 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -14162,6 +14987,11 @@ "object.getownpropertydescriptors": "^2.1.1" } }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -14192,6 +15022,11 @@ "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz", "integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg==" }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", diff --git a/util/package.json b/util/package.json index a132a99c..fc474d68 100644 --- a/util/package.json +++ b/util/package.json @@ -44,6 +44,7 @@ "dot-prop": "^6.0.1", "env-paths": "^2.2.1", "jsonwebtoken": "^8.5.1", + "lambert-server": "^1.2.8", "missing-native-js-functions": "^1.2.10", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", diff --git a/util/patches/test-performance+1.1.3.patch b/util/patches/test-performance+1.1.3.patch deleted file mode 100644 index 23b4900b..00000000 --- a/util/patches/test-performance+1.1.3.patch +++ /dev/null @@ -1,381 +0,0 @@ -diff --git a/node_modules/test-performance/cjs/index.js b/node_modules/test-performance/cjs/index.js -index 65d5904..04638a1 100644 ---- a/node_modules/test-performance/cjs/index.js -+++ b/node_modules/test-performance/cjs/index.js -@@ -1,4 +1,4 @@ --'use strict'; -+"use strict"; - - /*! ***************************************************************************** - Copyright (c) Microsoft Corporation. -@@ -15,50 +15,139 @@ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */ - -+const { performance } = require("perf_hooks"); -+ - function __awaiter(thisArg, _arguments, P, generator) { -- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } -- return new (P || (P = Promise))(function (resolve, reject) { -- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } -- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } -- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } -- step((generator = generator.apply(thisArg, _arguments || [])).next()); -- }); -+ function adopt(value) { -+ return value instanceof P -+ ? value -+ : new P(function (resolve) { -+ resolve(value); -+ }); -+ } -+ return new (P || (P = Promise))(function (resolve, reject) { -+ function fulfilled(value) { -+ try { -+ step(generator.next(value)); -+ } catch (e) { -+ reject(e); -+ } -+ } -+ function rejected(value) { -+ try { -+ step(generator["throw"](value)); -+ } catch (e) { -+ reject(e); -+ } -+ } -+ function step(result) { -+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); -+ } -+ step((generator = generator.apply(thisArg, _arguments || [])).next()); -+ }); - } - - function __generator(thisArg, body) { -- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; -- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; -- function verb(n) { return function (v) { return step([n, v]); }; } -- function step(op) { -- if (f) throw new TypeError("Generator is already executing."); -- while (_) try { -- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; -- if (y = 0, t) op = [op[0] & 2, t.value]; -- switch (op[0]) { -- case 0: case 1: t = op; break; -- case 4: _.label++; return { value: op[1], done: false }; -- case 5: _.label++; y = op[1]; op = [0]; continue; -- case 7: op = _.ops.pop(); _.trys.pop(); continue; -- default: -- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } -- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } -- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } -- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } -- if (t[2]) _.ops.pop(); -- _.trys.pop(); continue; -- } -- op = body.call(thisArg, _); -- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } -- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; -- } -+ var _ = { -+ label: 0, -+ sent: function () { -+ if (t[0] & 1) throw t[1]; -+ return t[1]; -+ }, -+ trys: [], -+ ops: [], -+ }, -+ f, -+ y, -+ t, -+ g; -+ return ( -+ (g = { next: verb(0), throw: verb(1), return: verb(2) }), -+ typeof Symbol === "function" && -+ (g[Symbol.iterator] = function () { -+ return this; -+ }), -+ g -+ ); -+ function verb(n) { -+ return function (v) { -+ return step([n, v]); -+ }; -+ } -+ function step(op) { -+ if (f) throw new TypeError("Generator is already executing."); -+ while (_) -+ try { -+ if ( -+ ((f = 1), -+ y && -+ (t = -+ op[0] & 2 -+ ? y["return"] -+ : op[0] -+ ? y["throw"] || ((t = y["return"]) && t.call(y), 0) -+ : y.next) && -+ !(t = t.call(y, op[1])).done) -+ ) -+ return t; -+ if (((y = 0), t)) op = [op[0] & 2, t.value]; -+ switch (op[0]) { -+ case 0: -+ case 1: -+ t = op; -+ break; -+ case 4: -+ _.label++; -+ return { value: op[1], done: false }; -+ case 5: -+ _.label++; -+ y = op[1]; -+ op = [0]; -+ continue; -+ case 7: -+ op = _.ops.pop(); -+ _.trys.pop(); -+ continue; -+ default: -+ if (!((t = _.trys), (t = t.length > 0 && t[t.length - 1])) && (op[0] === 6 || op[0] === 2)) { -+ _ = 0; -+ continue; -+ } -+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { -+ _.label = op[1]; -+ break; -+ } -+ if (op[0] === 6 && _.label < t[1]) { -+ _.label = t[1]; -+ t = op; -+ break; -+ } -+ if (t && _.label < t[2]) { -+ _.label = t[2]; -+ _.ops.push(op); -+ break; -+ } -+ if (t[2]) _.ops.pop(); -+ _.trys.pop(); -+ continue; -+ } -+ op = body.call(thisArg, _); -+ } catch (e) { -+ op = [6, e]; -+ y = 0; -+ } finally { -+ f = t = 0; -+ } -+ if (op[0] & 5) throw op[1]; -+ return { value: op[0] ? op[1] : void 0, done: true }; -+ } - } - - var baselineFunctions = { -- standard: { -- expectedMsRunTime: 12, -- func: function (dummyParam) { -- }, -- }, -+ standard: { -+ expectedMsRunTime: 12, -+ func: function (dummyParam) {}, -+ }, - }; - - /** -@@ -66,28 +155,28 @@ var baselineFunctions = { - * to a baseline. - */ - function calculateExpectedPerformance(baselineExpected, baselineActual, target) { -- var performanceRatio = baselineActual / baselineExpected; -- return target / performanceRatio; -+ var performanceRatio = baselineActual / baselineExpected; -+ return target / performanceRatio; - } - - /** - * This runs a single performance test of a function - */ - function perfTest(func) { -- return __awaiter(this, void 0, void 0, function () { -- var start, end; -- return __generator(this, function (_a) { -- switch (_a.label) { -- case 0: -- start = performance.now(); -- return [4 /*yield*/, func()]; -- case 1: -- _a.sent(); -- end = performance.now(); -- return [2 /*return*/, end - start]; -- } -- }); -- }); -+ return __awaiter(this, void 0, void 0, function () { -+ var start, end; -+ return __generator(this, function (_a) { -+ switch (_a.label) { -+ case 0: -+ start = performance.now(); -+ return [4 /*yield*/, func()]; -+ case 1: -+ _a.sent(); -+ end = performance.now(); -+ return [2 /*return*/, end - start]; -+ } -+ }); -+ }); - } - - var NUMBER_OF_TESTS = 10000; -@@ -96,22 +185,31 @@ var NUMBER_OF_TESTS = 10000; - * the average in milliseconds. - */ - function getScore(func) { -- return __awaiter(this, void 0, void 0, function () { -- var tests, results; -- var _this = this; -- return __generator(this, function (_a) { -- switch (_a.label) { -- case 0: -- tests = new Array(NUMBER_OF_TESTS).fill(undefined).map(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { -- return [2 /*return*/, perfTest(func)]; -- }); }); }); -- return [4 /*yield*/, Promise.all(tests)]; -- case 1: -- results = _a.sent(); -- return [2 /*return*/, results.reduce(function (acc, val) { return acc + val; }, 0) / NUMBER_OF_TESTS]; -- } -- }); -- }); -+ return __awaiter(this, void 0, void 0, function () { -+ var tests, results; -+ var _this = this; -+ return __generator(this, function (_a) { -+ switch (_a.label) { -+ case 0: -+ tests = new Array(NUMBER_OF_TESTS).fill(undefined).map(function () { -+ return __awaiter(_this, void 0, void 0, function () { -+ return __generator(this, function (_a) { -+ return [2 /*return*/, perfTest(func)]; -+ }); -+ }); -+ }); -+ return [4 /*yield*/, Promise.all(tests)]; -+ case 1: -+ results = _a.sent(); -+ return [ -+ 2 /*return*/, -+ results.reduce(function (acc, val) { -+ return acc + val; -+ }, 0) / NUMBER_OF_TESTS, -+ ]; -+ } -+ }); -+ }); - } - - /** -@@ -119,31 +217,38 @@ function getScore(func) { - * known baseline function. - */ - function runTests(baselineFunc, targetFunc) { -- return __awaiter(this, void 0, void 0, function () { -- var initialBaselineScore, initialTargetScore, midwayBaselineScore, endTargetScore, endBaselineScore, totalBaselineScore, totalTargetScore; -- return __generator(this, function (_a) { -- switch (_a.label) { -- case 0: return [4 /*yield*/, getScore(baselineFunc)]; -- case 1: -- initialBaselineScore = _a.sent(); -- return [4 /*yield*/, getScore(targetFunc)]; -- case 2: -- initialTargetScore = _a.sent(); -- return [4 /*yield*/, getScore(baselineFunc)]; -- case 3: -- midwayBaselineScore = _a.sent(); -- return [4 /*yield*/, getScore(targetFunc)]; -- case 4: -- endTargetScore = _a.sent(); -- return [4 /*yield*/, getScore(baselineFunc)]; -- case 5: -- endBaselineScore = _a.sent(); -- totalBaselineScore = (initialBaselineScore + midwayBaselineScore + endBaselineScore) / 3; -- totalTargetScore = (initialTargetScore + endTargetScore) / 2; -- return [2 /*return*/, [totalBaselineScore, totalTargetScore]]; -- } -- }); -- }); -+ return __awaiter(this, void 0, void 0, function () { -+ var initialBaselineScore, -+ initialTargetScore, -+ midwayBaselineScore, -+ endTargetScore, -+ endBaselineScore, -+ totalBaselineScore, -+ totalTargetScore; -+ return __generator(this, function (_a) { -+ switch (_a.label) { -+ case 0: -+ return [4 /*yield*/, getScore(baselineFunc)]; -+ case 1: -+ initialBaselineScore = _a.sent(); -+ return [4 /*yield*/, getScore(targetFunc)]; -+ case 2: -+ initialTargetScore = _a.sent(); -+ return [4 /*yield*/, getScore(baselineFunc)]; -+ case 3: -+ midwayBaselineScore = _a.sent(); -+ return [4 /*yield*/, getScore(targetFunc)]; -+ case 4: -+ endTargetScore = _a.sent(); -+ return [4 /*yield*/, getScore(baselineFunc)]; -+ case 5: -+ endBaselineScore = _a.sent(); -+ totalBaselineScore = (initialBaselineScore + midwayBaselineScore + endBaselineScore) / 3; -+ totalTargetScore = (initialTargetScore + endTargetScore) / 2; -+ return [2 /*return*/, [totalBaselineScore, totalTargetScore]]; -+ } -+ }); -+ }); - } - - /** -@@ -152,20 +257,22 @@ function runTests(baselineFunc, targetFunc) { - */ - var BASELINE_FUNCTION = baselineFunctions.standard; - function getPerformanceScore(func) { -- return __awaiter(this, void 0, void 0, function () { -- var _a, baseline, target; -- return __generator(this, function (_b) { -- switch (_b.label) { -- case 0: -- if (typeof func !== 'function') -- throw new Error(func + " is not a function"); -- return [4 /*yield*/, runTests(BASELINE_FUNCTION.func, func)]; -- case 1: -- _a = _b.sent(), baseline = _a[0], target = _a[1]; -- return [2 /*return*/, calculateExpectedPerformance(BASELINE_FUNCTION.expectedMsRunTime, baseline, target)]; -- } -- }); -- }); -+ return __awaiter(this, void 0, void 0, function () { -+ var _a, baseline, target; -+ return __generator(this, function (_b) { -+ switch (_b.label) { -+ case 0: -+ if (typeof func !== "function") throw new Error(func + " is not a function"); -+ return [4 /*yield*/, runTests(BASELINE_FUNCTION.func, func)]; -+ case 1: -+ (_a = _b.sent()), (baseline = _a[0]), (target = _a[1]); -+ return [ -+ 2 /*return*/, -+ calculateExpectedPerformance(BASELINE_FUNCTION.expectedMsRunTime, baseline, target), -+ ]; -+ } -+ }); -+ }); - } - - module.exports = getPerformanceScore; diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts index 2d2457de..bb6ccea1 100644 --- a/util/src/entities/BaseClass.ts +++ b/util/src/entities/BaseClass.ts @@ -3,6 +3,10 @@ import { BaseEntity, BeforeInsert, BeforeUpdate, PrimaryColumn } from "typeorm"; import { Snowflake } from "../util/Snowflake"; import Ajv, { ValidateFunction } from "ajv"; import schema from "./schema.json"; +import "missing-native-js-functions"; + +// TODO use class-validator https://typeorm.io/#/validation with class annotators (isPhone/isEmail) combined with types from typescript-json-schema +// btw. we don't use class-validator for everything, because we need to explicitly set the type instead of deriving it from typescript also it doesn't easily support nested objects const ajv = new Ajv({ removeAdditional: "all", @@ -12,7 +16,6 @@ const ajv = new Ajv({ validateFormats: false, allowUnionTypes: true, }); -// const validator = ajv.compile(schema); export class BaseClass extends BaseEntity { @PrimaryColumn() @@ -43,10 +46,20 @@ export class BaseClass extends BaseEntity { delete props.opts; + const properties = new Set(this.metadata.columns.map((x: any) => x.propertyName)); + // will not include relational properties (e.g. @RelationId @ManyToMany) + for (const key in props) { if (this.hasOwnProperty(key)) continue; + if (!properties.has(key)) continue; + // @ts-ignore + const setter = this[`set${key.capitalize()}`]; - Object.defineProperty(this, key, { value: props[key] }); + if (setter) { + setter.call(this, props[key]); + } else { + Object.defineProperty(this, key, { value: props[key] }); + } } } diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts index 60d84958..c9326be2 100644 --- a/util/src/entities/Config.ts +++ b/util/src/entities/Config.ts @@ -1,7 +1,7 @@ import { Column, Entity, JoinColumn, ManyToOne } from "typeorm"; -import { Snowflake } from "../util"; import { BaseClass } from "./BaseClass"; import crypto from "crypto"; +import { Snowflake } from "../util/Snowflake"; @Entity("config") export class ConfigEntity extends BaseClass { diff --git a/util/src/entities/ReadState.ts b/util/src/entities/ReadState.ts index 0310cb5f..70a38b84 100644 --- a/util/src/entities/ReadState.ts +++ b/util/src/entities/ReadState.ts @@ -4,6 +4,10 @@ import { Channel } from "./Channel"; import { Message } from "./Message"; import { User } from "./User"; +// for read receipts +// notification cursor and public read receipt need to be forwards-only (the former to prevent re-pinging when marked as unread, and the latter to be acceptable as a legal acknowledgement in criminal proceedings), and private read marker needs to be advance-rewind capable +// public read receipt ≥ notification cursor ≥ private fully read marker + @Entity("read_states") export class ReadState extends BaseClass { @RelationId((read_state: ReadState) => read_state.channel) diff --git a/util/src/entities/Template.ts b/util/src/entities/Template.ts index c8d2034c..1dfc3b1b 100644 --- a/util/src/entities/Template.ts +++ b/util/src/entities/Template.ts @@ -1,11 +1,11 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { User } from "./User"; @Entity("templates") export class Template extends BaseClass { - @Column() + @PrimaryColumn() code: string; @Column() @@ -36,4 +36,7 @@ export class Template extends BaseClass { @JoinColumn({ name: "source_guild_id" }) @ManyToOne(() => Guild, (guild: Guild) => guild.id) source_guild: Guild; + + @Column("simple-json") + serialized_source_guild: Guild; } diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index bdf0d35f..03cb3af4 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -29,8 +29,8 @@ export class User extends BaseClass { setDiscriminator(val: string) { const number = Number(val); if (isNaN(number)) throw new Error("invalid discriminator"); - if (number > 0 && number < 10000) throw new Error("discriminator must be between 1 and 9999"); - this.discriminator = val; + if (number <= 0 || number > 10000) throw new Error("discriminator must be between 1 and 9999"); + this.discriminator = val.toString(); } @Column() diff --git a/util/src/entities/schema.json b/util/src/entities/schema.json index ebf66e88..7f192690 100644 --- a/util/src/entities/schema.json +++ b/util/src/entities/schema.json @@ -1198,6 +1198,380 @@ }, "type": "object" }, + "ConfigEntity": { + "properties": { + "construct": { + }, + "id": { + "type": "string" + }, + "metadata": { + }, + "opts": { + "properties": { + "id": { + "type": "string" + } + }, + "type": "object" + }, + "value": { + "$ref": "#/definitions/ConfigValue" + } + }, + "type": "object" + }, + "ConfigValue": { + "properties": { + "cdn": { + "properties": { + "endpoint": { + "type": [ + "null", + "string" + ] + }, + "endpointClient": { + "type": [ + "null", + "string" + ] + } + }, + "type": "object" + }, + "gateway": { + "properties": { + "endpoint": { + "type": [ + "null", + "string" + ] + }, + "endpointClient": { + "type": [ + "null", + "string" + ] + } + }, + "type": "object" + }, + "general": { + "properties": { + "instance_id": { + "type": "string" + } + }, + "type": "object" + }, + "kafka": { + "properties": { + "brokers": { + "anyOf": [ + { + "items": { + "$ref": "#/definitions/KafkaBroker" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "limits": { + "properties": { + "channel": { + "properties": { + "maxPins": { + "type": "number" + }, + "maxTopic": { + "type": "number" + } + }, + "type": "object" + }, + "guild": { + "properties": { + "hideOfflineMember": { + "type": "number" + }, + "maxChannels": { + "type": "number" + }, + "maxChannelsInCategory": { + "type": "number" + }, + "maxMembers": { + "type": "number" + }, + "maxRoles": { + "type": "number" + } + }, + "type": "object" + }, + "message": { + "properties": { + "maxAttachmentSize": { + "type": "number" + }, + "maxBulkDelete": { + "type": "number" + }, + "maxCharacters": { + "type": "number" + }, + "maxReactions": { + "type": "number" + }, + "maxTTSCharacters": { + "type": "number" + } + }, + "type": "object" + }, + "rate": { + "properties": { + "error": { + "$ref": "#/definitions/RateLimitOptions" + }, + "global": { + "$ref": "#/definitions/RateLimitOptions" + }, + "ip": { + "$ref": "#/definitions/Omit" + }, + "routes": { + "properties": { + "auth": { + "properties": { + "login": { + "$ref": "#/definitions/RateLimitOptions" + }, + "register": { + "$ref": "#/definitions/RateLimitOptions" + } + }, + "type": "object" + }, + "channel": { + "$ref": "#/definitions/RateLimitOptions" + }, + "guild": { + "$ref": "#/definitions/RateLimitOptions" + }, + "webhook": { + "$ref": "#/definitions/RateLimitOptions" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "user": { + "properties": { + "maxFriends": { + "type": "number" + }, + "maxGuilds": { + "type": "number" + }, + "maxUsername": { + "type": "number" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "login": { + "properties": { + "requireCaptcha": { + "type": "boolean" + } + }, + "type": "object" + }, + "permissions": { + "properties": { + "user": { + "properties": { + "createGuilds": { + "type": "boolean" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "rabbitmq": { + "properties": { + "host": { + "type": [ + "null", + "string" + ] + } + }, + "type": "object" + }, + "regions": { + "properties": { + "available": { + "items": { + "$ref": "#/definitions/Region" + }, + "type": "array" + }, + "default": { + "type": "string" + } + }, + "type": "object" + }, + "register": { + "properties": { + "allowMultipleAccounts": { + "type": "boolean" + }, + "allowNewRegistration": { + "type": "boolean" + }, + "blockProxies": { + "type": "boolean" + }, + "dateOfBirth": { + "properties": { + "minimum": { + "type": "number" + }, + "necessary": { + "type": "boolean" + } + }, + "type": "object" + }, + "email": { + "properties": { + "allowlist": { + "type": "boolean" + }, + "blocklist": { + "type": "boolean" + }, + "domains": { + "items": { + "type": "string" + }, + "type": "array" + }, + "necessary": { + "type": "boolean" + } + }, + "type": "object" + }, + "password": { + "properties": { + "minLength": { + "type": "number" + }, + "minNumbers": { + "type": "number" + }, + "minSymbols": { + "type": "number" + }, + "minUpperCase": { + "type": "number" + } + }, + "type": "object" + }, + "requireCaptcha": { + "type": "boolean" + }, + "requireInvite": { + "type": "boolean" + } + }, + "type": "object" + }, + "security": { + "properties": { + "autoUpdate": { + "type": [ + "number", + "boolean" + ] + }, + "captcha": { + "properties": { + "enabled": { + "type": "boolean" + }, + "secret": { + "type": [ + "null", + "string" + ] + }, + "service": { + "anyOf": [ + { + "enum": [ + "hcaptcha", + "recaptcha" + ], + "type": "string" + }, + { + "type": "null" + } + ] + }, + "sitekey": { + "type": [ + "null", + "string" + ] + } + }, + "type": "object" + }, + "forwadedFor": { + "type": [ + "null", + "string" + ] + }, + "ipdataApiKey": { + "type": [ + "null", + "string" + ] + }, + "jwtSecret": { + "type": "string" + }, + "requestSignature": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "ConnectedAccount": { "properties": { "access_token": { @@ -1721,6 +2095,9 @@ "public_updates_channel": { "$ref": "#/definitions/Channel" }, + "public_updates_channel_id": { + "type": "string" + }, "region": { "type": "string" }, @@ -1760,6 +2137,9 @@ "vanity_url": { "$ref": "#/definitions/Invite" }, + "vanity_url_code": { + "type": "string" + }, "verification_level": { "type": "number" }, @@ -1809,6 +2189,9 @@ "widget_channel": { "$ref": "#/definitions/Channel" }, + "widget_channel_id": { + "type": "string" + }, "widget_enabled": { "type": "boolean" } @@ -2520,12 +2903,12 @@ "target_user": { "type": "string" }, + "target_user_id": { + "type": "string" + }, "target_user_type": { "type": "number" }, - "target_usser_id": { - "type": "string" - }, "temporary": { "type": "boolean" }, @@ -2615,6 +2998,17 @@ }, "type": "object" }, + "KafkaBroker": { + "properties": { + "ip": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, "ListenEventOpts": { "properties": { "acknowledge": { @@ -3507,12 +3901,12 @@ "target_user": { "type": "string" }, + "target_user_id": { + "type": "string" + }, "target_user_type": { "type": "number" }, - "target_usser_id": { - "type": "string" - }, "temporary": { "type": "boolean" }, @@ -3843,6 +4237,23 @@ }, "type": "object" }, + "Omit": { + "properties": { + "bot": { + "type": "number" + }, + "count": { + "type": "number" + }, + "onyIp": { + "type": "boolean" + }, + "window": { + "type": "number" + } + }, + "type": "object" + }, "Omit": { "properties": { "assign": { @@ -4322,6 +4733,23 @@ }, "type": "object" }, + "RateLimitOptions": { + "properties": { + "bot": { + "type": "number" + }, + "count": { + "type": "number" + }, + "onyIp": { + "type": "boolean" + }, + "window": { + "type": "number" + } + }, + "type": "object" + }, "Reaction": { "properties": { "count": { @@ -4355,6 +4783,9 @@ "last_message": { "$ref": "#/definitions/Message" }, + "last_message_id": { + "type": "string" + }, "last_pin_timestamp": { "format": "date-time", "type": "string" @@ -4763,6 +5194,29 @@ "Record": { "type": "object" }, + "Region": { + "properties": { + "custom": { + "type": "boolean" + }, + "deprecated": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "optimal": { + "type": "boolean" + }, + "vip": { + "type": "boolean" + } + }, + "type": "object" + }, "Relationship": { "properties": { "construct": { @@ -5053,6 +5507,9 @@ "creator": { "$ref": "#/definitions/User" }, + "creator_id": { + "type": "string" + }, "description": { "type": "string" }, @@ -5072,9 +5529,15 @@ }, "type": "object" }, + "serialized_source_guild": { + "$ref": "#/definitions/Guild" + }, "source_guild": { "$ref": "#/definitions/Guild" }, + "source_guild_id": { + "type": "string" + }, "updated_at": { "format": "date-time", "type": "string" @@ -5164,6 +5627,18 @@ "format": "date-time", "type": "string" }, + "data": { + "properties": { + "hash": { + "type": "string" + }, + "valid_tokens_since": { + "format": "date-time", + "type": "string" + } + }, + "type": "object" + }, "deleted": { "type": "boolean" }, @@ -5179,15 +5654,27 @@ "email": { "type": "string" }, + "fingerprints": { + "items": { + "type": "string" + }, + "type": "array" + }, "flags": { "type": "bigint" }, - "guilds": { + "guild_ids": { "items": { "type": "string" }, "type": "array" }, + "guilds": { + "items": { + "$ref": "#/definitions/Guild" + }, + "type": "array" + }, "id": { "type": "string" }, @@ -5240,24 +5727,6 @@ "system": { "type": "boolean" }, - "user_data": { - "properties": { - "fingerprints": { - "items": { - "type": "string" - }, - "type": "array" - }, - "hash": { - "type": "string" - }, - "valid_tokens_since": { - "format": "date-time", - "type": "string" - } - }, - "type": "object" - }, "username": { "type": "string" }, @@ -5544,6 +6013,9 @@ "channel": { "$ref": "#/definitions/Channel" }, + "channel_id": { + "type": "string" + }, "construct": { }, "deaf": { @@ -5552,6 +6024,9 @@ "guild": { "$ref": "#/definitions/Guild" }, + "guild_id": { + "type": "string" + }, "id": { "type": "string" }, @@ -5588,6 +6063,9 @@ }, "user": { "$ref": "#/definitions/User" + }, + "user_id": { + "type": "string" } }, "type": "object" @@ -5634,17 +6112,26 @@ "Webhook": { "properties": { "application": { + "$ref": "#/definitions/Application" + }, + "application_id": { "type": "string" }, "avatar": { "type": "string" }, "channel": { + "$ref": "#/definitions/Channel" + }, + "channel_id": { "type": "string" }, "construct": { }, "guild": { + "$ref": "#/definitions/Guild" + }, + "guild_id": { "type": "string" }, "id": { @@ -5664,6 +6151,9 @@ "type": "object" }, "source_guild": { + "$ref": "#/definitions/Guild" + }, + "source_guild_id": { "type": "string" }, "token": { @@ -5673,6 +6163,9 @@ "$ref": "#/definitions/WebhookType" }, "user": { + "$ref": "#/definitions/User" + }, + "user_id": { "type": "string" } }, diff --git a/util/src/util/Config.ts b/util/src/util/Config.ts new file mode 100644 index 00000000..f8574f38 --- /dev/null +++ b/util/src/util/Config.ts @@ -0,0 +1,19 @@ +import "missing-native-js-functions"; +import { ConfigValue, ConfigEntity, DefaultConfigOptions } from "../entities/Config"; + +var config: ConfigEntity; +// TODO: use events to inform about config updates + +export const Config = { + init: async function init() { + config = new ConfigEntity({}, { id: "0" }); + return this.set((config.value || {}).merge(DefaultConfigOptions)); + }, + get: function get() { + return config.value as ConfigValue; + }, + set: function set(val: any) { + config.value = val.merge(config.value); + return config.save(); + }, +}; diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts index 90ba9079..8bb8078e 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts @@ -1,11 +1,12 @@ import "reflect-metadata"; -import { createConnection } from "typeorm"; +import { Connection, createConnection } from "typeorm"; import * as Models from "../entities"; // UUID extension option is only supported with postgres // We want to generate all id's with Snowflakes that's why we have our own BaseEntity class var promise: Promise; +var dbConnection: Connection | undefined; export function initDatabase() { if (promise) return promise; // prevent initalizing multiple times @@ -20,7 +21,16 @@ export function initDatabase() { logging: false, }); - promise.then(() => console.log("[Database] connected")); + promise.then((connection) => { + dbConnection = connection; + console.log("[Database] connected"); + }); return promise; } + +export { dbConnection }; + +export function closeDatabase() { + dbConnection?.close(); +} diff --git a/util/src/util/checkToken.ts b/util/src/util/checkToken.ts index 58e537ea..1e203006 100644 --- a/util/src/util/checkToken.ts +++ b/util/src/util/checkToken.ts @@ -9,13 +9,10 @@ export function checkToken(token: string, jwtSecret: string): Promise { jwt.verify(token, jwtSecret, JWTOptions, async (err, decoded: any) => { if (err || !decoded) return rej("Invalid Token"); - const user = await User.findOne( - { id: decoded.id }, - { select: ["user_data", "bot", "disabled", "deleted"] } - ); + const user = await User.findOne({ id: decoded.id }, { select: ["data", "bot", "disabled", "deleted"] }); if (!user) return rej("Invalid Token"); // we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds - if (decoded.iat * 1000 < user.user_data.valid_tokens_since.setSeconds(0, 0)) return rej("Invalid Token"); + if (decoded.iat * 1000 < user.data.valid_tokens_since.setSeconds(0, 0)) return rej("Invalid Token"); if (user.disabled) return rej("User disabled"); if (user.deleted) return rej("User not found"); diff --git a/util/src/util/index.ts b/util/src/util/index.ts index 700ecfa5..16b98ca3 100644 --- a/util/src/util/index.ts +++ b/util/src/util/index.ts @@ -1,13 +1,13 @@ export * from "./Database"; -export * from "./Regex"; -export * from "./String"; export * from "./BitField"; +export * from "./Config"; +export * from "./checkToken"; +export * from "./Event"; export * from "./Intents"; export * from "./MessageFlags"; export * from "./Permissions"; export * from "./Snowflake"; -export * from "./toBigInt"; export * from "./RabbitMQ"; -export * from "./Event"; -export * from "./checkToken"; +export * from "./Regex"; +export * from "./String"; diff --git a/util/src/util/toBigInt.ts b/util/src/util/toBigInt.ts deleted file mode 100644 index b7985928..00000000 --- a/util/src/util/toBigInt.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default function toBigInt(string: string): bigint { - return BigInt(string); -} - diff --git a/util/tests/User.test.js b/util/tests/User.test.js new file mode 100644 index 00000000..b87c753d --- /dev/null +++ b/util/tests/User.test.js @@ -0,0 +1,31 @@ +const { initDatabase, closeDatabase } = require("../dist/util/Database"); +const { User } = require("../dist/entities/User"); +jest.setTimeout(10000); + +beforeAll((done) => { + initDatabase().then(() => { + new User().validate(); // warm up schema/model + done(); + }); +}); + +afterAll(() => { + closeDatabase(); +}); + +describe("User", () => { + test("valid discriminator: 1", async () => { + new User({ discriminator: "1" }).validate(); + }); + test("invalid discriminator: test", async () => { + expect(() => { + new User({ discriminator: "test" }).validate(); + }).toThrow(); + }); + + test("invalid discriminator: 0", async () => { + expect(() => { + new User({ discriminator: "0" }).validate(); + }).toThrow(); + }); +}); diff --git a/util/tests/validate.test.js b/util/tests/validate.test.js index c885a167..434422f8 100644 --- a/util/tests/validate.test.js +++ b/util/tests/validate.test.js @@ -1,4 +1,4 @@ -const { initDatabase } = require("../dist/util/Database"); +const { initDatabase, closeDatabase } = require("../dist/util/Database"); const { User } = require("../dist/entities/User"); jest.setTimeout(10000); @@ -9,13 +9,15 @@ beforeAll((done) => { }); }); +afterAll(() => { + closeDatabase(); +}); + describe("Validate model class properties", () => { - describe("User", () => { - test("object instead of string", async () => { - expect(() => { - new User({ username: {} }).validate(); - }).toThrow(); - }); + test("object instead of string", async () => { + expect(() => { + new User({}, { id: {} }).validate(); + }).toThrow(); }); test("validation should be faster than 20ms", () => { diff --git a/util/util/Config.ts b/util/util/Config.ts deleted file mode 100644 index c65c4e44..00000000 --- a/util/util/Config.ts +++ /dev/null @@ -1,290 +0,0 @@ -import { Schema, model, Types, Document } from "mongoose"; -import "missing-native-js-functions"; -import { Snowflake } from "./Snowflake"; -import crypto from "crypto"; - -var config: any; - -export default { - init: async function init(defaultOpts: any = DefaultOptions) { - config = await db.collection("config").findOneOrFail({}); - return this.set((config || {}).merge(defaultOpts)); - }, - get: function get() { - return config as DefaultOptions; - }, - set: function set(val: any) { - config = val.merge(config); - return db.collection("config").update({}, { $set: val }, { upsert: true }); - }, -}; - -export interface RateLimitOptions { - bot?: number; - count: number; - window: number; - onyIp?: boolean; -} - -export interface Region { - id: string; - name: string; - vip: boolean; - custom: boolean; - deprecated: boolean; - optimal: boolean; -} - -export interface KafkaBroker { - ip: string; - port: number; -} - -export interface DefaultOptions { - gateway: { - endpointClient: string | null; - endpoint: string | null; - }; - cdn: { - endpointClient: string | null; - endpoint: string | null; - }; - general: { - instance_id: string; - }; - permissions: { - user: { - createGuilds: boolean; - }; - }; - limits: { - user: { - maxGuilds: number; - maxUsername: number; - maxFriends: number; - }; - guild: { - maxRoles: number; - maxMembers: number; - maxChannels: number; - maxChannelsInCategory: number; - hideOfflineMember: number; - }; - message: { - maxCharacters: number; - maxTTSCharacters: number; - maxReactions: number; - maxAttachmentSize: number; - maxBulkDelete: number; - }; - channel: { - maxPins: number; - maxTopic: number; - }; - rate: { - ip: Omit; - global: RateLimitOptions; - error: RateLimitOptions; - routes: { - guild: RateLimitOptions; - webhook: RateLimitOptions; - channel: RateLimitOptions; - auth: { - login: RateLimitOptions; - register: RateLimitOptions; - }; - // TODO: rate limit configuration for all routes - }; - }; - }; - security: { - autoUpdate: boolean | number; - requestSignature: string; - jwtSecret: string; - forwadedFor: string | null; // header to get the real user ip address - captcha: { - enabled: boolean; - service: "recaptcha" | "hcaptcha" | null; // TODO: hcaptcha, custom - sitekey: string | null; - secret: string | null; - }; - ipdataApiKey: string | null; - }; - login: { - requireCaptcha: boolean; - }; - register: { - email: { - necessary: boolean; // we have to use necessary instead of required as the cli tool uses json schema and can't use required - allowlist: boolean; - blocklist: boolean; - domains: string[]; - }; - dateOfBirth: { - necessary: boolean; - minimum: number; // in years - }; - requireCaptcha: boolean; - requireInvite: boolean; - allowNewRegistration: boolean; - allowMultipleAccounts: boolean; - blockProxies: boolean; - password: { - minLength: number; - minNumbers: number; - minUpperCase: number; - minSymbols: number; - }; - }; - regions: { - default: string; - available: Region[]; - }; - rabbitmq: { - host: string | null; - }; - kafka: { - brokers: KafkaBroker[] | null; - }; -} - -export const DefaultOptions: DefaultOptions = { - gateway: { - endpointClient: null, - endpoint: null, - }, - cdn: { - endpointClient: null, - endpoint: null, - }, - general: { - instance_id: Snowflake.generate(), - }, - permissions: { - user: { - createGuilds: true, - }, - }, - limits: { - user: { - maxGuilds: 100, - maxUsername: 32, - maxFriends: 1000, - }, - guild: { - maxRoles: 250, - maxMembers: 250000, - maxChannels: 500, - maxChannelsInCategory: 50, - hideOfflineMember: 1000, - }, - message: { - maxCharacters: 2000, - maxTTSCharacters: 200, - maxReactions: 20, - maxAttachmentSize: 8388608, - maxBulkDelete: 100, - }, - channel: { - maxPins: 50, - maxTopic: 1024, - }, - rate: { - ip: { - count: 500, - window: 5, - }, - global: { - count: 20, - window: 5, - bot: 250, - }, - error: { - count: 10, - window: 5, - }, - routes: { - guild: { - count: 5, - window: 5, - }, - webhook: { - count: 5, - window: 20, - }, - channel: { - count: 5, - window: 20, - }, - auth: { - login: { - count: 5, - window: 60, - }, - register: { - count: 2, - window: 60 * 60 * 12, - }, - }, - }, - }, - }, - security: { - autoUpdate: true, - requestSignature: crypto.randomBytes(32).toString("base64"), - jwtSecret: crypto.randomBytes(256).toString("base64"), - forwadedFor: null, - // forwadedFor: "X-Forwarded-For" // nginx/reverse proxy - // forwadedFor: "CF-Connecting-IP" // cloudflare: - captcha: { - enabled: false, - service: null, - sitekey: null, - secret: null, - }, - ipdataApiKey: "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9", - }, - login: { - requireCaptcha: false, - }, - register: { - email: { - necessary: true, - allowlist: false, - blocklist: true, - domains: [], // TODO: efficiently save domain blocklist in database - // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"), - }, - dateOfBirth: { - necessary: true, - minimum: 13, - }, - requireInvite: false, - requireCaptcha: true, - allowNewRegistration: true, - allowMultipleAccounts: true, - blockProxies: true, - password: { - minLength: 8, - minNumbers: 2, - minUpperCase: 2, - minSymbols: 0, - }, - }, - regions: { - default: "fosscord", - available: [{ id: "fosscord", name: "Fosscord", vip: false, custom: false, deprecated: false, optimal: false }], - }, - rabbitmq: { - host: null, - }, - kafka: { - brokers: null, - }, -}; - -export const ConfigSchema = new Schema({}, { strict: false }); - -export interface DefaultOptionsDocument extends DefaultOptions, Document {} - -export const ConfigModel = model("Config", ConfigSchema, "config"); -- cgit 1.5.1 From b4b8d1d8df3bf8263116310273c7f7ba65557806 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 29 Aug 2021 00:30:04 +0200 Subject: :sparkles: typeorm gateway --- gateway/package-lock.json | 42 ++++++++++++++++++++++++---------------- gateway/src/Server.ts | 13 +++---------- gateway/src/listener/listener.ts | 23 +++++++++++----------- gateway/src/opcodes/Identify.ts | 15 ++++++-------- gateway/src/schema/Activity.ts | 41 +++++++++++++++++++++++++++++++++++++-- util/src/entities/Channel.ts | 1 + 6 files changed, 85 insertions(+), 50 deletions(-) (limited to 'gateway/src') diff --git a/gateway/package-lock.json b/gateway/package-lock.json index e76bd71c..5190b6b0 100644 --- a/gateway/package-lock.json +++ b/gateway/package-lock.json @@ -41,26 +41,30 @@ "hasInstallScript": true, "license": "GPLV3", "dependencies": { - "ajv": "^8.5.0", + "ajv": "^8.6.2", "amqplib": "^0.8.0", + "class-validator": "^0.13.1", "dot-prop": "^6.0.1", "env-paths": "^2.2.1", "jsonwebtoken": "^8.5.1", - "missing-native-js-functions": "^1.2.10", - "mongodb": "^3.6.9", - "mongoose": "^5.13.7", - "mongoose-autopopulate": "^0.12.3", + "lambert-server": "^1.2.10", + "missing-native-js-functions": "^1.2.11", "node-fetch": "^2.6.1", - "typescript": "^4.1.3" + "patch-package": "^6.4.7", + "pg": "^8.7.1", + "reflect-metadata": "^0.1.13", + "sqlite3": "^5.0.2", + "typeorm": "^0.2.37", + "typescript": "^4.3.5", + "typescript-json-schema": "^0.50.1" }, "devDependencies": { "@types/amqplib": "^0.8.1", "@types/jsonwebtoken": "^8.5.0", - "@types/mongodb": "^3.6.9", "@types/mongoose-autopopulate": "^0.10.1", - "@types/mongoose-lean-virtuals": "^0.5.1", "@types/node": "^14.17.9", - "@types/node-fetch": "^2.5.12" + "@types/node-fetch": "^2.5.12", + "jest": "^27.0.6" } }, "node_modules/@fosscord/util": { @@ -1927,22 +1931,26 @@ "requires": { "@types/amqplib": "^0.8.1", "@types/jsonwebtoken": "^8.5.0", - "@types/mongodb": "^3.6.9", "@types/mongoose-autopopulate": "^0.10.1", - "@types/mongoose-lean-virtuals": "^0.5.1", "@types/node": "^14.17.9", "@types/node-fetch": "^2.5.12", - "ajv": "^8.5.0", + "ajv": "^8.6.2", "amqplib": "^0.8.0", + "class-validator": "^0.13.1", "dot-prop": "^6.0.1", "env-paths": "^2.2.1", + "jest": "^27.0.6", "jsonwebtoken": "^8.5.1", - "missing-native-js-functions": "^1.2.10", - "mongodb": "^3.6.9", - "mongoose": "^5.13.7", - "mongoose-autopopulate": "^0.12.3", + "lambert-server": "^1.2.10", + "missing-native-js-functions": "^1.2.11", "node-fetch": "^2.6.1", - "typescript": "^4.1.3" + "patch-package": "^6.4.7", + "pg": "^8.7.1", + "reflect-metadata": "^0.1.13", + "sqlite3": "^5.0.2", + "typeorm": "^0.2.37", + "typescript": "^4.3.5", + "typescript-json-schema": "^0.50.1" } }, "@types/amqplib": { diff --git a/gateway/src/Server.ts b/gateway/src/Server.ts index a50c24a6..944174c7 100644 --- a/gateway/src/Server.ts +++ b/gateway/src/Server.ts @@ -1,7 +1,7 @@ import "missing-native-js-functions"; import dotenv from "dotenv"; dotenv.config(); -import { Config, db, initEvent, RabbitMQ } from "@fosscord/util"; +import { closeDatabase, Config, initDatabase, initEvent, RabbitMQ } from "@fosscord/util"; import { Server as WebSocketServer } from "ws"; import { Connection } from "./events/Connection"; import http from "http"; @@ -38,15 +38,8 @@ export class Server { this.ws.on("error", console.error); } - async setupSchema() { - // TODO: adjust expireAfterSeconds -> lower - await Promise.all([db.collection("events").createIndex({ created_at: 1 }, { expireAfterSeconds: 60 })]); - } - async start(): Promise { - // @ts-ignore - await (db as Promise); - await this.setupSchema(); + await initDatabase(); await Config.init(); await initEvent(); if (!this.server.listening) { @@ -56,7 +49,7 @@ export class Server { } async stop() { - await db.close(); + closeDatabase(); this.server.close(); } } diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index 633580e3..8fa96555 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -1,22 +1,20 @@ import { - db, - Event, User, getPermission, Permissions, Channel, RabbitMQ, - EVENT, listenEvent, EventOpts, ListenEventOpts, + Member, } from "@fosscord/util"; import { OPCODES } from "../util/Constants"; import { Send } from "../util/Send"; import WebSocket from "../util/WebSocket"; import "missing-native-js-functions"; -import { ConsumeMessage } from "amqplib"; -import { Channel } from "amqplib"; +import { Channel as AMQChannel } from "amqplib"; +import { In } from "../../../util/node_modules/typeorm"; // TODO: close connection on Invalidated Token // TODO: check intent @@ -27,15 +25,16 @@ import { Channel } from "amqplib"; // TODO: use already queried guilds/channels of Identify and don't fetch them again export async function setupListener(this: WebSocket) { - const user = await User.findOneOrFail({ id: this.user_id }, { guilds: true }); - const channels = await Channel.find( - { $or: [{ recipient_ids: this.user_id }, { guild_id: { $in: user.guilds } }] }, - { id: true, permission_overwrites: true } - ); + const members = await Member.find({ where: { id: this.user_id } }); + const guild_ids = members.map((x) => x.guild_id); + const user = await User.findOneOrFail({ id: this.user_id }); + const channels = await Channel.find({ + where: [{ recipient_ids: this.user_id }, { guild_id: In(guild_ids) }], + }); const dm_channels = channels.filter((x) => !x.guild_id); const guild_channels = channels.filter((x) => x.guild_id); - const opts: { acknowledge: boolean; channel?: Channel } = { acknowledge: true }; + const opts: { acknowledge: boolean; channel?: AMQChannel } = { acknowledge: true }; const consumer = consume.bind(this); if (RabbitMQ.connection) { @@ -50,7 +49,7 @@ export async function setupListener(this: WebSocket) { this.events[channel.id] = await listenEvent(channel.id, consumer, opts); } - for (const guild of user.guilds) { + for (const guild of guild_ids) { // contains guild and dm channels getPermission(this.user_id, guild) diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index 644d0984..5be2acce 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -42,16 +42,17 @@ export async function onIdentify(this: WebSocket, data: Payload) { } } - const members = await Member.find({ id: this.user_id }); + const members = await Member.find({ where: { id: this.user_id }, relations: ["guilds"] }); const merged_members = members.map((x: any) => { const y = { ...x, user_id: x.id }; delete y.settings; delete y.id; return [y]; - }) as MemberDocument[][]; + }) as Member[][]; + const guilds = members.map((x) => x.guild); const user_guild_settings_entries = members.map((x) => x.settings); - const channels = await Channel.find({ recipient_ids: this.user_id }); + const channels = await Channel.find({ where: { recipient_ids: this.user_id } }); const user = await User.findOneOrFail({ id: this.user_id }); if (!user) return this.close(CLOSECODES.Authentication_failed); @@ -64,10 +65,6 @@ export async function onIdentify(this: WebSocket, data: Payload) { bot: user.bot, }; - const guilds = await Guild.find({ id: { $in: user.guilds } }).populate({ - path: "joined_at", - match: { id: this.user_id }, - }); const privateUser = { avatar: user.avatar, mobile: user.mobile, @@ -87,6 +84,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { bot: user.bot, accent_color: user.accent_color || 0, banner: user.banner, + bio: user.bio, }; const d: ReadyEventData = { @@ -106,7 +104,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { }), guild_experiments: [], // TODO geo_ordered_rtc_regions: [], // TODO - relationships: user.data.relationships, + relationships: user.relationships, read_state: { // TODO entries: [], @@ -120,7 +118,6 @@ export async function onIdentify(this: WebSocket, data: Payload) { }, // @ts-ignore private_channels: channels.map((x): ChannelDocument => { - x.recipient_ids = x.recipients.map((y: any) => y.id); delete x.recipients; return x; }), diff --git a/gateway/src/schema/Activity.ts b/gateway/src/schema/Activity.ts index d7e0a30b..0fd0592f 100644 --- a/gateway/src/schema/Activity.ts +++ b/gateway/src/schema/Activity.ts @@ -1,10 +1,47 @@ -import { ActivityBodySchema } from "@fosscord/util"; import { EmojiSchema } from "./Emoji"; export const ActivitySchema = { afk: Boolean, status: String, - $activities: [ActivityBodySchema], + $activities: [ + { + name: String, + type: Number, + $url: String, + $created_at: Date, + $timestamps: [ + { + $start: Number, + $end: Number, + }, + ], + $application_id: String, + $details: String, + $state: String, + $emoji: { + $name: String, + $id: String, + $amimated: Boolean, + }, + $party: { + $id: String, + $size: [Number, Number], + }, + $assets: { + $large_image: String, + $large_text: String, + $small_image: String, + $small_text: String, + }, + $secrets: { + $join: String, + $spectate: String, + $match: String, + }, + $instance: Boolean, + $flags: BigInt, + }, + ], $since: Number, // unix time (in milliseconds) of when the client went idle, or null if the client is not idle }; diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index d02cedb4..4900f485 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -25,6 +25,7 @@ export class Channel extends BaseClass { @Column({ type: "simple-enum", enum: ChannelType }) type: ChannelType; + @Column("simple-array") @RelationId((channel: Channel) => channel.recipients) recipient_ids: string[]; -- cgit 1.5.1 From d0292ef96bedde2dd23962c15b2a0446b8492fb0 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 29 Aug 2021 17:12:46 +0200 Subject: :bug: convert bigint -> string --- api/src/middlewares/RateLimit.ts | 4 ++-- .../routes/channels/#channel_id/messages/index.ts | 2 +- api/src/routes/guilds/index.ts | 2 +- api/src/schema/Guild.ts | 2 +- bundle/database.db | Bin 225280 -> 225280 bytes gateway/src/opcodes/Identify.ts | 2 +- gateway/src/schema/Activity.ts | 4 ++-- util/src/entities/Application.ts | 2 +- util/src/interfaces/Event.ts | 6 +++--- 9 files changed, 12 insertions(+), 12 deletions(-) (limited to 'gateway/src') diff --git a/api/src/middlewares/RateLimit.ts b/api/src/middlewares/RateLimit.ts index e0cf103a..ed6b951a 100644 --- a/api/src/middlewares/RateLimit.ts +++ b/api/src/middlewares/RateLimit.ts @@ -1,6 +1,6 @@ import { Config, listenEvent, emitEvent, RateLimit } from "@fosscord/util"; import { NextFunction, Request, Response, Router } from "express"; -import { LessThan } from "typeorm"; +import { LessThan, MoreThan } from "typeorm"; import { getIpAdress } from "../util/ipAddress"; import { API_PREFIX_TRAILING_SLASH } from "./Authentication"; @@ -100,7 +100,7 @@ export async function initRateLimits(app: Router) { Cache.set(event.channel_id as string, event.data); event.acknowledge?.(); }); - await RateLimit.delete({ expires_at: LessThan(new Date()) }); // clean up if not already deleted + await RateLimit.delete({ expires_at: MoreThan(new Date()) }); // cleans up if not already deleted, morethan -> older date const limits = await RateLimit.find({ blocked: true }); limits.forEach((limit) => { Cache.set(limit.executor_id, limit); diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts index 6307c022..17944548 100644 --- a/api/src/routes/channels/#channel_id/messages/index.ts +++ b/api/src/routes/channels/#channel_id/messages/index.ts @@ -77,7 +77,7 @@ router.get("/", async (req: Request, res: Response) => { delete x.user_ids; }); // @ts-ignore - if (!x.author) x.author = { discriminator: "0000", username: "Deleted User", public_flags: 0n, avatar: null }; + if (!x.author) x.author = { discriminator: "0000", username: "Deleted User", public_flags: "0", avatar: null }; return x; }); diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts index c158c7d4..1e83cf13 100644 --- a/api/src/routes/guilds/index.ts +++ b/api/src/routes/guilds/index.ts @@ -47,7 +47,7 @@ router.post("/", check(GuildCreateSchema), async (req: Request, res: Response) = premium_tier: 0, public_updates_channel_id: undefined, rules_channel_id: undefined, - system_channel_flags: 0, + system_channel_flags: "0", system_channel_id: undefined, unavailable: false, vanity_url_code: undefined, diff --git a/api/src/schema/Guild.ts b/api/src/schema/Guild.ts index 01690ae9..3e98fe76 100644 --- a/api/src/schema/Guild.ts +++ b/api/src/schema/Guild.ts @@ -33,7 +33,7 @@ export const GuildUpdateSchema = { $icon: String, $verification_level: Number, $default_message_notifications: Number, - $system_channel_flags: Number, + $system_channel_flags: String, $system_channel_id: String, $explicit_content_filter: Number, $public_updates_channel_id: String, diff --git a/bundle/database.db b/bundle/database.db index 9572c45e..2d4abd49 100644 Binary files a/bundle/database.db and b/bundle/database.db differ diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index 5be2acce..87008998 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -42,7 +42,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { } } - const members = await Member.find({ where: { id: this.user_id }, relations: ["guilds"] }); + const members = await Member.find({ where: { id: this.user_id }, relations: ["guild"] }); const merged_members = members.map((x: any) => { const y = { ...x, user_id: x.id }; delete y.settings; diff --git a/gateway/src/schema/Activity.ts b/gateway/src/schema/Activity.ts index 0fd0592f..f1665efd 100644 --- a/gateway/src/schema/Activity.ts +++ b/gateway/src/schema/Activity.ts @@ -39,7 +39,7 @@ export const ActivitySchema = { $match: String, }, $instance: Boolean, - $flags: BigInt, + $flags: String, }, ], $since: Number, // unix time (in milliseconds) of when the client went idle, or null if the client is not idle @@ -79,7 +79,7 @@ export interface ActivitySchema { match?: string; // the secret for a specific instanced match }; instance?: boolean; - flags: bigint; // activity flags OR d together, describes what the payload includes + flags: string; // activity flags OR d together, describes what the payload includes } ]; since?: number; // unix time (in milliseconds) of when the client went idle, or null if the client is not idle diff --git a/util/src/entities/Application.ts b/util/src/entities/Application.ts index a87b5cea..b179d171 100644 --- a/util/src/entities/Application.ts +++ b/util/src/entities/Application.ts @@ -62,7 +62,7 @@ export class Application extends BaseClass { cover_image?: string; // the application's default rich presence invite cover image hash @Column() - flags: number; // the application's public flags + flags: string; // the application's public flags } export interface ApplicationCommand { diff --git a/util/src/interfaces/Event.ts b/util/src/interfaces/Event.ts index 0de55f71..814a8beb 100644 --- a/util/src/interfaces/Event.ts +++ b/util/src/interfaces/Event.ts @@ -36,7 +36,7 @@ export interface ReadyEventData { mobile: boolean; desktop: boolean; email: string | undefined; - flags: bigint; + flags: string; mfa_enabled: boolean; nsfw_allowed: boolean; phone: string | undefined; @@ -85,7 +85,7 @@ export interface ReadyEventData { }; application?: { id: string; - flags: bigint; + flags: string; }; merged_members?: Omit[][]; // probably all users who the user is in contact with @@ -95,7 +95,7 @@ export interface ReadyEventData { id: string; username: string; bot: boolean; - public_flags: bigint; + public_flags: string; }[]; } -- cgit 1.5.1 From adc75ca76b5561d6d4e8d01c5fdd574f8b98363a Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Tue, 31 Aug 2021 17:58:28 +0200 Subject: :sparkles: channel recipients --- api/src/routes/users/@me/channels.ts | 7 +++--- gateway/package-lock.json | 4 ++-- gateway/src/listener/listener.ts | 10 ++++----- gateway/src/opcodes/Identify.ts | 42 ++++++++++++++++++++++++------------ 4 files changed, 39 insertions(+), 24 deletions(-) (limited to 'gateway/src') diff --git a/api/src/routes/users/@me/channels.ts b/api/src/routes/users/@me/channels.ts index ab203571..880e09c1 100644 --- a/api/src/routes/users/@me/channels.ts +++ b/api/src/routes/users/@me/channels.ts @@ -5,13 +5,14 @@ import { HTTPError } from "lambert-server"; import { DmChannelCreateSchema } from "../../../schema/Channel"; import { check } from "../../../util/instanceOf"; import { In } from "typeorm"; +import { Recipient } from "../../../../../util/dist/entities/Recipient"; const router: Router = Router(); router.get("/", async (req: Request, res: Response) => { - var channels = await Channel.find({ recipient_ids: req.user_id }); + const recipients = await Recipient.find({ where: { id: req.user_id }, relations: ["channel"] }); - res.json(channels); + res.json(recipients.map((x) => x.channel)); }); router.post("/", check(DmChannelCreateSchema), async (req: Request, res: Response) => { @@ -34,7 +35,7 @@ router.post("/", check(DmChannelCreateSchema), async (req: Request, res: Respons owner_id: req.user_id, created_at: new Date(), last_message_id: null, - recipient_ids: [...body.recipients, req.user_id] + recipients: [...body.recipients.map((x) => new Recipient({ id: x })), new Recipient({ id: req.user_id })] }).save(); await emitEvent({ event: "CHANNEL_CREATE", data: channel, user_id: req.user_id } as ChannelCreateEvent); diff --git a/gateway/package-lock.json b/gateway/package-lock.json index 5190b6b0..40606ecd 100644 --- a/gateway/package-lock.json +++ b/gateway/package-lock.json @@ -55,7 +55,7 @@ "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", "typeorm": "^0.2.37", - "typescript": "^4.3.5", + "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" }, "devDependencies": { @@ -1949,7 +1949,7 @@ "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", "typeorm": "^0.2.37", - "typescript": "^4.3.5", + "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" } }, diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index 8fa96555..75ca1680 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -14,7 +14,8 @@ import { Send } from "../util/Send"; import WebSocket from "../util/WebSocket"; import "missing-native-js-functions"; import { Channel as AMQChannel } from "amqplib"; -import { In } from "../../../util/node_modules/typeorm"; +import { In, Like } from "../../../util/node_modules/typeorm"; +import { Recipient } from "../../../util/dist/entities/Recipient"; // TODO: close connection on Invalidated Token // TODO: check intent @@ -28,10 +29,9 @@ export async function setupListener(this: WebSocket) { const members = await Member.find({ where: { id: this.user_id } }); const guild_ids = members.map((x) => x.guild_id); const user = await User.findOneOrFail({ id: this.user_id }); - const channels = await Channel.find({ - where: [{ recipient_ids: this.user_id }, { guild_id: In(guild_ids) }], - }); - const dm_channels = channels.filter((x) => !x.guild_id); + const recipients = await Recipient.find({ where: { id: this.user_id }, relations: ["channel"] }); + const channels = await Channel.find({ guild_id: In(guild_ids) }); + const dm_channels = recipients.map((x) => x.channel); const guild_channels = channels.filter((x) => x.guild_id); const opts: { acknowledge: boolean; channel?: AMQChannel } = { acknowledge: true }; diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index 87008998..958f1b73 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -1,12 +1,25 @@ import { CLOSECODES, Payload, OPCODES } from "../util/Constants"; import WebSocket from "../util/WebSocket"; -import { Channel, checkToken, Guild, Intents, Member, ReadyEventData, User, EVENTEnum, Config } from "@fosscord/util"; +import { + Channel, + checkToken, + Guild, + Intents, + Member, + ReadyEventData, + User, + EVENTEnum, + Config, + dbConnection, +} from "@fosscord/util"; import { setupListener } from "../listener/listener"; import { IdentifySchema } from "../schema/Identify"; import { Send } from "../util/Send"; // import experiments from "./experiments.json"; const experiments: any = []; import { check } from "./instanceOf"; +import { Like } from "../../../util/node_modules/typeorm"; +import { Recipient } from "../../../util/dist/entities/Recipient"; // TODO: bot sharding // TODO: check priviliged intents @@ -42,17 +55,21 @@ export async function onIdentify(this: WebSocket, data: Payload) { } } - const members = await Member.find({ where: { id: this.user_id }, relations: ["guild"] }); + const members = await Member.find({ + where: { id: this.user_id }, + relations: ["guild", "guild.channels", "guild.emojis", "guild.roles", "guild.stickers", "user", "roles"], + }); const merged_members = members.map((x: any) => { - const y = { ...x, user_id: x.id }; - delete y.settings; - delete y.id; - return [y]; + return [x]; }) as Member[][]; - const guilds = members.map((x) => x.guild); + const guilds = members.map((x) => ({ ...x.guild, joined_at: x.joined_at })); const user_guild_settings_entries = members.map((x) => x.settings); - const channels = await Channel.find({ where: { recipient_ids: this.user_id } }); + const recipients = await Recipient.find({ + where: { id: this.user_id }, + relations: ["channel", "channel.recipients"], + }); + const channels = recipients.map((x) => x.channel); const user = await User.findOneOrFail({ id: this.user_id }); if (!user) return this.close(CLOSECODES.Authentication_failed); @@ -63,6 +80,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { public_flags: user.public_flags, avatar: user.avatar, bot: user.bot, + bio: user.bio, }; const privateUser = { @@ -116,11 +134,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { partial: false, // TODO partial version: 642, }, - // @ts-ignore - private_channels: channels.map((x): ChannelDocument => { - delete x.recipients; - return x; - }), + private_channels: channels, session_id: "", // TODO analytics_token: "", // TODO connected_accounts: [], // TODO @@ -134,7 +148,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { // @ts-ignore experiments: experiments, // TODO guild_join_requests: [], // TODO what is this? - users: [public_user, ...channels.map((x: any) => x.recipients).flat()].unique(), // TODO + users: [public_user].unique(), // TODO merged_members: merged_members, // shard // TODO: only for bots sharding // application // TODO for applications -- cgit 1.5.1