backend-service/internal/handlers/meeting.go

131 lines
3.3 KiB
Go
Raw Normal View History

package handlers
import (
"fmt"
"net/http"
"strconv"
"attune-heart-therapy/internal/middleware"
"attune-heart-therapy/internal/repositories"
"attune-heart-therapy/internal/services"
"github.com/gin-gonic/gin"
)
type MeetingHandler struct {
bookingRepo repositories.BookingRepository
userRepo repositories.UserRepository
jitsiService services.JitsiService
}
func NewMeetingHandler(bookingRepo repositories.BookingRepository, userRepo repositories.UserRepository, jitsiService services.JitsiService) *MeetingHandler {
return &MeetingHandler{
bookingRepo: bookingRepo,
userRepo: userRepo,
jitsiService: jitsiService,
}
}
// GetMeetingLink handles GET /api/meetings/:id/link - returns personalized meeting link
func (h *MeetingHandler) GetMeetingLink(c *gin.Context) {
// Get booking ID from URL parameter
bookingIDStr := c.Param("id")
bookingID, err := strconv.ParseUint(bookingIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid booking ID",
})
return
}
// Get user ID from JWT token
userID, exists := middleware.GetUserIDFromContext(c)
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{
"error": "User not authenticated",
})
return
}
// Get booking details
booking, err := h.bookingRepo.GetByID(uint(bookingID))
if err != nil {
c.JSON(http.StatusNotFound, gin.H{
"error": "Booking not found",
})
return
}
// Verify booking belongs to user (or user is admin)
user, err := h.userRepo.GetByID(userID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to retrieve user information",
})
return
}
// Check authorization: user must own the booking or be an admin
if booking.UserID != userID && !user.IsAdmin {
c.JSON(http.StatusForbidden, gin.H{
"error": "You don't have permission to access this meeting",
})
return
}
// Check if meeting URL exists
if booking.JitsiRoomURL == "" {
c.JSON(http.StatusNotFound, gin.H{
"error": "Meeting link not available for this booking",
})
return
}
// Prepare display name
displayName := fmt.Sprintf("%s %s", user.FirstName, user.LastName)
if displayName == " " || displayName == "" {
displayName = user.Email
}
// Determine if user is admin
isAdmin := user.IsAdmin
// Generate JWT token for Jitsi authentication
token, err := h.jitsiService.GenerateJitsiToken(
booking.JitsiRoomID,
displayName,
user.Email,
isAdmin,
)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to generate meeting token",
"details": err.Error(),
})
return
}
// Build Jitsi URL with JWT token
var jitsiURL string
if token != "" {
// If JWT is configured, append token as query parameter
jitsiURL = fmt.Sprintf("%s?jwt=%s", booking.JitsiRoomURL, token)
} else {
// Fallback to URL parameters if JWT not configured
jitsiURL = fmt.Sprintf("%s#userInfo.displayName=\"%s\"", booking.JitsiRoomURL, displayName)
if isAdmin {
jitsiURL = fmt.Sprintf("%s&config.startWithAudioMuted=false&config.startWithVideoMuted=false", jitsiURL)
}
}
c.JSON(http.StatusOK, gin.H{
"booking_id": booking.ID,
"meeting_url": jitsiURL,
"display_name": displayName,
"is_admin": isAdmin,
"scheduled_at": booking.ScheduledAt,
"duration": booking.Duration,
"status": booking.Status,
})
}