From 4d6ec631f74bac45fbcee0bd8e4ae91c19fcd134 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 10 Feb 2025 21:07:18 -0800 Subject: [PATCH] Updated redis logic. --- package.json | 2 +- src/app/api/auth/login/route.ts | 17 +++++++++-------- src/app/api/auth/logout/route.ts | 8 +++----- src/app/api/auth/sso/route.ts | 4 ++-- src/lib/auth.ts | 18 ++++++++---------- src/lib/load.ts | 14 +++++--------- src/lib/redis.ts | 17 +++++++++++++++++ src/queries/prisma/website.ts | 10 +++------- yarn.lock | 8 ++++---- 9 files changed, 52 insertions(+), 46 deletions(-) create mode 100644 src/lib/redis.ts diff --git a/package.json b/package.json index 5a3546ee..a438a539 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@react-spring/web": "^9.7.3", "@tanstack/react-query": "^5.28.6", "@umami/prisma-client": "^0.14.0", - "@umami/redis-client": "^0.24.0", + "@umami/redis-client": "^0.25.0", "bcryptjs": "^2.4.3", "chalk": "^4.1.1", "chart.js": "^4.4.2", diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts index 0b48fe83..766c788c 100644 --- a/src/app/api/auth/login/route.ts +++ b/src/app/api/auth/login/route.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { checkPassword } from '@/lib/auth'; import { createSecureToken } from '@/lib/jwt'; -import { redisEnabled } from '@umami/redis-client'; +import redis from '@/lib/redis'; import { getUserByUsername } from '@/queries'; import { json, unauthorized } from '@/lib/response'; import { parseRequest } from '@/lib/request'; @@ -29,15 +29,16 @@ export async function POST(request: Request) { return unauthorized(); } - if (redisEnabled) { - const token = await saveAuth({ userId: user.id }); - - return json({ token, user }); - } - - const token = createSecureToken({ userId: user.id }, secret()); const { id, role, createdAt } = user; + let token = null; + + if (redis.enabled) { + token = await saveAuth({ userId: id, role }); + } else { + token = createSecureToken({ userId: user.id, role }, secret()); + } + return json({ token, user: { id, username, role, createdAt, isAdmin: role === ROLES.admin }, diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts index 22bb3091..7bf0a813 100644 --- a/src/app/api/auth/logout/route.ts +++ b/src/app/api/auth/logout/route.ts @@ -1,13 +1,11 @@ -import { getClient, redisEnabled } from '@umami/redis-client'; +import redis from '@/lib/redis'; import { ok } from '@/lib/response'; export async function POST(request: Request) { - if (redisEnabled) { - const redis = getClient(); - + if (redis.enabled) { const token = request.headers.get('authorization')?.split(' ')?.[1]; - await redis.del(token); + await redis.client.del(token); } return ok(); diff --git a/src/app/api/auth/sso/route.ts b/src/app/api/auth/sso/route.ts index 4a713424..fc8fb9bf 100644 --- a/src/app/api/auth/sso/route.ts +++ b/src/app/api/auth/sso/route.ts @@ -1,4 +1,4 @@ -import { redisEnabled } from '@umami/redis-client'; +import redis from '@/lib/redis'; import { json } from '@/lib/response'; import { parseRequest } from '@/lib/request'; import { saveAuth } from '@/lib/auth'; @@ -10,7 +10,7 @@ export async function POST(request: Request) { return error(); } - if (redisEnabled) { + if (redis.enabled) { const token = await saveAuth({ userId: auth.user.id }, 86400); return json({ user: auth.user, token }); diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 4ce90706..d67566b8 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,6 +1,6 @@ import bcrypt from 'bcryptjs'; import { Report } from '@prisma/client'; -import { getClient, redisEnabled } from '@umami/redis-client'; +import redis from '@/lib/redis'; import debug from 'debug'; import { PERMISSIONS, ROLE_PERMISSIONS, ROLES, SHARE_TOKEN_HEADER } from '@/lib/constants'; import { secret, getRandomChars } from '@/lib/crypto'; @@ -31,10 +31,8 @@ export async function checkAuth(request: Request) { if (userId) { user = await getUser(userId); - } else if (redisEnabled && authKey) { - const redis = getClient(); - - const key = await redis.get(authKey); + } else if (redis.enabled && authKey) { + const key = await redis.client.get(authKey); if (key?.userId) { user = await getUser(key.userId); @@ -66,12 +64,12 @@ export async function checkAuth(request: Request) { export async function saveAuth(data: any, expire = 0) { const authKey = `auth:${getRandomChars(32)}`; - const redis = getClient(); + if (redis.enabled) { + await redis.client.set(authKey, data); - await redis.set(authKey, data); - - if (expire) { - await redis.expire(authKey, expire); + if (expire) { + await redis.client.expire(authKey, expire); + } } return createSecureToken({ authKey }, secret()); diff --git a/src/lib/load.ts b/src/lib/load.ts index 2b7f7de4..d9aa23c2 100644 --- a/src/lib/load.ts +++ b/src/lib/load.ts @@ -1,14 +1,12 @@ import { Website, Session } from '@prisma/client'; -import { getClient, redisEnabled } from '@umami/redis-client'; +import redis from '@/lib/redis'; import { getWebsiteSession, getWebsite } from '@/queries'; export async function fetchWebsite(websiteId: string): Promise { let website = null; - if (redisEnabled) { - const redis = getClient(); - - website = await redis.fetch(`website:${websiteId}`, () => getWebsite(websiteId), 86400); + if (redis.enabled) { + website = await redis.client.fetch(`website:${websiteId}`, () => getWebsite(websiteId), 86400); } else { website = await getWebsite(websiteId); } @@ -23,10 +21,8 @@ export async function fetchWebsite(websiteId: string): Promise { export async function fetchSession(websiteId: string, sessionId: string): Promise { let session = null; - if (redisEnabled) { - const redis = getClient(); - - session = await redis.fetch( + if (redis.enabled) { + session = await redis.client.fetch( `session:${sessionId}`, () => getWebsiteSession(websiteId, sessionId), 86400, diff --git a/src/lib/redis.ts b/src/lib/redis.ts new file mode 100644 index 00000000..868b408a --- /dev/null +++ b/src/lib/redis.ts @@ -0,0 +1,17 @@ +import { REDIS, UmamiRedisClient } from '@umami/redis-client'; + +const enabled = !!process.env.REDIS_URL; + +function getClient() { + const client = new UmamiRedisClient(process.env.REDIS_URL); + + if (process.env.NODE_ENV !== 'production') { + global[REDIS] = client; + } + + return client; +} + +const client = global[REDIS] || getClient(); + +export default { client, enabled }; diff --git a/src/queries/prisma/website.ts b/src/queries/prisma/website.ts index 96463501..25328914 100644 --- a/src/queries/prisma/website.ts +++ b/src/queries/prisma/website.ts @@ -1,5 +1,5 @@ import { Prisma, Website } from '@prisma/client'; -import { getClient } from '@umami/redis-client'; +import redis from '@/lib/redis'; import prisma from '@/lib/prisma'; import { PageResult, PageParams } from '@/lib/types'; import WebsiteFindManyArgs = Prisma.WebsiteFindManyArgs; @@ -182,9 +182,7 @@ export async function resetWebsite( }), ]).then(async data => { if (cloudMode) { - const redis = getClient(); - - await redis.set(`website:${websiteId}`, data[3]); + await redis.client.set(`website:${websiteId}`, data[3]); } return data; @@ -227,9 +225,7 @@ export async function deleteWebsite( }), ]).then(async data => { if (cloudMode) { - const redis = getClient(); - - await redis.del(`website:${websiteId}`); + await redis.client.del(`website:${websiteId}`); } return data; diff --git a/yarn.lock b/yarn.lock index 2c6eb5f9..3396d55a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3402,10 +3402,10 @@ chalk "^4.1.2" debug "^4.3.4" -"@umami/redis-client@^0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@umami/redis-client/-/redis-client-0.24.0.tgz#8af489250396be76bc0906766343620589774c4b" - integrity sha512-yUZmC87H5QZKNA6jD9k/7d8WDaXQTDROlpyK7S+V2csD96eAnMNi7JsWAVWx9T/584QKD8DsSIy87PTWq1HNPw== +"@umami/redis-client@^0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@umami/redis-client/-/redis-client-0.25.0.tgz#8bf01f22ceb3b90e15e59ab8daf44f838b83a6a7" + integrity sha512-j2GUehtrUfNPuikmcVXucgnL04gQOtbLiG20NqdlUXlDA/ebkV/waDfcYtMLuvXOFwiEeTatqPFEfXYuLDwJWw== dependencies: debug "^4.3.4" redis "^4.5.1"