# 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 (
);
}
```
## 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