diff --git a/nuxt.config.ts b/nuxt.config.ts index 08bbc89..246bef7 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -127,6 +127,7 @@ export default defineNuxtConfig({ }, sessionSecret: process.env.NUXT_SESSION_SECRET || "", encryptionKey: process.env.NUXT_ENCRYPTION_KEY || "", + jwtSecret: process.env.NUXT_JWT_SECRET || process.env.NUXT_SESSION_SECRET || "", public: { // Client-side configuration appName: "MonacoUSA Portal", diff --git a/server/api/members/[id]/create-portal-account.post.ts b/server/api/members/[id]/create-portal-account.post.ts index 95eb5b7..24d5c67 100644 --- a/server/api/members/[id]/create-portal-account.post.ts +++ b/server/api/members/[id]/create-portal-account.post.ts @@ -119,6 +119,8 @@ export default defineEventHandler(async (event) => { // 9. Send welcome/verification email using our custom email system console.log('[api/members/[id]/create-portal-account.post] Attempting to send welcome/verification email...'); let emailSent = false; + let emailError: string | null = null; + try { const { getEmailService } = await import('~/server/utils/email'); const { generateEmailVerificationToken } = await import('~/server/utils/email-tokens'); @@ -137,8 +139,13 @@ export default defineEventHandler(async (event) => { emailSent = true; console.log('[api/members/[id]/create-portal-account.post] Welcome email sent successfully'); - } catch (emailError: any) { - console.error('[api/members/[id]/create-portal-account.post] Failed to send welcome email:', emailError.message); + } catch (error: any) { + emailError = error.message || 'Unknown email error'; + console.error('[api/members/[id]/create-portal-account.post] Failed to send welcome email:', emailError); + + // Log the full error for debugging + console.error('[api/members/[id]/create-portal-account.post] Full email error:', error); + // Don't fail the account creation if email fails - user can resend verification email later } @@ -148,13 +155,14 @@ export default defineEventHandler(async (event) => { success: true, message: emailSent ? 'Portal account created successfully. The member will receive an email to verify their account and set their password.' - : 'Portal account created successfully. Email sending is not configured - the member will need to request a password reset to access their account.', + : `Portal account created successfully. Email sending failed: ${emailError || 'Unknown error'}. The member can use "Forgot Password" to access their account.`, data: { keycloak_id: keycloakId, member_id: memberId, email: member.email, name: `${member.first_name} ${member.last_name}`, - email_sent: emailSent + email_sent: emailSent, + email_error: emailError } }; diff --git a/server/utils/email-tokens.ts b/server/utils/email-tokens.ts index 71fedd7..9dce896 100644 --- a/server/utils/email-tokens.ts +++ b/server/utils/email-tokens.ts @@ -1,4 +1,4 @@ -import { sign, verify } from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; export interface EmailVerificationTokenPayload { userId: string; @@ -27,7 +27,7 @@ export async function generateEmailVerificationToken(userId: string, email: stri iat: Date.now() }; - const token = sign(payload, runtimeConfig.jwtSecret, { + const token = jwt.sign(payload, runtimeConfig.jwtSecret as string, { expiresIn: '24h', issuer: 'monacousa-portal', audience: 'email-verification' @@ -62,10 +62,10 @@ export async function verifyEmailToken(token: string): Promise<{ userId: string; try { // Verify JWT signature and expiration - const decoded = verify(token, runtimeConfig.jwtSecret, { + const decoded = jwt.verify(token, runtimeConfig.jwtSecret as string, { issuer: 'monacousa-portal', audience: 'email-verification' - }) as EmailVerificationTokenPayload; + }) as any as EmailVerificationTokenPayload; // Validate token purpose if (decoded.purpose !== 'email-verification') { @@ -118,10 +118,10 @@ export async function isTokenValid(token: string): Promise { return false; } - const decoded = verify(token, runtimeConfig.jwtSecret, { + const decoded = jwt.verify(token, runtimeConfig.jwtSecret as string, { issuer: 'monacousa-portal', audience: 'email-verification' - }) as EmailVerificationTokenPayload; + }) as any as EmailVerificationTokenPayload; return decoded.purpose === 'email-verification' && activeTokens.has(token); } catch (error) {