Aktueller Stand

This commit is contained in:
2026-01-15 23:18:42 +01:00
parent 46eae2a2a9
commit dcf45bac3d
32 changed files with 2625 additions and 395 deletions

57
lib/rate-limit.ts Normal file
View File

@@ -0,0 +1,57 @@
import { prisma } from "./prisma";
type RateLimitResult = {
ok: boolean;
remaining: number;
resetAt: Date;
};
const parseNumber = (value: string | undefined, fallback: number) => {
if (!value) return fallback;
const parsed = Number(value);
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
};
export const getRateLimitConfig = (envKey: string, defaultLimit: number) => {
const limit = parseNumber(process.env[envKey], defaultLimit);
const windowMinutes = parseNumber(process.env.RATE_LIMIT_WINDOW_MINUTES, 15);
return { limit, windowMs: windowMinutes * 60 * 1000 };
};
export async function checkRateLimit({
key,
limit,
windowMs
}: {
key: string;
limit: number;
windowMs: number;
}): Promise<RateLimitResult> {
const now = new Date();
const resetAt = new Date(now.getTime() + windowMs);
const existing = await prisma.rateLimit.findUnique({ where: { key } });
if (!existing || existing.resetAt <= now) {
await prisma.rateLimit.upsert({
where: { key },
update: { count: 1, resetAt },
create: { key, count: 1, resetAt }
});
return { ok: true, remaining: Math.max(0, limit - 1), resetAt };
}
if (existing.count >= limit) {
return { ok: false, remaining: 0, resetAt: existing.resetAt };
}
const updated = await prisma.rateLimit.update({
where: { key },
data: { count: { increment: 1 } }
});
return {
ok: true,
remaining: Math.max(0, limit - updated.count),
resetAt: updated.resetAt
};
}