70 lines
1.7 KiB
TypeScript
70 lines
1.7 KiB
TypeScript
"use server";
|
|
|
|
import argon2 from "argon2";
|
|
import { redirect } from "next/navigation";
|
|
import { z } from "zod";
|
|
import { db } from "@/lib/db";
|
|
import { hashToken } from "@/app/(publico)/recuperar-senha/actions";
|
|
|
|
const redefinirSenhaSchema = z
|
|
.object({
|
|
token: z.string().min(1),
|
|
senha: z.string().min(8, "A senha precisa ter pelo menos 8 caracteres."),
|
|
confirmarSenha: z.string()
|
|
})
|
|
.refine((data) => data.senha === data.confirmarSenha, {
|
|
path: ["confirmarSenha"],
|
|
message: "As senhas nao conferem."
|
|
});
|
|
|
|
export type RedefinirSenhaState = {
|
|
ok: boolean;
|
|
message?: string;
|
|
};
|
|
|
|
export async function redefinirSenha(
|
|
_state: RedefinirSenhaState,
|
|
formData: FormData
|
|
): Promise<RedefinirSenhaState> {
|
|
const parsed = redefinirSenhaSchema.safeParse({
|
|
token: formData.get("token"),
|
|
senha: formData.get("senha"),
|
|
confirmarSenha: formData.get("confirmarSenha")
|
|
});
|
|
|
|
if (!parsed.success) {
|
|
return {
|
|
ok: false,
|
|
message: parsed.error.issues[0]?.message ?? "Revise os dados informados."
|
|
};
|
|
}
|
|
|
|
const tokenHash = hashToken(parsed.data.token);
|
|
const resetToken = await db.passwordResetToken.findUnique({
|
|
where: { tokenHash },
|
|
select: {
|
|
id: true,
|
|
userId: true,
|
|
expiraEm: true,
|
|
usadoEm: true
|
|
}
|
|
});
|
|
|
|
if (!resetToken || resetToken.usadoEm || resetToken.expiraEm < new Date()) {
|
|
return { ok: false, message: "Link invalido ou expirado." };
|
|
}
|
|
|
|
await db.$transaction([
|
|
db.user.update({
|
|
where: { id: resetToken.userId },
|
|
data: { senhaHash: await argon2.hash(parsed.data.senha) }
|
|
}),
|
|
db.passwordResetToken.update({
|
|
where: { id: resetToken.id },
|
|
data: { usadoEm: new Date() }
|
|
})
|
|
]);
|
|
|
|
redirect("/login");
|
|
}
|