From e097fb746f437833819469dd813aefad11c958ed Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 13 Aug 2025 17:16:22 +0200 Subject: [PATCH] fixes --- server/api/admin/debug-rsvp-config.get.ts | 64 +++++++++++++++++++++++ server/api/auth/verify-email.get.ts | 64 +++++++++++------------ server/utils/nocodb-events.ts | 21 ++++++-- 3 files changed, 113 insertions(+), 36 deletions(-) create mode 100644 server/api/admin/debug-rsvp-config.get.ts diff --git a/server/api/admin/debug-rsvp-config.get.ts b/server/api/admin/debug-rsvp-config.get.ts new file mode 100644 index 0000000..38590ae --- /dev/null +++ b/server/api/admin/debug-rsvp-config.get.ts @@ -0,0 +1,64 @@ +// server/api/admin/debug-rsvp-config.get.ts +import { createSessionManager } from '~/server/utils/session'; +import { getEffectiveNocoDBConfig } from '~/server/utils/admin-config'; +import { getEventTableId } from '~/server/utils/nocodb-events'; + +export default defineEventHandler(async (event) => { + try { + // Verify admin session + const sessionManager = createSessionManager(); + const cookieHeader = getHeader(event, 'cookie'); + const session = sessionManager.getSession(cookieHeader); + + if (!session?.user || session.user.tier !== 'admin') { + throw createError({ + statusCode: 403, + statusMessage: 'Admin access required' + }); + } + + console.log('[admin/debug-rsvp-config] ========================='); + console.log('[admin/debug-rsvp-config] 🔍 DEBUG: RSVP Configuration Analysis'); + + // Get effective config + const effectiveConfig = getEffectiveNocoDBConfig(); + console.log('[admin/debug-rsvp-config] 🔍 Effective config:', JSON.stringify(effectiveConfig, null, 2)); + + // Test RSVP table ID retrieval + const rsvpTableId = getEventTableId('EventRSVPs'); + console.log('[admin/debug-rsvp-config] 🔍 RSVP Table ID retrieved:', rsvpTableId); + + // Test Events table ID retrieval + const eventsTableId = getEventTableId('Events'); + console.log('[admin/debug-rsvp-config] 🔍 Events Table ID retrieved:', eventsTableId); + + return { + success: true, + debug: { + effectiveConfig, + rsvpTableId, + eventsTableId, + availableTableKeys: Object.keys(effectiveConfig?.tables || {}), + rsvpTableInConfig: { + 'rsvps': effectiveConfig?.tables?.['rsvps'], + 'event_rsvps': effectiveConfig?.tables?.['event_rsvps'], + 'EventRSVPs': effectiveConfig?.tables?.['EventRSVPs'], + 'rsvp_table': effectiveConfig?.tables?.['rsvp_table'], + 'RSVPs': effectiveConfig?.tables?.['RSVPs'] + } + } + }; + + } catch (error: any) { + console.error('[admin/debug-rsvp-config] ❌ Error:', error); + + if (error.statusCode) { + throw error; + } + + throw createError({ + statusCode: 500, + statusMessage: 'Failed to debug RSVP configuration' + }); + } +}); diff --git a/server/api/auth/verify-email.get.ts b/server/api/auth/verify-email.get.ts index 7ecfc14..d36f2d3 100644 --- a/server/api/auth/verify-email.get.ts +++ b/server/api/auth/verify-email.get.ts @@ -3,10 +3,8 @@ export default defineEventHandler(async (event) => { const { token } = getQuery(event); if (!token || typeof token !== 'string') { - throw createError({ - statusCode: 400, - statusMessage: 'Verification token is required' - }); + console.log('[verify-email] Missing or invalid token, redirecting to expired page'); + return sendRedirect(event, '/auth/verify-expired?reason=invalid', 302); } console.log('[verify-email] Processing verification token...'); @@ -35,54 +33,54 @@ export default defineEventHandler(async (event) => { // ONLY consume token after successful Keycloak update await consumeEmailToken(token); - } catch (keycloakError: any) { - console.error('[verify-email] Keycloak update failed:', keycloakError.message); + } catch (keycloakUpdateError: any) { + console.error('[verify-email] Keycloak update failed:', keycloakUpdateError.message); // Check if this is a retryable error or a permanent failure - if (keycloakError.message?.includes('error-user-attribute-required')) { + if (keycloakUpdateError.message?.includes('error-user-attribute-required')) { // This is a configuration issue - don't consume token, allow retries console.log('[verify-email] Keycloak configuration error - token preserved for retry'); partialSuccess = true; - keycloakError = keycloakError.message; + keycloakError = keycloakUpdateError.message; } else { // For other errors, still consume token to prevent infinite retries console.log('[verify-email] Consuming token despite Keycloak error to prevent loops'); await consumeEmailToken(token); partialSuccess = true; - keycloakError = keycloakError.message; + keycloakError = keycloakUpdateError.message; } } - // Return JSON response for client-side navigation - return { - success: true, - data: { - userId, - email, - partialSuccess, - keycloakError: keycloakError || undefined - } - }; + // Build success redirect URL with query parameters + const successUrl = new URL('/auth/verify-success', 'https://portal.monacousa.org'); + successUrl.searchParams.set('email', email); + + if (partialSuccess && keycloakError) { + successUrl.searchParams.set('warning', 'partial'); + console.log('[verify-email] Redirecting to success page with partial warning'); + } else { + console.log('[verify-email] Redirecting to success page - verification complete'); + } + + // Redirect to success page instead of returning JSON + return sendRedirect(event, successUrl.pathname + successUrl.search, 302); } catch (error: any) { console.error('[verify-email] Verification failed:', error.message); - // Return error response + // Redirect to appropriate error page instead of throwing errors if (error.message?.includes('expired')) { - throw createError({ - statusCode: 410, - statusMessage: 'Verification link has expired. Please request a new one.' - }); - } else if (error.message?.includes('already used') || error.message?.includes('not found')) { - throw createError({ - statusCode: 409, - statusMessage: 'This verification link has already been used or is invalid.' - }); + console.log('[verify-email] Token expired, redirecting to expired page'); + return sendRedirect(event, '/auth/verify-expired?reason=expired', 302); + } else if (error.message?.includes('already used')) { + console.log('[verify-email] Token already used, redirecting to expired page'); + return sendRedirect(event, '/auth/verify-expired?reason=used', 302); + } else if (error.message?.includes('not found')) { + console.log('[verify-email] Token not found, redirecting to expired page'); + return sendRedirect(event, '/auth/verify-expired?reason=invalid', 302); } else { - throw createError({ - statusCode: 400, - statusMessage: error.message || 'Invalid verification link' - }); + console.log('[verify-email] Generic verification error, redirecting to expired page'); + return sendRedirect(event, '/auth/verify-expired?reason=invalid', 302); } } }); diff --git a/server/utils/nocodb-events.ts b/server/utils/nocodb-events.ts index 8b09311..ac5b4d2 100644 --- a/server/utils/nocodb-events.ts +++ b/server/utils/nocodb-events.ts @@ -26,18 +26,26 @@ export enum EventTable { // Dynamic table ID getter - will use configured table ID from admin panel export const getEventTableId = (tableName: 'Events' | 'EventRSVPs'): string => { + console.log(`[nocodb-events] 🔍 DEBUG: Getting table ID for ${tableName}...`); + try { // Try to get effective configuration from admin config system first const effectiveConfig = getEffectiveNocoDBConfig(); + console.log(`[nocodb-events] 🔍 DEBUG: Effective config:`, JSON.stringify(effectiveConfig, null, 2)); + if (effectiveConfig?.tables) { + console.log(`[nocodb-events] 🔍 DEBUG: Available table keys:`, Object.keys(effectiveConfig.tables)); + if (tableName === 'Events') { // Check multiple possible keys for Events table const eventsTableId = effectiveConfig.tables['events'] || effectiveConfig.tables['Events'] || effectiveConfig.tables['events_table']; if (eventsTableId) { - console.log(`[nocodb-events] Using admin config table ID for ${tableName}:`, eventsTableId); + console.log(`[nocodb-events] ✅ Using admin config table ID for ${tableName}:`, eventsTableId); return eventsTableId; + } else { + console.log(`[nocodb-events] ⚠️ No Events table ID found in config`); } } else if (tableName === 'EventRSVPs') { // Check multiple possible keys for RSVP table @@ -47,13 +55,20 @@ export const getEventTableId = (tableName: 'Events' | 'EventRSVPs'): string => { effectiveConfig.tables['rsvp_table'] || effectiveConfig.tables['RSVPs']; if (rsvpTableId) { - console.log(`[nocodb-events] Using admin config table ID for ${tableName}:`, rsvpTableId); + console.log(`[nocodb-events] ✅ Using admin config table ID for ${tableName}:`, rsvpTableId); return rsvpTableId; + } else { + console.log(`[nocodb-events] ⚠️ No RSVP table ID found in config. Checking individual keys:`); + console.log(`[nocodb-events] 🔍 rsvps:`, effectiveConfig.tables['rsvps']); + console.log(`[nocodb-events] 🔍 event_rsvps:`, effectiveConfig.tables['event_rsvps']); + console.log(`[nocodb-events] 🔍 EventRSVPs:`, effectiveConfig.tables['EventRSVPs']); } } + } else { + console.log(`[nocodb-events] ⚠️ No tables configuration found in effective config`); } } catch (error) { - console.log(`[nocodb-events] Admin config not available, trying fallback for ${tableName}:`, error); + console.log(`[nocodb-events] ❌ Admin config error for ${tableName}:`, error); } // Try to get table ID from global configuration