From c5345b01bb756c6055d529f0bc5e61db47a887a2 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 10:25:57 -0700 Subject: [PATCH 1/4] Update tsconfig. --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 0faf5fbc..9d860a22 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,6 @@ "jsx": "preserve", "incremental": false }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"], "exclude": ["node_modules"] } From f794b5674b3b7d6124515fb4f5f090add29f30a2 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 11:26:41 -0700 Subject: [PATCH 2/4] Update team/website permission check. --- src/lib/auth.ts | 8 ++++---- src/lib/{date.js => date.ts} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename src/lib/{date.js => date.ts} (100%) diff --git a/src/lib/auth.ts b/src/lib/auth.ts index a93f89c7..4a42d85d 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -4,7 +4,7 @@ import debug from 'debug'; import { PERMISSIONS, ROLE_PERMISSIONS, SHARE_TOKEN_HEADER } from 'lib/constants'; import { secret } from 'lib/crypto'; import { createSecureToken, ensureArray, getRandomChars, parseToken } from 'next-basics'; -import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite, getWebsitesByUserId } from 'queries'; +import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite } from 'queries'; import { loadWebsite } from './load'; import { Auth } from './types'; @@ -60,11 +60,11 @@ export async function canViewWebsite({ user, shareToken }: Auth, websiteId: stri export async function canCreateWebsite({ user, grant }: Auth) { if (cloudMode) { - if (grant.find(a => a === PERMISSIONS.websiteCreate)) { + if (grant?.find(a => a === PERMISSIONS.websiteCreate)) { return true; } - return (await getWebsitesByUserId(user.id)).count < Number(process.env.WEBSITE_LIMIT); + return false; } if (user.isAdmin) { @@ -120,7 +120,7 @@ export async function canDeleteReport(auth: Auth, report: Report) { export async function canCreateTeam({ user, grant }: Auth) { if (cloudMode) { - if (grant.find(a => a === PERMISSIONS.teamCreate)) { + if (grant?.find(a => a === PERMISSIONS.teamCreate)) { return true; } diff --git a/src/lib/date.js b/src/lib/date.ts similarity index 100% rename from src/lib/date.js rename to src/lib/date.ts From d43ab3e5593572895c2d6c443291fd4073f1ec9e Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 11:55:45 -0700 Subject: [PATCH 3/4] Roll back session insert. --- src/lib/session.ts | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/lib/session.ts b/src/lib/session.ts index 5eb7398a..85c173c5 100644 --- a/src/lib/session.ts +++ b/src/lib/session.ts @@ -1,12 +1,27 @@ -import { secret, uuid, isUuid } from 'lib/crypto'; +import { isUuid, secret, uuid } from 'lib/crypto'; import { getClientInfo, getJsonBody } from 'lib/detect'; import { parseToken } from 'next-basics'; import { CollectRequestBody, NextApiRequestCollect } from 'pages/api/send'; import { createSession } from 'queries'; import cache from './cache'; +import clickhouse from './clickhouse'; import { loadSession, loadWebsite } from './load'; -export async function findSession(req: NextApiRequestCollect) { +export async function findSession(req: NextApiRequestCollect): Promise<{ + id: any; + websiteId: string; + hostname: string; + browser: string; + os: any; + device: string; + screen: string; + language: string; + country: any; + subdivision1: any; + subdivision2: any; + city: any; + ownerId: string; +}> { const { payload } = getJsonBody(req); if (!payload) { @@ -53,6 +68,25 @@ export async function findSession(req: NextApiRequestCollect) { const sessionId = uuid(websiteId, hostname, ip, userAgent); + // Clickhouse does not require session lookup + if (clickhouse.enabled) { + return { + id: sessionId, + websiteId, + hostname, + browser, + os: os as any, + device, + screen, + language, + country, + subdivision1, + subdivision2, + city, + ownerId: website.userId, + }; + } + // Find session let session = await loadSession(sessionId); From 06de67ec55821051480f5ca1ad3e612cb0cb7809 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 12:17:32 -0700 Subject: [PATCH 4/4] Add 1 day cache limit to user/website/session --- src/lib/cache.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/lib/cache.ts b/src/lib/cache.ts index bc46c23d..c54eda2e 100644 --- a/src/lib/cache.ts +++ b/src/lib/cache.ts @@ -2,17 +2,20 @@ import { User, Website } from '@prisma/client'; import redis from '@umami/redis-client'; import { getSession, getUserById, getWebsiteById } from '../queries'; -const { fetchObject, storeObject, deleteObject } = redis; +const { fetchObject, storeObject, deleteObject, expire } = redis; async function fetchWebsite(id): Promise { - return fetchObject(`website:${id}`, () => getWebsiteById(id)); + return fetchObject(`website:${id}`, () => getWebsiteById(id), 86400); } async function storeWebsite(data) { const { id } = data; const key = `website:${id}`; - return storeObject(key, data); + const obj = await storeObject(key, data); + await expire(key, 86400); + + return obj; } async function deleteWebsite(id) { @@ -20,14 +23,17 @@ async function deleteWebsite(id) { } async function fetchUser(id): Promise { - return fetchObject(`user:${id}`, () => getUserById(id, { includePassword: true })); + return fetchObject(`user:${id}`, () => getUserById(id, { includePassword: true }), 86400); } async function storeUser(data) { const { id } = data; const key = `user:${id}`; - return storeObject(key, data); + const obj = await storeObject(key, data); + await expire(key, 86400); + + return obj; } async function deleteUser(id) { @@ -35,14 +41,17 @@ async function deleteUser(id) { } async function fetchSession(id) { - return fetchObject(`session:${id}`, () => getSession(id)); + return fetchObject(`session:${id}`, () => getSession(id), 86400); } async function storeSession(data) { const { id } = data; const key = `session:${id}`; - return storeObject(key, data); + const obj = await storeObject(key, data); + await expire(key, 86400); + + return obj; } async function deleteSession(id) {