import jwt from 'jsonwebtoken' import PreRegistration from '../../models/preRegistration.js' import { connectDB } from '../../utils/mongoose.js' export default defineEventHandler(async (event) => { const { token } = await validateBody(event, inviteVerifySchema) const config = useRuntimeConfig(event) await connectDB() let decoded try { decoded = jwt.verify(token, config.jwtSecret) } catch { throw createError({ statusCode: 401, statusMessage: 'Invalid or expired invitation link' }) } if (decoded.type !== 'prereg-invite') { throw createError({ statusCode: 401, statusMessage: 'Invalid or expired invitation link' }) } const preReg = await PreRegistration.findById(decoded.preRegistrationId) if (!preReg) { throw createError({ statusCode: 401, statusMessage: 'Invalid or expired invitation link' }) } if (preReg.status === 'accepted') { throw createError({ statusCode: 400, statusMessage: 'This invitation has already been accepted' }) } // Single-use enforcement if (!decoded.jti || decoded.jti !== preReg.magicLinkJti || preReg.magicLinkJtiUsed) { throw createError({ statusCode: 401, statusMessage: 'Invalid or expired invitation link' }) } // Burn the token await PreRegistration.findByIdAndUpdate(preReg._id, { $set: { magicLinkJtiUsed: true } }) return { preRegistrationId: preReg._id, name: preReg.name, email: preReg.email, city: preReg.city, } })