# Personalized Meeting Links Implementation ## Overview All meeting links are now personalized with the user's name and role-specific settings. This ensures users join meetings with their actual names instead of generic identifiers, and admins get appropriate moderator privileges. ## Changes Made ### 1. API Endpoints with Personalized Links #### GET /api/bookings Returns the authenticated user's bookings with personalized meeting links. **Response Example:** ```json { "bookings": [ { "id": 123, "user_id": 45, "scheduled_at": "2024-01-15T10:00:00Z", "duration": 60, "status": "scheduled", "jitsi_room_id": "booking-123-1234567890-abc123", "jitsi_room_url": "https://meet.jit.si/booking-123-1234567890-abc123", "personalized_meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123#userInfo.displayName=\"John Doe\"", "amount": 100.00, "payment_status": "succeeded" } ] } ``` **Key Fields:** - `jitsi_room_url`: Original Jitsi room URL (kept for backward compatibility) - `personalized_meeting_url`: User-specific URL with their name pre-filled #### GET /api/admin/bookings Returns all bookings with admin's personalized meeting links. **Response Example:** ```json { "bookings": [ { "id": 123, "user_id": 45, "scheduled_at": "2024-01-15T10:00:00Z", "duration": 60, "status": "scheduled", "jitsi_room_id": "booking-123-1234567890-abc123", "jitsi_room_url": "https://meet.jit.si/booking-123-1234567890-abc123", "admin_meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123#userInfo.displayName=\"Dr. Smith\"&config.startWithAudioMuted=false&config.startWithVideoMuted=false", "amount": 100.00, "payment_status": "succeeded" } ], "total": 1, "limit": 50, "offset": 0 } ``` **Key Fields:** - `admin_meeting_url`: Admin-specific URL with moderator privileges #### GET /api/meetings/:id/link Returns a personalized meeting link for a specific booking. **Response Example:** ```json { "booking_id": 123, "meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123#userInfo.displayName=\"John Doe\"", "display_name": "John Doe", "is_admin": false, "scheduled_at": "2024-01-15T10:00:00Z", "duration": 60, "status": "scheduled" } ``` ### 2. Email Notifications All email notifications now include personalized meeting links: #### Meeting Info Email (After Booking) - Sent to: **User** - Link includes: User's name - Example: `https://meet.jit.si/room-id#userInfo.displayName="John Doe"` #### Reminder Email (Before Meeting) - Sent to: **User** - Link includes: User's name - Example: `https://meet.jit.si/room-id#userInfo.displayName="John Doe"` **Note:** Admin users receive emails with admin privileges in the link if they book for themselves. ### 3. Display Name Logic The system determines display names in this order: 1. **First Name + Last Name**: `"John Doe"` 2. **Email**: If name fields are empty, uses email address 3. **Fallback**: Email as last resort ### 4. Admin vs Regular User Differences #### Regular User Link ``` https://meet.jit.si/room-id#userInfo.displayName="John Doe" ``` **Features:** - Name pre-filled - Standard participant permissions - Default audio/video settings #### Admin User Link ``` https://meet.jit.si/room-id#userInfo.displayName="Dr. Smith"&config.startWithAudioMuted=false&config.startWithVideoMuted=false ``` **Features:** - Name pre-filled - Moderator privileges - Audio and video enabled by default - Can manage participants - Can start/stop recording (if configured) ## Frontend Implementation Guide ### Using Personalized Links from /api/bookings ```javascript // Fetch user's bookings async function fetchMyBookings() { const response = await fetch('/api/bookings', { headers: { 'Authorization': `Bearer ${userToken}` } }); const data = await response.json(); // Use personalized_meeting_url instead of jitsi_room_url data.bookings.forEach(booking => { if (booking.personalized_meeting_url) { console.log(`Join link: ${booking.personalized_meeting_url}`); } }); } ``` ### Using Admin Links from /api/admin/bookings ```javascript // Fetch all bookings as admin async function fetchAllBookings() { const response = await fetch('/api/admin/bookings', { headers: { 'Authorization': `Bearer ${adminToken}` } }); const data = await response.json(); // Use admin_meeting_url for admin access data.bookings.forEach(booking => { if (booking.admin_meeting_url) { console.log(`Admin join link: ${booking.admin_meeting_url}`); } }); } ``` ### React Component Example ```jsx function BookingCard({ booking, isAdmin }) { const getMeetingLink = () => { if (isAdmin && booking.admin_meeting_url) { return booking.admin_meeting_url; } return booking.personalized_meeting_url || booking.jitsi_room_url; }; const handleJoinMeeting = () => { const meetingLink = getMeetingLink(); window.open(meetingLink, '_blank'); }; return (

Booking #{booking.id}

Scheduled: {new Date(booking.scheduled_at).toLocaleString()}

{booking.status === 'scheduled' && ( )}
); } ``` ## Migration Guide ### Before (Old Implementation) ```javascript // Direct use of jitsi_room_url Join Meeting ``` **Problems:** - Users join as "Booking ID" or generic name - No admin differentiation - Same link for everyone ### After (New Implementation) ```javascript // Use personalized_meeting_url for users // Use admin_meeting_url for admins ``` **Benefits:** - Users join with their actual names - Admins get moderator privileges - Better user experience ## Testing Checklist ### Test as Regular User 1. ✅ Login as regular user 2. ✅ Create a booking 3. ✅ Call `GET /api/bookings` 4. ✅ Verify `personalized_meeting_url` contains your name 5. ✅ Open the URL and confirm name appears in Jitsi 6. ✅ Check email notification has personalized link ### Test as Admin 1. ✅ Login as admin 2. ✅ Call `GET /api/admin/bookings` 3. ✅ Verify `admin_meeting_url` contains admin name and moderator config 4. ✅ Open the URL and confirm moderator privileges 5. ✅ Verify audio/video enabled by default 6. ✅ Check email notification has admin link (if admin books for themselves) ### Test Email Notifications 1. ✅ Create a booking 2. ✅ Check "Meeting Info" email 3. ✅ Verify "Join Meeting" button uses personalized link 4. ✅ Click link and confirm name is pre-filled 5. ✅ Wait for reminder email 6. ✅ Verify reminder also has personalized link ## Security Considerations ### Authorization - Regular users can only access their own bookings via `/api/bookings` - Admins can access all bookings via `/api/admin/bookings` - `/api/meetings/:id/link` enforces ownership or admin check ### Link Sharing - Personalized links include user-specific information - Links are generated on-demand, not stored - Original `jitsi_room_url` remains unchanged in database ### Token Expiration - All endpoints require valid JWT authentication - Expired tokens require re-authentication - Meeting links remain valid regardless of token expiration ## Backward Compatibility The `jitsi_room_url` field is still present in all responses for backward compatibility. However, frontends should migrate to using: - `personalized_meeting_url` for regular users - `admin_meeting_url` for admins - `/api/meetings/:id/link` endpoint for dynamic link generation ## Troubleshooting ### Issue: Name still shows as "Booking ID" **Solution:** Ensure you're using `personalized_meeting_url` or `admin_meeting_url` instead of `jitsi_room_url` ### Issue: Admin doesn't have moderator privileges **Solution:** 1. Verify user's `is_admin` field is `true` in database 2. Check that `admin_meeting_url` includes moderator config parameters 3. Ensure using `/api/admin/bookings` endpoint, not `/api/bookings` ### Issue: Email links don't have personalized URLs **Solution:** 1. Verify notification service is generating personalized URLs 2. Check email template uses `{{.JoinURL}}` field 3. Ensure user has valid first/last name or email ### Issue: Display name is email instead of name **Solution:** Update user's `first_name` and `last_name` fields in the database ## Future Enhancements Potential improvements: 1. **Custom Display Names**: Allow users to set custom display names 2. **Meeting Roles**: Support different roles beyond admin/user (e.g., observer, presenter) 3. **Link Expiration**: Add time-based expiration to meeting links 4. **Waiting Room**: Implement waiting room for participants before admin joins 5. **Custom Branding**: Add organization-specific branding to Jitsi interface