11import { createHash , randomUUID } from "node:crypto" ;
22import type { CalendarEvent , EventBusyDate } from "@calcom/types/Calendar" ;
33import type { PartialReference } from "@calcom/types/EventManager" ;
4- import type { VideoApiAdapter , VideoCallData } from "@calcom/types/VideoApiAdapter" ;
4+ import type {
5+ VideoApiAdapter ,
6+ VideoCallData ,
7+ } from "@calcom/types/VideoApiAdapter" ;
58import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug" ;
69import { metadata } from "../_metadata" ;
710
@@ -18,10 +21,22 @@ const normalizeApiUrl = (serverUrl: string) => {
1821const checksum = ( method : string , query : string , sharedSecret : string ) =>
1922 createHash ( "sha1" ) . update ( `${ method } ${ query } ${ sharedSecret } ` ) . digest ( "hex" ) ;
2023
21- const deriveMeetingPassword = ( role : "attendee" | "moderator" , meetingID : string , sharedSecret : string ) =>
22- createHash ( "sha256" ) . update ( `${ role } :${ meetingID } :${ sharedSecret } ` ) . digest ( "hex" ) . slice ( 0 , 24 ) ;
23-
24- const buildApiUrl = ( apiUrl : string , method : string , params : URLSearchParams , sharedSecret : string ) => {
24+ const deriveMeetingPassword = (
25+ role : "attendee" | "moderator" ,
26+ meetingID : string ,
27+ sharedSecret : string ,
28+ ) =>
29+ createHash ( "sha256" )
30+ . update ( `${ role } :${ meetingID } :${ sharedSecret } ` )
31+ . digest ( "hex" )
32+ . slice ( 0 , 24 ) ;
33+
34+ const buildApiUrl = (
35+ apiUrl : string ,
36+ method : string ,
37+ params : URLSearchParams ,
38+ sharedSecret : string ,
39+ ) => {
2540 const query = params . toString ( ) ;
2641 const signedQuery = new URLSearchParams ( params ) ;
2742 signedQuery . set ( "checksum" , checksum ( method , query , sharedSecret ) ) ;
@@ -37,7 +52,9 @@ const assertSuccessResponse = async (response: Response) => {
3752} ;
3853
3954const getBigBlueButtonConfig = async ( ) => {
40- const appKeys = ( await getAppKeysFromSlug ( metadata . slug ) ) as BigBlueButtonKeys ;
55+ const appKeys = ( await getAppKeysFromSlug (
56+ metadata . slug ,
57+ ) ) as BigBlueButtonKeys ;
4158 const serverUrl = appKeys . bigBlueButtonServerUrl ?. trim ( ) ;
4259 const sharedSecret = appKeys . bigBlueButtonSharedSecret ?. trim ( ) ;
4360
@@ -59,8 +76,16 @@ const BigBlueButtonVideoApiAdapter = (): VideoApiAdapter => {
5976 createMeeting : async ( eventData : CalendarEvent ) : Promise < VideoCallData > => {
6077 const { apiUrl, sharedSecret } = await getBigBlueButtonConfig ( ) ;
6178 const meetingID = eventData . uid || randomUUID ( ) ;
62- const attendeePassword = deriveMeetingPassword ( "attendee" , meetingID , sharedSecret ) ;
63- const moderatorPassword = deriveMeetingPassword ( "moderator" , meetingID , sharedSecret ) ;
79+ const attendeePassword = deriveMeetingPassword (
80+ "attendee" ,
81+ meetingID ,
82+ sharedSecret ,
83+ ) ;
84+ const moderatorPassword = deriveMeetingPassword (
85+ "moderator" ,
86+ meetingID ,
87+ sharedSecret ,
88+ ) ;
6489
6590 const createParams = new URLSearchParams ( {
6691 name : eventData . title ,
@@ -70,7 +95,12 @@ const BigBlueButtonVideoApiAdapter = (): VideoApiAdapter => {
7095 record : "false" ,
7196 } ) ;
7297
73- const createUrl = buildApiUrl ( apiUrl , "create" , createParams , sharedSecret ) ;
98+ const createUrl = buildApiUrl (
99+ apiUrl ,
100+ "create" ,
101+ createParams ,
102+ sharedSecret ,
103+ ) ;
74104 await assertSuccessResponse ( await fetch ( createUrl ) ) ;
75105
76106 const joinParams = new URLSearchParams ( {
@@ -89,21 +119,35 @@ const BigBlueButtonVideoApiAdapter = (): VideoApiAdapter => {
89119 } ,
90120 deleteMeeting : async ( uid : string ) : Promise < void > => {
91121 const { apiUrl, sharedSecret } = await getBigBlueButtonConfig ( ) ;
92- const moderatorPassword = deriveMeetingPassword ( "moderator" , uid , sharedSecret ) ;
122+ const moderatorPassword = deriveMeetingPassword (
123+ "moderator" ,
124+ uid ,
125+ sharedSecret ,
126+ ) ;
93127
94128 const endParams = new URLSearchParams ( {
95129 meetingID : uid ,
96130 password : moderatorPassword ,
97131 } ) ;
98132
99- await assertSuccessResponse ( await fetch ( buildApiUrl ( apiUrl , "end" , endParams , sharedSecret ) ) ) ;
133+ await assertSuccessResponse (
134+ await fetch ( buildApiUrl ( apiUrl , "end" , endParams , sharedSecret ) ) ,
135+ ) ;
100136 } ,
101137 updateMeeting : ( bookingRef : PartialReference ) : Promise < VideoCallData > => {
138+ const { meetingId, meetingPassword, meetingUrl } = bookingRef ;
139+
140+ if ( ! meetingId || ! meetingPassword || ! meetingUrl ) {
141+ throw new Error (
142+ "BigBlueButton booking reference is missing meeting data" ,
143+ ) ;
144+ }
145+
102146 return Promise . resolve ( {
103147 type : metadata . type ,
104- id : bookingRef . meetingId as string ,
105- password : bookingRef . meetingPassword as string ,
106- url : bookingRef . meetingUrl as string ,
148+ id : meetingId ,
149+ password : meetingPassword ,
150+ url : meetingUrl ,
107151 } ) ;
108152 } ,
109153 } ;
0 commit comments