backend-service/docs/PERSONALIZED_MEETING_LINKS.md
ats-tech25 04f2d02afc docs(api comprehensive API documentation for attune Heart Therapy
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
2025-11-07 19:22:46 +00:00

9.0 KiB

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

GET /api/bookings

Returns the authenticated user's bookings with personalized meeting links.

Response Example:

{
  "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:

{
  "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

Returns a personalized meeting link for a specific booking.

Response Example:

{
  "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

https://meet.jit.si/room-id#userInfo.displayName="John Doe"

Features:

  • Name pre-filled
  • Standard participant permissions
  • Default audio/video settings
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

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

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 (
    <div className="booking-card">
      <h3>Booking #{booking.id}</h3>
      <p>Scheduled: {new Date(booking.scheduled_at).toLocaleString()}</p>
      
      {booking.status === 'scheduled' && (
        <button onClick={handleJoinMeeting}>
          {isAdmin ? 'Join as Moderator' : 'Join Meeting'}
        </button>
      )}
    </div>
  );
}

Migration Guide

Before (Old Implementation)

// Direct use of jitsi_room_url
<a href={booking.jitsi_room_url} target="_blank">
  Join Meeting
</a>

Problems:

  • Users join as "Booking ID" or generic name
  • No admin differentiation
  • Same link for everyone

After (New Implementation)

// Use personalized_meeting_url for users
<button onClick={() => window.open(booking.personalized_meeting_url, '_blank')}>
  Join Meeting
</button>

// Use admin_meeting_url for admins
<button onClick={() => window.open(booking.admin_meeting_url, '_blank')}>
  Join as Moderator
</button>

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
  • 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

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