Add detailed API: - Complete API documentation for In Format Usage flow diagrams for authentication and booking processes - Comprehensive endpoint descriptions with request/response examples - Detailed authentication and booking flow explanations - Structured documentation for health checks, authentication, and booking endpoints -: - Includes JWT authentication details usage - Provides clear API usage patterns for users and clients and administrators system interactions - Enhances project documentation with provides clear, structured API reference - Improves developer and user understanding of system capabilities
218 lines
6.3 KiB
Markdown
218 lines
6.3 KiB
Markdown
# 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 (
|
|
<div className="booking-card">
|
|
<h3>Booking #{booking.id}</h3>
|
|
<p>Scheduled: {new Date(booking.scheduled_at).toLocaleString()}</p>
|
|
<p>Duration: {booking.duration} minutes</p>
|
|
|
|
{booking.status === 'scheduled' && booking.jitsi_room_url && (
|
|
<button onClick={handleJoinMeeting}>
|
|
Join Meeting
|
|
</button>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
## 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
|
|
<a href={booking.jitsi_room_url} target="_blank">Join Meeting</a>
|
|
```
|
|
|
|
### Updated Code
|
|
|
|
Change to:
|
|
```javascript
|
|
// NEW WAY - Use the API endpoint
|
|
<button onClick={() => joinMeeting(booking.id)}>Join Meeting</button>
|
|
```
|
|
|
|
## 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
|