43 lines
1.5 KiB
JavaScript
43 lines
1.5 KiB
JavaScript
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' })
|
|
}
|
|
|
|
// Match the jti so that re-invite (which rotates the jti) kills old links.
|
|
// The burn happens in accept.post.js once a Member is created — keeps verify
|
|
// idempotent so the form survives a refresh.
|
|
if (!decoded.jti || decoded.jti !== preReg.magicLinkJti) {
|
|
throw createError({ statusCode: 401, statusMessage: 'Invalid or expired invitation link' })
|
|
}
|
|
|
|
return {
|
|
preRegistrationId: preReg._id,
|
|
name: preReg.name,
|
|
email: preReg.email,
|
|
city: preReg.city,
|
|
}
|
|
})
|