feat(signup): community guidelines agreement and policies routes
Introduces /community-guidelines and /policies/{privacy,terms,[slug]} pages,
swaps the signup/invite checkbox from agreedToTerms to agreedToGuidelines,
adds Member.agreement.acceptedAt, and stamps the field when a Helcim
customer is created.
This commit is contained in:
parent
e0d11e47f4
commit
c5e901ed24
13 changed files with 1292 additions and 54 deletions
|
|
@ -1,5 +1,4 @@
|
|||
// Create a Helcim customer
|
||||
import jwt from 'jsonwebtoken'
|
||||
import Member from '../../models/member.js'
|
||||
import { connectDB } from '../../utils/mongoose.js'
|
||||
import { createHelcimCustomer } from '../../utils/helcim.js'
|
||||
|
|
@ -7,7 +6,6 @@ import { createHelcimCustomer } from '../../utils/helcim.js'
|
|||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
await connectDB()
|
||||
const config = useRuntimeConfig(event)
|
||||
const body = await validateBody(event, helcimCustomerSchema)
|
||||
|
||||
// Check if member already exists
|
||||
|
|
@ -33,34 +31,16 @@ export default defineEventHandler(async (event) => {
|
|||
circle: body.circle,
|
||||
contributionTier: body.contributionTier,
|
||||
helcimCustomerId: customerData.id,
|
||||
status: 'pending_payment'
|
||||
status: 'pending_payment',
|
||||
agreement: { acceptedAt: new Date() }
|
||||
})
|
||||
|
||||
// Generate JWT token for the session
|
||||
const token = jwt.sign(
|
||||
{
|
||||
memberId: member._id,
|
||||
email: body.email,
|
||||
helcimCustomerId: customerData.id
|
||||
},
|
||||
config.jwtSecret,
|
||||
{ expiresIn: '7d' }
|
||||
)
|
||||
setAuthCookie(event, member)
|
||||
|
||||
// Set the session cookie server-side
|
||||
setCookie(event, 'auth-token', token, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
maxAge: 60 * 60 * 24 * 7, // 7 days (matches verify.get.js and refresh.post.js)
|
||||
path: '/',
|
||||
domain: undefined // Let browser set domain automatically
|
||||
})
|
||||
return {
|
||||
success: true,
|
||||
customerId: customerData.id,
|
||||
customerCode: customerData.customerCode,
|
||||
token,
|
||||
member: {
|
||||
id: member._id,
|
||||
email: member.email,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export default defineEventHandler(async (event) => {
|
|||
contributionTier: body.contributionTier,
|
||||
bio: body.motivation || undefined,
|
||||
status: body.contributionTier === '0' ? 'active' : 'pending_payment',
|
||||
agreement: { acceptedAt: new Date() },
|
||||
})
|
||||
|
||||
await assignMemberNumber(member._id)
|
||||
|
|
|
|||
|
|
@ -83,6 +83,10 @@ const memberSchema = new mongoose.Schema({
|
|||
inviteEmailSent: { type: Boolean, default: false },
|
||||
inviteEmailSentAt: Date,
|
||||
|
||||
agreement: {
|
||||
acceptedAt: Date,
|
||||
},
|
||||
|
||||
// Magic link single-use enforcement
|
||||
magicLinkJti: String,
|
||||
magicLinkJtiUsed: { type: Boolean, default: false },
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ export const helcimCustomerSchema = z.object({
|
|||
name: z.string().min(1).max(200),
|
||||
email: z.string().trim().toLowerCase().email(),
|
||||
circle: z.enum(['community', 'founder', 'practitioner']).optional(),
|
||||
contributionTier: z.enum(['0', '5', '15', '30', '50']).optional()
|
||||
contributionTier: z.enum(['0', '5', '15', '30', '50']).optional(),
|
||||
agreedToGuidelines: z.literal(true)
|
||||
})
|
||||
|
||||
export const helcimInitializePaymentSchema = z.object({
|
||||
|
|
@ -147,7 +148,7 @@ export const seriesTicketPurchaseSchema = z.object({
|
|||
name: z.string().min(1).max(200),
|
||||
email: z.string().trim().toLowerCase().email(),
|
||||
paymentId: z.string().max(500).optional(),
|
||||
ticketType: z.enum(['member', 'public', 'guest']).optional(),
|
||||
ticketType: z.enum(['member', 'public', 'guest']),
|
||||
})
|
||||
|
||||
export const seriesTicketEligibilitySchema = z.object({
|
||||
|
|
@ -345,7 +346,7 @@ export const inviteAcceptSchema = z.object({
|
|||
circle: z.enum(['community', 'founder', 'practitioner']),
|
||||
motivation: z.string().max(5000).optional(),
|
||||
contributionTier: z.enum(['0', '5', '15', '30', '50']),
|
||||
agreedToTerms: z.literal(true),
|
||||
agreedToGuidelines: z.literal(true),
|
||||
token: z.string().min(1)
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue