// server/api/auth/login.post.js import jwt from "jsonwebtoken"; import { Resend } from "resend"; import Member from "../../models/member.js"; import { connectDB } from "../../utils/mongoose.js"; import { validateBody } from "../../utils/validateBody.js"; import { emailSchema } from "../../utils/schemas.js"; const resend = new Resend(process.env.RESEND_API_KEY); export default defineEventHandler(async (event) => { // Connect to database await connectDB(); const { email } = await validateBody(event, emailSchema); const GENERIC_MESSAGE = "If this email is registered, we've sent a login link."; const member = await Member.findOne({ email }); if (!member) { // Return same response shape to prevent enumeration return { success: true, message: GENERIC_MESSAGE, }; } // Generate magic link token (use runtime config for consistency with verify/requireAuth) const config = useRuntimeConfig(event); const token = jwt.sign( { memberId: member._id }, config.jwtSecret, { expiresIn: "15m" }, ); // Get the base URL for the magic link const headers = getHeaders(event); const baseUrl = process.env.BASE_URL || `${headers.host?.includes("localhost") ? "http" : "https"}://${headers.host}`; // Send magic link via Resend try { await resend.emails.send({ from: "Ghost Guild ", to: email, subject: "Your Ghost Guild login link", html: `

Welcome back to Ghost Guild!

Click the button below to sign in to your account:

Sign In to Ghost Guild

This link will expire in 15 minutes for security. If you didn't request this login link, you can safely ignore this email.

`, }); return { success: true, message: GENERIC_MESSAGE, }; } catch (error) { console.error("Failed to send email:", error); throw createError({ statusCode: 500, statusMessage: "Failed to send login email. Please try again.", }); } });