fix(chat): add ip-based rate limiting to prevent session rotation abuse (#1436)
This commit is contained in:
parent
211cb96a96
commit
ad47aa0ee0
7 changed files with 87 additions and 5 deletions
|
|
@ -9,14 +9,14 @@ export const entitlementsByUserType: Record<UserType, Entitlements> = {
|
|||
* For users without an account
|
||||
*/
|
||||
guest: {
|
||||
maxMessagesPerDay: 20,
|
||||
maxMessagesPerDay: 10,
|
||||
},
|
||||
|
||||
/*
|
||||
* For users with an account
|
||||
*/
|
||||
regular: {
|
||||
maxMessagesPerDay: 50,
|
||||
maxMessagesPerDay: 10,
|
||||
},
|
||||
|
||||
/*
|
||||
|
|
|
|||
42
lib/ratelimit.ts
Normal file
42
lib/ratelimit.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { createClient } from "redis";
|
||||
|
||||
import { isProductionEnvironment } from "@/lib/constants";
|
||||
import { ChatbotError } from "@/lib/errors";
|
||||
|
||||
const MAX_MESSAGES_PER_DAY = 10;
|
||||
const TTL_SECONDS = 60 * 60 * 24;
|
||||
|
||||
let client: ReturnType<typeof createClient> | null = null;
|
||||
|
||||
function getClient() {
|
||||
if (!client && process.env.REDIS_URL) {
|
||||
client = createClient({ url: process.env.REDIS_URL });
|
||||
client.on("error", () => {});
|
||||
client.connect().catch(() => {
|
||||
client = null;
|
||||
});
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
export async function checkIpRateLimit(ip: string | undefined) {
|
||||
if (!isProductionEnvironment || !ip) return;
|
||||
|
||||
const redis = getClient();
|
||||
if (!redis?.isReady) return;
|
||||
|
||||
try {
|
||||
const key = `ip-rate-limit:${ip}`;
|
||||
const [count] = await redis
|
||||
.multi()
|
||||
.incr(key)
|
||||
.expire(key, TTL_SECONDS, "NX")
|
||||
.exec();
|
||||
|
||||
if (typeof count === "number" && count > MAX_MESSAGES_PER_DAY) {
|
||||
throw new ChatbotError("rate_limit:chat");
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof ChatbotError) throw error;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue