# Meeting Join Implementation Guide ## Overview This guide explains how to properly implement the meeting join functionality with personalized user information and admin differentiation. ## Issues Addressed 1. **Name Prepopulation**: Users now join meetings with their actual name instead of "Booking ID" 2. **Admin Differentiation**: Admin users get special moderator privileges in the meeting 3. **Personalized Links**: Each user gets a personalized meeting URL with their display name ## API Endpoint ### GET /api/meetings/:id/link Returns a personalized meeting link for the authenticated user. **Authentication**: Required (JWT token) **Parameters**: - `id` (path parameter): The booking ID **Response** (200 OK): ```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" } ``` **Error Responses**: - `400 Bad Request`: Invalid booking ID - `401 Unauthorized`: User not authenticated - `403 Forbidden`: User doesn't have permission to access this meeting - `404 Not Found`: Booking not found or meeting link not available ## Frontend Implementation ### Step 1: Fetch Personalized Meeting Link Instead of using the `jitsi_room_url` directly from the booking response, call the new endpoint: ```javascript // When user clicks "Join Meeting" button async function joinMeeting(bookingId) { try { const response = await fetch(`/api/meetings/${bookingId}/link`, { headers: { 'Authorization': `Bearer ${userToken}` } }); if (!response.ok) { throw new Error('Failed to get meeting link'); } const data = await response.json(); // Open the personalized meeting URL window.open(data.meeting_url, '_blank'); // Optionally show user info console.log(`Joining as: ${data.display_name}`); console.log(`Admin privileges: ${data.is_admin}`); } catch (error) { console.error('Error joining meeting:', error); alert('Failed to join meeting. Please try again.'); } } ``` ### Step 2: Update Booking Display Component ```javascript function BookingCard({ booking }) { const handleJoinMeeting = async () => { try { const response = await fetch(`/api/meetings/${booking.id}/link`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); const data = await response.json(); window.open(data.meeting_url, '_blank'); } catch (error) { console.error('Error:', error); } }; return (

Booking #{booking.id}

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

Duration: {booking.duration} minutes

{booking.status === 'scheduled' && booking.jitsi_room_url && ( )}
); } ``` ## How It Works ### For Regular Users 1. User calls `/api/meetings/:id/link` with their JWT token 2. Backend verifies the user owns the booking 3. Backend generates a personalized Jitsi URL with the user's name: ``` https://meet.jit.si/room-id#userInfo.displayName="John Doe" ``` 4. User joins the meeting with their name pre-filled ### For Admin Users 1. Admin calls `/api/meetings/:id/link` with their JWT token 2. Backend verifies admin status (can access any booking) 3. Backend generates a personalized Jitsi URL with admin privileges: ``` https://meet.jit.si/room-id#userInfo.displayName="Dr. Smith"&config.startWithAudioMuted=false&config.startWithVideoMuted=false ``` 4. Admin joins with moderator privileges and audio/video enabled by default ## Display Name Logic The system determines the display name in this order: 1. **First Name + Last Name**: If both are available 2. **Email**: If name fields are empty 3. **Fallback**: Uses email as last resort ## Security Considerations 1. **Authentication Required**: All meeting link requests require valid JWT token 2. **Authorization Check**: - Regular users can only access their own bookings - Admin users can access any booking 3. **No Direct URL Sharing**: The personalized URL includes user-specific information 4. **Token Expiration**: JWT tokens expire, requiring re-authentication ## Migration Notes ### Existing Code If your frontend currently uses: ```javascript // OLD WAY - Don't use this anymore Join Meeting ``` ### Updated Code Change to: ```javascript // NEW WAY - Use the API endpoint ``` ## Testing ### Test as Regular User 1. Login as a regular user 2. Create a booking 3. Call `/api/meetings/{booking_id}/link` 4. Verify the response includes your name in the URL 5. Open the URL and confirm your name appears in Jitsi ### Test as Admin 1. Login as admin 2. Get any booking ID 3. Call `/api/meetings/{booking_id}/link` 4. Verify `is_admin: true` in response 5. Open the URL and confirm moderator privileges ### Test Authorization 1. Try to access another user's booking as a regular user 2. Should receive `403 Forbidden` error 3. Admin should be able to access any booking ## Troubleshooting ### Issue: Name shows as "Booking ID" **Solution**: Ensure you're using the new `/api/meetings/:id/link` endpoint instead of the raw `jitsi_room_url` ### Issue: Admin doesn't have moderator privileges **Solution**: Verify the user's `is_admin` field is set to `true` in the database ### Issue: 403 Forbidden error **Solution**: Regular users can only access their own bookings. Verify the booking belongs to the authenticated user. ### Issue: Meeting URL not available **Solution**: The booking might not have a Jitsi room created yet. This can happen if payment hasn't been completed or if there was an error during booking creation. ## Future Enhancements Potential improvements for the future: 1. **Waiting Room**: Add a waiting room for participants before admin joins 2. **Recording Control**: Give admin ability to start/stop recording 3. **Participant Limits**: Enforce maximum participant limits 4. **Custom Branding**: Add custom Jitsi branding for the therapy practice 5. **Meeting Analytics**: Track join times, duration, and participant count