diff --git a/lib/cache.ts b/lib/cache.ts index 528dd012..e63a53bb 100644 --- a/lib/cache.ts +++ b/lib/cache.ts @@ -49,6 +49,11 @@ async function deleteSession(id) { return deleteObject(`session:${id}`); } +async function fetchUserBlock(userId: string) { + const key = `user:block:${userId}`; + return redis.get(key); +} + export default { fetchWebsite, storeWebsite, @@ -59,5 +64,6 @@ export default { fetchSession, storeSession, deleteSession, + fetchUserBlock, enabled: redis.enabled, }; diff --git a/lib/middleware.ts b/lib/middleware.ts index 79c48404..1fd13b09 100644 --- a/lib/middleware.ts +++ b/lib/middleware.ts @@ -1,4 +1,10 @@ -import { createMiddleware, unauthorized, badRequest, parseSecureToken } from 'next-basics'; +import { + createMiddleware, + unauthorized, + badRequest, + parseSecureToken, + tooManyRequest, +} from 'next-basics'; import debug from 'debug'; import cors from 'cors'; import { validate } from 'uuid'; @@ -30,6 +36,9 @@ export const useSession = createMiddleware(async (req, res, next) => { (req as any).session = session; } catch (e: any) { + if (e.message === 'Usage Limit.') { + return tooManyRequest(res, e.message); + } return badRequest(res, e.message); } diff --git a/lib/session.ts b/lib/session.ts index 937bfef2..32f3bdc8 100644 --- a/lib/session.ts +++ b/lib/session.ts @@ -6,6 +6,7 @@ import { CollectRequestBody, NextApiRequestCollect } from 'pages/api/send'; import { createSession } from 'queries'; import { validate } from 'uuid'; import { loadSession, loadWebsite } from './query'; +import cache from './cache'; export async function findSession(req: NextApiRequestCollect) { const { payload } = getJsonBody(req); @@ -21,6 +22,8 @@ export async function findSession(req: NextApiRequestCollect) { const result = await parseToken(cacheToken, secret()); if (result) { + await checkUserBlock(result?.ownerId); + return result; } } @@ -39,6 +42,8 @@ export async function findSession(req: NextApiRequestCollect) { throw new Error(`Website not found: ${websiteId}.`); } + await checkUserBlock(website.userId); + const { userAgent, browser, os, ip, country, subdivision1, subdivision2, city, device } = await getClientInfo(req, payload); const sessionId = uuid(websiteId, hostname, ip, userAgent); @@ -88,5 +93,11 @@ export async function findSession(req: NextApiRequestCollect) { } } - return session; + return { ...session, ownerId: website.userId }; +} + +async function checkUserBlock(userId: string) { + if (process.env.ENABLE_BLOCKER && (await cache.fetchUserBlock(userId))) { + throw new Error('Usage Limit.'); + } } diff --git a/pages/api/send.ts b/pages/api/send.ts index 51ddb980..df7ceb6e 100644 --- a/pages/api/send.ts +++ b/pages/api/send.ts @@ -28,6 +28,7 @@ export interface NextApiRequestCollect extends NextApiRequest { session: { id: string; websiteId: string; + ownerId: string; hostname: string; browser: string; os: string;