Files
SeConectai_Web/app/(publico)/recuperar-senha/actions.ts
T

67 lines
1.7 KiB
TypeScript

"use server";
import { createHash, randomBytes } from "crypto";
import { db } from "@/lib/db";
import { sendMail } from "@/lib/mail";
import { checkRateLimit } from "@/lib/rate-limit";
export type RecuperarSenhaState = {
ok: boolean;
message?: string;
};
function hashToken(token: string) {
return createHash("sha256").update(token).digest("hex");
}
export async function solicitarRecuperacao(
_state: RecuperarSenhaState,
formData: FormData
): Promise<RecuperarSenhaState> {
const email = formData.get("email")?.toString().trim().toLowerCase();
const genericMessage = "Se o e-mail estiver cadastrado, enviaremos as instrucoes de redefinicao.";
const limit = checkRateLimit(`recuperar-senha:${email ?? "sem-email"}`, 5, 60 * 60 * 1000);
if (!limit.allowed) {
return { ok: true, message: genericMessage };
}
if (!email) {
return { ok: true, message: genericMessage };
}
const user = await db.user.findUnique({
where: { email },
select: { id: true, email: true }
});
if (!user) {
return { ok: true, message: genericMessage };
}
const token = randomBytes(32).toString("base64url");
const tokenHash = hashToken(token);
const expiraEm = new Date(Date.now() + 60 * 60 * 1000);
await db.passwordResetToken.create({
data: {
userId: user.id,
tokenHash,
expiraEm
}
});
const baseUrl = process.env.APP_URL ?? "http://localhost:3000";
const resetUrl = `${baseUrl}/redefinir-senha?token=${token}`;
await sendMail({
to: user.email,
subject: "Redefinicao de senha - Briefing SeConectai",
text: `Use o link abaixo para redefinir sua senha. Ele expira em 1 hora.\n\n${resetUrl}`
});
return { ok: true, message: genericMessage };
}
export { hashToken };