feat: pre-registrant management and invitation system
Admin interface to review, filter, and batch-invite the 95 pre-registrants from Baby Ghosts. Accept-invitation page pre-fills their data and collects circle, pronouns, motivation, contribution tier, and agreement before creating their member record.
This commit is contained in:
parent
bab53cec9e
commit
501be10bfe
15 changed files with 1896 additions and 1 deletions
46
server/api/invite/verify.post.js
Normal file
46
server/api/invite/verify.post.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
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,
|
||||
}
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue