forked from hikmet4434/winninghunter
Uygulamada hicbir hiz siniri yoktu. /api/auth/login sinirsiz sifre denemesine, /api/auth/register sinirsiz sahte hesap acmaya aciкti (her hesap FREE plan kotasi alir = dogrudan maliyet). - src/lib/rate-limit.ts: IP basina sabit pencere sayaci, surec belleginde (ek altyapi yok). Cok instance'a cikilirsa Redis/Postgres'e tasinmali. - giris 10/15dk — sayac IP+eposta bazli: tek IP'den farkli hesaplara saldiri da yavaslar - kayit 5/saat - ads/search 60/dk — kota kontrolu zaten var, bu limit agir sorgu seliyle veritabanini bogmayi engeller - 429 + Retry-After + Turkce mesaj - IP: x-forwarded-for'un SON elemani (ilk eleman istemci tarafindan uydurulabilir; son elemani bizim proxy ekler) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
24 lines
1.1 KiB
TypeScript
24 lines
1.1 KiB
TypeScript
import bcrypt from "bcryptjs";
|
||
import { NextResponse } from "next/server";
|
||
import { z } from "zod";
|
||
import { prisma } from "@/lib/db";
|
||
import { createSession } from "@/lib/auth/session";
|
||
import { hizSiniriAsimi } from "@/lib/rate-limit";
|
||
|
||
const schema = z.object({ email: z.string().email(), password: z.string().min(1) });
|
||
|
||
export async function POST(req: Request) {
|
||
const body = schema.parse(await req.json());
|
||
// Sayaç e-posta bazlı da tutulur: tek IP'den farklı hesaplara saldırı da yavaşlar.
|
||
const sinir = hizSiniriAsimi(req, "giris", body.email.trim().toLowerCase());
|
||
if (sinir) return sinir;
|
||
|
||
const user = await prisma.user.findUnique({ where: { email: body.email } });
|
||
if (!user?.passwordHash) return NextResponse.json({ error: "INVALID_CREDENTIALS" }, { status: 401 });
|
||
const ok = await bcrypt.compare(body.password, user.passwordHash);
|
||
if (!ok) return NextResponse.json({ error: "INVALID_CREDENTIALS" }, { status: 401 });
|
||
await prisma.user.update({ where: { id: user.id }, data: { lastLoginAt: new Date() } });
|
||
await createSession(user.id);
|
||
return NextResponse.json({ ok: true });
|
||
}
|