import { prisma } from "./prisma"; import nodemailer from "nodemailer"; import crypto from "crypto"; const transporter = nodemailer.createTransport({ host: "smtp.gmail.com", port: 587, secure: false, auth: { user: process.env.GMAIL_USER, pass: process.env.GMAIL_APP_PASSWORD, }, }); export async function enviarMagicLink(email: string): Promise<{ ok: boolean; error?: string }> { const cliente = await prisma.cliente.findUnique({ where: { email } }); if (!cliente) return { ok: false, error: "Email no registrado" }; await prisma.magicToken.updateMany({ where: { clienteId: cliente.id, usado: false }, data: { usado: true }, }); const token = crypto.randomBytes(32).toString("hex"); const expiresAt = new Date(Date.now() + 15 * 60 * 1000); await prisma.magicToken.create({ data: { clienteId: cliente.id, token, expiresAt }, }); const link = `${process.env.MAGIC_LINK_BASE_URL}/cliente/auth?token=${token}`; await transporter.sendMail({ from: `"Taller" <${process.env.GMAIL_USER}>`, to: email, subject: "Tu link de acceso al taller", html: `

Hola ${cliente.nombre}!

Hacé click en el siguiente botón para acceder a tu cuenta:

Acceder al taller

Este link expira en 15 minutos. Si no lo pediste, ignorá este email.

`, }); return { ok: true }; } export async function validarMagicToken(token: string) { const registro = await prisma.magicToken.findUnique({ where: { token }, include: { cliente: true }, }); if (!registro || registro.usado || registro.expiresAt < new Date()) { return null; } await prisma.magicToken.update({ where: { id: registro.id }, data: { usado: true }, }); return registro.cliente; }