53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
import type { NextApiRequest, NextApiResponse } from "next";
|
|
import { z } from "zod";
|
|
|
|
import { passwordResetRequest } from "@calcom/features/auth/lib/passwordResetRequest";
|
|
import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError";
|
|
import { defaultHandler } from "@calcom/lib/server";
|
|
import prisma from "@calcom/prisma";
|
|
|
|
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
const email = z
|
|
.string()
|
|
.email()
|
|
.transform((val) => val.toLowerCase())
|
|
.safeParse(req.body?.email);
|
|
|
|
if (!email.success) {
|
|
return res.status(400).json({ message: "email is required" });
|
|
}
|
|
|
|
// fallback to email if ip is not present
|
|
let ip = (req.headers["x-real-ip"] as string) ?? email.data;
|
|
|
|
const forwardedFor = req.headers["x-forwarded-for"] as string;
|
|
if (!ip && forwardedFor) {
|
|
ip = forwardedFor?.split(",").at(0) ?? email.data;
|
|
}
|
|
|
|
// 10 requests per minute
|
|
|
|
await checkRateLimitAndThrowError({
|
|
rateLimitingType: "core",
|
|
identifier: 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) return res.status(201).json({ message: "password_reset_email_sent" });
|
|
await passwordResetRequest(user);
|
|
return res.status(201).json({ message: "password_reset_email_sent" });
|
|
} catch (reason) {
|
|
console.error(reason);
|
|
return res.status(500).json({ message: "Unable to create password reset request" });
|
|
}
|
|
}
|
|
|
|
export default defaultHandler({
|
|
POST: Promise.resolve({ default: handler }),
|
|
});
|