From 1de0dbe50942803c00eff92dd695694db4a771f3 Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 17 Mar 2023 16:36:25 +0100 Subject: build: update dependencies --- src/api/middlewares/Translation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api') diff --git a/src/api/middlewares/Translation.ts b/src/api/middlewares/Translation.ts index 928d29ff..999d42a3 100644 --- a/src/api/middlewares/Translation.ts +++ b/src/api/middlewares/Translation.ts @@ -20,7 +20,7 @@ import fs from "fs"; import path from "path"; import i18next from "i18next"; import i18nextMiddleware from "i18next-http-middleware"; -import i18nextBackend from "i18next-node-fs-backend"; +import i18nextBackend from "i18next-fs-backend"; import { Router } from "express"; const ASSET_FOLDER_PATH = path.join(__dirname, "..", "..", "..", "assets"); -- cgit 1.5.1 From 810f5dd84cab8249f90276ce3acde5ffe6938c8d Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 17 Mar 2023 17:47:43 +0100 Subject: perf: cache jwt secret as key --- src/api/Server.ts | 8 ++++++-- src/api/middlewares/Authentication.ts | 17 +++++++++++++---- src/util/util/Token.ts | 3 ++- 3 files changed, 21 insertions(+), 7 deletions(-) (limited to 'src/api') diff --git a/src/api/Server.ts b/src/api/Server.ts index 49229494..ced82dce 100644 --- a/src/api/Server.ts +++ b/src/api/Server.ts @@ -32,7 +32,7 @@ import "missing-native-js-functions"; import morgan from "morgan"; import path from "path"; import { red } from "picocolors"; -import { Authentication, CORS } from "./middlewares/"; +import { CORS, initAuthentication } from "./middlewares/"; import { BodyParser } from "./middlewares/BodyParser"; import { ErrorHandler } from "./middlewares/ErrorHandler"; import { initRateLimits } from "./middlewares/RateLimit"; @@ -97,7 +97,7 @@ export class FosscordServer extends Server { // @ts-ignore this.app = api; - api.use(Authentication); + initAuthentication(api); await initRateLimits(api); await initTranslation(api); @@ -126,6 +126,10 @@ export class FosscordServer extends Server { app.use("/api/v9", api); app.use("/api", api); // allow unversioned requests + try { + require("./middlewares/TestClient").default(this.app); + // eslint-disable-next-line no-empty + } catch (error) {} this.app.use(ErrorHandler); Sentry.errorHandler(this.app); diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts index 771f0de8..e6e2f59a 100644 --- a/src/api/middlewares/Authentication.ts +++ b/src/api/middlewares/Authentication.ts @@ -18,8 +18,9 @@ import { checkToken, Config, Rights } from "@fosscord/util"; import * as Sentry from "@sentry/node"; -import { NextFunction, Request, Response } from "express"; +import { NextFunction, Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; +import { createSecretKey, KeyObject } from "crypto"; export const NO_AUTHORIZATION_ROUTES = [ // Authentication routes @@ -69,6 +70,16 @@ declare global { } } +let jwtPublicKey: KeyObject; + +// Initialize the jwt secret as a key object so it does not need to be regenerated for each request. +export function initAuthentication(api: Router) { + jwtPublicKey = createSecretKey( + Buffer.from(Config.get().security.jwtSecret), + ); + api.use(Authentication); +} + export async function Authentication( req: Request, res: Response, @@ -90,11 +101,9 @@ export async function Authentication( Sentry.setUser({ id: req.user_id }); try { - const { jwtSecret } = Config.get().security; - const { decoded, user } = await checkToken( req.headers.authorization, - jwtSecret, + jwtPublicKey, ); req.token = decoded; diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts index ffc442aa..67e4b879 100644 --- a/src/util/util/Token.ts +++ b/src/util/util/Token.ts @@ -19,6 +19,7 @@ import jwt, { VerifyOptions } from "jsonwebtoken"; import { Config } from "./Config"; import { User } from "../entities"; +import { KeyObject } from "crypto"; export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] }; @@ -62,7 +63,7 @@ async function checkEmailToken( export function checkToken( token: string, - jwtSecret: string, + jwtSecret: string | KeyObject, isEmailVerification = false, ): Promise { return new Promise((res, rej) => { -- cgit 1.5.1 From d086c053bbfb50a24403a270ce8d45f04ef000b7 Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 17 Mar 2023 17:49:12 +0100 Subject: perf: custom i18next middleware that only initializes when needed --- package.json | 1 - src/api/middlewares/Translation.ts | 56 ++++++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 19 deletions(-) (limited to 'src/api') diff --git a/package.json b/package.json index 5578849a..03cc7981 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,6 @@ "form-data": "^4.0.0", "i18next": "^22.4.12", "i18next-fs-backend": "^2.1.1", - "i18next-http-middleware": "^3.2.1", "image-size": "^1.0.2", "json-bigint": "^1.0.0", "jsonwebtoken": "^9.0.0", diff --git a/src/api/middlewares/Translation.ts b/src/api/middlewares/Translation.ts index 999d42a3..bf6ea034 100644 --- a/src/api/middlewares/Translation.ts +++ b/src/api/middlewares/Translation.ts @@ -18,11 +18,20 @@ import fs from "fs"; import path from "path"; -import i18next from "i18next"; -import i18nextMiddleware from "i18next-http-middleware"; +import i18next, { TFunction } from "i18next"; import i18nextBackend from "i18next-fs-backend"; import { Router } from "express"; +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Express { + interface Request { + t: TFunction; + language?: string; + } + } +} + const ASSET_FOLDER_PATH = path.join(__dirname, "..", "..", "..", "assets"); export async function initTranslation(router: Router) { @@ -34,21 +43,32 @@ export async function initTranslation(router: Router) { .filter((x) => x.endsWith(".json")) .map((x) => x.slice(0, x.length - 5)); - await i18next - .use(i18nextBackend) - .use(i18nextMiddleware.LanguageDetector) - .init({ - preload: languages, - // debug: true, - fallbackLng: "en", - ns, - backend: { - loadPath: - path.join(ASSET_FOLDER_PATH, "locales") + - "/{{lng}}/{{ns}}.json", - }, - load: "all", - }); + await i18next.use(i18nextBackend).init({ + preload: languages, + // debug: true, + fallbackLng: "en", + ns, + backend: { + loadPath: + path.join(ASSET_FOLDER_PATH, "locales") + + "/{{lng}}/{{ns}}.json", + }, + load: "all", + }); - router.use(i18nextMiddleware.handle(i18next, {})); + router.use((req, res, next) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + req.t = (key: string | string[], options?: any) => { + let lng = "en"; + if (req.headers["accept-language"]) { + lng = req.headers["accept-language"].split(",")[0]; + } + req.language = lng; + return i18next.t(key, { + ...options, + lng, + }); + }; + next(); + }); } -- cgit 1.5.1 From cae6fcc72a61608d594b3a7c3077c8e01a0b5045 Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 17 Mar 2023 19:30:54 +0100 Subject: fix: request language property --- src/api/middlewares/Translation.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/api') diff --git a/src/api/middlewares/Translation.ts b/src/api/middlewares/Translation.ts index bf6ea034..0e292962 100644 --- a/src/api/middlewares/Translation.ts +++ b/src/api/middlewares/Translation.ts @@ -57,13 +57,14 @@ export async function initTranslation(router: Router) { }); router.use((req, res, next) => { + let lng = "en"; + if (req.headers["accept-language"]) { + lng = req.headers["accept-language"].split(",")[0]; + } + req.language = lng; + // eslint-disable-next-line @typescript-eslint/no-explicit-any req.t = (key: string | string[], options?: any) => { - let lng = "en"; - if (req.headers["accept-language"]) { - lng = req.headers["accept-language"].split(",")[0]; - } - req.language = lng; return i18next.t(key, { ...options, lng, -- cgit 1.5.1 From 52f8508b38aa0a0aed67c3ac1fab72b35bbfe3bb Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Sat, 18 Mar 2023 04:12:16 +0100 Subject: fix: missing id in select query --- src/api/routes/guilds/#guild_id/templates.ts | 1 + src/util/util/Token.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/api') diff --git a/src/api/routes/guilds/#guild_id/templates.ts b/src/api/routes/guilds/#guild_id/templates.ts index 284bbccf..7c4a6961 100644 --- a/src/api/routes/guilds/#guild_id/templates.ts +++ b/src/api/routes/guilds/#guild_id/templates.ts @@ -39,6 +39,7 @@ const TemplateGuildProjection: (keyof Guild)[] = [ "system_channel_id", "system_channel_flags", "icon", + "id", ]; router.get("/", route({}), async (req: Request, res: Response) => { diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts index 67e4b879..0a8e7378 100644 --- a/src/util/util/Token.ts +++ b/src/util/util/Token.ts @@ -87,7 +87,7 @@ export function checkToken( const user = await User.findOne({ where: { id: decoded.id }, - select: ["data", "bot", "disabled", "deleted", "rights"], + select: ["id", "data", "bot", "disabled", "deleted", "rights"], }); if (!user) return rej("Invalid Token"); -- cgit 1.5.1 From 7b00e9905327c826b82fc47cfa22e37b9c5161a9 Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Sat, 18 Mar 2023 04:13:04 +0100 Subject: fix: use entity.save() instead of insert (needed for caching) --- src/api/routes/users/@me/notes.ts | 6 +++--- src/api/util/handlers/Message.ts | 2 +- src/util/util/Database.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/api') diff --git a/src/api/routes/users/@me/notes.ts b/src/api/routes/users/@me/notes.ts index 64730c1a..f82c3ca1 100644 --- a/src/api/routes/users/@me/notes.ts +++ b/src/api/routes/users/@me/notes.ts @@ -52,17 +52,17 @@ router.put("/:id", route({}), async (req: Request, res: Response) => { where: { owner: { id: owner.id }, target: { id: target.id } }, }) ) { - Note.update( + await Note.update( { owner: { id: owner.id }, target: { id: target.id } }, { owner, target, content: note }, ); } else { - Note.insert({ + await Note.create({ id: Snowflake.generate(), owner, target, content: note, - }); + }).save(); } } else { await Note.delete({ diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts index e514d400..8fbbf4bf 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts @@ -274,7 +274,7 @@ export async function sendMessage(opts: MessageOptions) { const message = await handleMessage({ ...opts, timestamp: new Date() }); await Promise.all([ - Message.insert(message), + message.save(), emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, diff --git a/src/util/util/Database.ts b/src/util/util/Database.ts index 5c5c8b4c..5d48ac03 100644 --- a/src/util/util/Database.ts +++ b/src/util/util/Database.ts @@ -127,10 +127,10 @@ export async function initDatabase(): Promise { // Manually insert every current migration to prevent this: await Promise.all( dbConnection.migrations.map((migration) => - Migration.insert({ + Migration.create({ name: migration.name, timestamp: Date.now(), - }), + }).save(), ), ); } else { -- cgit 1.5.1 From d97dbdf73cb4a5b21492575fce9b24cdcc337402 Mon Sep 17 00:00:00 2001 From: Samuel <34555296+Flam3rboy@users.noreply.github.com> Date: Sat, 18 Mar 2023 04:18:18 +0100 Subject: fix: remove proxy --- src/api/Server.ts | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/api') diff --git a/src/api/Server.ts b/src/api/Server.ts index ced82dce..fb32e511 100644 --- a/src/api/Server.ts +++ b/src/api/Server.ts @@ -126,10 +126,6 @@ export class FosscordServer extends Server { app.use("/api/v9", api); app.use("/api", api); // allow unversioned requests - try { - require("./middlewares/TestClient").default(this.app); - // eslint-disable-next-line no-empty - } catch (error) {} this.app.use(ErrorHandler); Sentry.errorHandler(this.app); -- cgit 1.5.1