Add NocoDB events/RSVPs table config and improve session handling
All checks were successful
Build And Push Image / docker (push) Successful in 3m24s

- Add events and rsvps table ID fields to NocoDB settings dialog
- Replace mock getUserSession with proper SessionManager integration
- Improve type safety with explicit type casting and error handling
- Add comprehensive events system bug analysis documentation
This commit is contained in:
2025-08-12 12:24:16 +02:00
parent e06f639454
commit 67d4d5236b
10 changed files with 289 additions and 122 deletions

View File

@@ -1,5 +1,6 @@
// server/api/events/[id]/attendees.patch.ts
import { createNocoDBEventsClient } from '~/server/utils/nocodb-events';
import { createSessionManager } from '~/server/utils/session';
import type { EventAttendanceRequest } from '~/utils/types';
export default defineEventHandler(async (event) => {
@@ -14,8 +15,11 @@ export default defineEventHandler(async (event) => {
});
}
// Get user session
const session = await getUserSession(event);
// Get user session using the proper SessionManager
const sessionManager = createSessionManager();
const cookieHeader = getHeader(event, 'cookie');
const session = sessionManager.getSession(cookieHeader);
if (!session || !session.user) {
throw createError({
statusCode: 401,
@@ -63,7 +67,7 @@ export default defineEventHandler(async (event) => {
message: `Attendance ${body.attended ? 'marked' : 'unmarked'} successfully`
};
} catch (error) {
} catch (error: any) {
console.error('Error updating attendance:', error);
if (error.statusCode) {
@@ -76,20 +80,3 @@ export default defineEventHandler(async (event) => {
});
}
});
// Helper function
async function getUserSession(event: any) {
try {
const sessionCookie = getCookie(event, 'session') || getHeader(event, 'authorization');
if (!sessionCookie) return null;
return {
user: {
id: 'user-id',
tier: 'board' // Replace with actual session logic
}
};
} catch {
return null;
}
}

View File

@@ -1,6 +1,7 @@
// server/api/events/[id]/rsvp.post.ts
import { createNocoDBEventsClient } from '~/server/utils/nocodb-events';
import { getMemberByKeycloakId } from '~/server/utils/nocodb';
import { createSessionManager } from '~/server/utils/session';
import type { EventRSVPRequest } from '~/utils/types';
export default defineEventHandler(async (event) => {
@@ -15,8 +16,11 @@ export default defineEventHandler(async (event) => {
});
}
// Get user session
const session = await getUserSession(event);
// Get user session using the proper SessionManager
const sessionManager = createSessionManager();
const cookieHeader = getHeader(event, 'cookie');
const session = sessionManager.getSession(cookieHeader);
if (!session || !session.user) {
throw createError({
statusCode: 401,
@@ -66,7 +70,7 @@ export default defineEventHandler(async (event) => {
const paymentReference = generatePaymentReference(member.member_id || member.Id);
// Determine pricing and payment status
let paymentStatus = 'not_required';
let paymentStatus: 'pending' | 'not_required' | 'paid' | 'overdue' = 'not_required';
let isMemberPricing = 'false';
if (eventDetails.is_paid === 'true' && body.rsvp_status === 'confirmed') {
@@ -96,7 +100,7 @@ export default defineEventHandler(async (event) => {
updated_at: new Date().toISOString()
};
const newRSVP = await eventsClient.create(rsvpData);
const newRSVP = await eventsClient.createRSVP(rsvpData);
// Include payment information in response for paid events
let responseData: any = newRSVP;
@@ -121,12 +125,12 @@ export default defineEventHandler(async (event) => {
return {
success: true,
data: responseData,
message: body.rsvp_status === 'waitlist' ?
message: (body.rsvp_status as string) === 'waitlist' ?
'Added to waitlist - event is full' :
'RSVP submitted successfully'
};
} catch (error) {
} catch (error: any) {
console.error('Error processing RSVP:', error);
if (error.statusCode) {
@@ -141,19 +145,6 @@ export default defineEventHandler(async (event) => {
});
// Helper functions
async function getUserSession(event: any) {
try {
// For now, return a mock session - this should integrate with your actual auth system
return {
user: {
id: 'mock-keycloak-id',
tier: 'user'
}
};
} catch {
return null;
}
}
function generatePaymentReference(memberId: string): string {
const date = new Date().toISOString().split('T')[0];

View File

@@ -1,5 +1,6 @@
// server/api/events/index.get.ts
import { createNocoDBEventsClient, transformEventForCalendar } from '~/server/utils/nocodb-events';
import { createSessionManager } from '~/server/utils/session';
import type { EventFilters } from '~/utils/types';
export default defineEventHandler(async (event) => {
@@ -10,8 +11,11 @@ export default defineEventHandler(async (event) => {
calendar_format?: string
};
// Get user session for role-based filtering
const session = await getUserSession(event);
// Get user session using the proper SessionManager
const sessionManager = createSessionManager();
const cookieHeader = getHeader(event, 'cookie');
const session = sessionManager.getSession(cookieHeader);
if (!session || !session.user) {
throw createError({
statusCode: 401,
@@ -59,32 +63,17 @@ export default defineEventHandler(async (event) => {
pagination: response.PageInfo
};
} catch (error) {
} catch (error: any) {
console.error('Error fetching events:', error);
// Re-throw authentication errors as-is
if (error.statusCode === 401) {
throw error;
}
throw createError({
statusCode: 500,
statusMessage: 'Failed to fetch events'
});
}
});
// Helper function to get user session (you may need to adjust this based on your auth implementation)
async function getUserSession(event: any) {
// This should be replaced with your actual session retrieval logic
// For now, assuming you have a session utility similar to your auth system
try {
const sessionCookie = getCookie(event, 'session') || getHeader(event, 'authorization');
if (!sessionCookie) return null;
// Decode session - adjust based on your session implementation
// This is a placeholder that should be replaced with your actual session logic
return {
user: {
id: 'user-id', // This should come from your session
tier: 'user' // This should come from your session
}
};
} catch {
return null;
}
}

View File

@@ -1,13 +1,17 @@
// server/api/events/index.post.ts
import { createNocoDBEventsClient } from '~/server/utils/nocodb-events';
import { createSessionManager } from '~/server/utils/session';
import type { EventCreateRequest } from '~/utils/types';
export default defineEventHandler(async (event) => {
try {
const body = await readBody(event) as EventCreateRequest;
// Get user session for authentication and authorization
const session = await getUserSession(event);
// Get user session using the proper SessionManager
const sessionManager = createSessionManager();
const cookieHeader = getHeader(event, 'cookie');
const session = sessionManager.getSession(cookieHeader);
if (!session || !session.user) {
throw createError({
statusCode: 401,
@@ -74,7 +78,7 @@ export default defineEventHandler(async (event) => {
const eventData = {
title: body.title.trim(),
description: body.description?.trim() || '',
event_type: body.event_type,
event_type: body.event_type as 'meeting' | 'social' | 'fundraiser' | 'workshop' | 'board-only',
start_datetime: body.start_datetime,
end_datetime: body.end_datetime,
location: body.location?.trim() || '',
@@ -85,10 +89,10 @@ export default defineEventHandler(async (event) => {
cost_members: body.cost_members || '',
cost_non_members: body.cost_non_members || '',
member_pricing_enabled: body.member_pricing_enabled || 'true',
visibility: body.visibility,
status: body.status || 'active',
visibility: body.visibility as 'public' | 'board-only' | 'admin-only',
status: (body.status as 'active' | 'cancelled' | 'completed' | 'draft') || 'active',
creator: session.user.id,
current_attendees: '0'
current_attendees: 0
};
// Create the event
@@ -100,7 +104,7 @@ export default defineEventHandler(async (event) => {
message: 'Event created successfully'
};
} catch (error) {
} catch (error: any) {
console.error('Error creating event:', error);
// Re-throw createError instances
@@ -114,20 +118,3 @@ export default defineEventHandler(async (event) => {
});
}
});
// Helper function to get user session (same as in index.get.ts)
async function getUserSession(event: any) {
try {
const sessionCookie = getCookie(event, 'session') || getHeader(event, 'authorization');
if (!sessionCookie) return null;
return {
user: {
id: 'user-id', // Replace with actual session logic
tier: 'board' // Replace with actual session logic
}
};
} catch {
return null;
}
}