lomavuokraus/app/api/auth/reset/route.ts
Tero Halla-aho 0bb709d9c5
Some checks failed
CI / checks (push) Has been cancelled
chore: fix audit alerts and formatting
2026-02-04 12:43:03 +02:00

63 lines
1.7 KiB
TypeScript

import { NextResponse } from "next/server";
import { prisma } from "../../../../lib/prisma";
import { hashPassword } from "../../../../lib/auth";
import { addHours } from "../../../../lib/tokens";
export async function POST(req: Request) {
try {
const body = await req.json();
const token = String(body.token ?? "").trim();
const password = String(body.password ?? "");
if (!token || !password) {
return NextResponse.json(
{ error: "Missing token or password" },
{ status: 400 },
);
}
if (password.length < 8) {
return NextResponse.json(
{ error: "Password must be at least 8 characters" },
{ status: 400 },
);
}
const record = await prisma.verificationToken.findUnique({
where: { token },
include: { user: true },
});
if (
!record ||
record.type !== "password_reset" ||
record.consumedAt ||
record.expiresAt < new Date()
) {
return NextResponse.json(
{ error: "Invalid or expired token" },
{ status: 400 },
);
}
const passwordHash = await hashPassword(password);
await prisma.$transaction([
prisma.user.update({
where: { id: record.userId },
data: { passwordHash },
}),
prisma.verificationToken.update({
where: { id: record.id },
data: { consumedAt: new Date(), expiresAt: addHours(-1) },
}),
]);
return NextResponse.json({ ok: true });
} catch (error) {
console.error("Password reset error", error);
return NextResponse.json(
{ error: "Failed to reset password" },
{ status: 500 },
);
}
}
export const dynamic = "force-dynamic";