diff --git a/bun.lock b/bun.lock index ca198071..885763f4 100644 --- a/bun.lock +++ b/bun.lock @@ -31,6 +31,7 @@ "dotenv": "^16.4.5", "dotenv-cli": "^7.4.2", "firebase-admin": "^12.2.0", + "lru-cache": "^11.0.2", "hono": "^4.7.1", "sharp": "^0.33.5", "socket.io": "^4.7.5", @@ -902,7 +903,7 @@ "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], - "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + "lru-cache": ["lru-cache@11.0.2", "", {}, "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA=="], "lru-memoizer": ["lru-memoizer@2.3.0", "", { "dependencies": { "lodash.clonedeep": "^4.5.0", "lru-cache": "6.0.0" } }, "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug=="], @@ -1274,6 +1275,8 @@ "log-update/slice-ansi": ["slice-ansi@7.1.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg=="], + "lru-memoizer/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + "nearley/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], diff --git a/server/package.json b/server/package.json index 3e4c2865..2a056c65 100644 --- a/server/package.json +++ b/server/package.json @@ -24,6 +24,7 @@ "dotenv": "^16.4.5", "dotenv-cli": "^7.4.2", "firebase-admin": "^12.2.0", + "lru-cache": "^11.0.2", "hono": "^4.7.1", "sharp": "^0.33.5", "socket.io": "^4.7.5", diff --git a/server/src/firebase/auth/db.ts b/server/src/firebase/auth/db.ts index eb207415..9f4865a5 100644 --- a/server/src/firebase/auth/db.ts +++ b/server/src/firebase/auth/db.ts @@ -1,24 +1,23 @@ -import type { IDToken, UserID } from "common/types"; -import { getGUID, getGUIDFromToken } from "./lib"; - +import type { GUID, IDToken, UserID } from "common/types"; import type { Context } from "hono"; +import { LRUCache } from "lru-cache"; import { prisma } from "../../database/client"; import { error } from "../../lib/error"; -/** - * REQUIRE: cookieParser middleware before this - * THROWS: if idToken is not present in request cookie, or when the token is not valid. - * Expected use case: - * ```js - * let userId: number; - * try { - * userId = await getUserId(req); - * } catch { - * return res.status(401).send("auth error"); - * } - * ``` - **/ +import { getGUID, getGUIDFromToken } from "./lib"; + +const guid_userid_cache = new LRUCache({ + max: 100, +}); + export async function getUserId(c: Context): Promise { const guid = await getGUID(c); + + const cache = guid_userid_cache.get(guid); + if (cache) { + console.log(`[CACHE HIT] ${guid} -> ${cache}`); + return cache; + } + const user = await prisma.user.findUnique({ where: { guid: guid, @@ -28,17 +27,28 @@ export async function getUserId(c: Context): Promise { }, }); if (!user) error("auth error: unauthorized", 401); + guid_userid_cache.set(guid, user.id); return user.id; } export async function getUserIdFromToken(token: IDToken): Promise { const guid = await getGUIDFromToken(token); + + const cache = guid_userid_cache.get(guid); + if (cache) { + return cache; + } + const user = await prisma.user.findUnique({ where: { guid: guid, }, + select: { + id: true, + }, }); if (!user) error("User not found!", 401); + guid_userid_cache.set(guid, user.id); return user.id; }