Files
calendar/apps/web/app/api/auth/forgot-password/route.ts
T

50 lines
1.8 KiB
TypeScript

import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseRequestData } from "app/api/parseRequestData";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { passwordResetRequest } from "@calcom/features/auth/lib/passwordResetRequest";
import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError";
import { emailSchema } from "@calcom/lib/emailSchema";
import prisma from "@calcom/prisma";
import { piiHasher } from "@calcom/lib/server/PiiHasher";
async function handler(req: NextRequest) {
const body = await parseRequestData(req);
const email = emailSchema.transform((val) => val.toLowerCase()).safeParse(body?.email);
if (!email.success) {
return NextResponse.json({ message: "email is required" }, { status: 400 });
}
// fallback to email if ip is not present
let ip = (req.headers.get("x-real-ip") as string) ?? email.data;
const forwardedFor = req.headers.get("x-forwarded-for") as string;
if (!ip && forwardedFor) {
ip = forwardedFor?.split(",").at(0) ?? email.data;
}
// 10 requests per minute
await checkRateLimitAndThrowError({
rateLimitingType: "core",
identifier: piiHasher.hash(ip),
});
try {
const user = await prisma.user.findUnique({
where: { email: email.data },
select: { name: true, email: true, locale: true },
});
// Don't leak info about whether the user exists
if (user) passwordResetRequest(user).catch(console.error);
return NextResponse.json({ message: "password_reset_email_sent" }, { status: 201 });
} catch (reason) {
console.error(reason);
return NextResponse.json({ message: "Unable to create password reset request" }, { status: 500 });
}
}
export const POST = defaultResponderForAppDir(handler);