forked from External/greenlight
Add endpoint to detect new recordings and update the interface
The endpoint receives events from BigBlueButton via webhooks or scripts in the record and playback workflow. For now it only treats the event for when a recording is ready. When it happens, it uses action cable to update the interface dynamically with the new recording.
This commit is contained in:
@ -20,6 +20,9 @@ class BbbController < ApplicationController
|
||||
before_action :authorize_recording_owner!, only: [:update_recordings, :delete_recordings]
|
||||
before_action :load_and_authorize_room_owner!, only: [:end]
|
||||
|
||||
skip_before_action :verify_authenticity_token, only: :callback
|
||||
before_action :validate_checksum, only: :callback
|
||||
|
||||
# GET /:resource/:id/join
|
||||
def join
|
||||
if params[:name].blank?
|
||||
@ -39,7 +42,9 @@ class BbbController < ApplicationController
|
||||
user_is_moderator: true
|
||||
}
|
||||
end
|
||||
options[:meeting_logout_url] = "#{request.base_url}/#{params[:resource]}/#{params[:id]}"
|
||||
base_url = "#{request.base_url}/#{params[:resource]}/#{params[:id]}"
|
||||
options[:meeting_logout_url] = base_url
|
||||
options[:hook_url] = "#{base_url}/callback"
|
||||
|
||||
bbb_res = bbb_join_url(
|
||||
params[:id],
|
||||
@ -55,6 +60,20 @@ class BbbController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# POST /:resource/:id/callback
|
||||
# Endpoint for webhook calls from BigBlueButton
|
||||
def callback
|
||||
begin
|
||||
data = JSON.parse(read_body(request))
|
||||
treat_callback_event(data["event"])
|
||||
rescue Exception => e
|
||||
logger.error "Error parsing webhook data. Data: #{data}, exception: #{e.inspect}"
|
||||
|
||||
# respond with 200 anyway so BigBlueButton knows the hook call was ok
|
||||
render head(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /rooms/:id/end
|
||||
def end
|
||||
load_and_authorize_room_owner!
|
||||
@ -130,4 +149,61 @@ class BbbController < ApplicationController
|
||||
@response = response
|
||||
render status: @status
|
||||
end
|
||||
|
||||
def read_body(request)
|
||||
request.body.read.force_encoding("UTF-8")
|
||||
end
|
||||
|
||||
def treat_callback_event(event)
|
||||
|
||||
# a recording is ready
|
||||
if event['header']['name'] == "publish_ended"
|
||||
token = event['payload']['metadata'][META_TOKEN]
|
||||
record_id = event['payload']['meeting_id']
|
||||
|
||||
# the webhook event doesn't have all the data we need, so we need
|
||||
# to send a getRecordings anyway
|
||||
# TODO: if the webhooks included all data we wouldn't need this
|
||||
rec_info = bbb_get_recordings(token, record_id)
|
||||
rec_info = rec_info[:recordings].first
|
||||
RecordingCreatedJob.perform_later(token, parse_recording_for_view(rec_info))
|
||||
end
|
||||
|
||||
render head(:ok) && return
|
||||
end
|
||||
|
||||
# Validates the checksum received in a callback call.
|
||||
# If the checksum doesn't match, renders an ok and aborts execution.
|
||||
def validate_checksum
|
||||
secret = ENV['BIGBLUEBUTTON_SECRET']
|
||||
checksum = params["checksum"]
|
||||
data = read_body(request)
|
||||
callback_url = uri_remove_param(request.url, "checksum")
|
||||
|
||||
checksum_str = "#{callback_url}#{data}#{secret}"
|
||||
calculated_checksum = Digest::SHA1.hexdigest(checksum_str)
|
||||
|
||||
if calculated_checksum != checksum
|
||||
logger.error "Checksum did not match. Calculated: #{calculated_checksum}, received: #{checksum}"
|
||||
|
||||
# respond with 200 anyway so BigBlueButton knows the hook call was ok
|
||||
# but abort execution
|
||||
render head(:ok) && return
|
||||
end
|
||||
end
|
||||
|
||||
# Removes parameters from an URI
|
||||
def uri_remove_param(uri, params = nil)
|
||||
return uri unless params
|
||||
params = Array(params)
|
||||
uri_parsed = URI.parse(uri)
|
||||
return uri unless uri_parsed.query
|
||||
new_params = uri_parsed.query.gsub(/&/, '&').split('&').reject { |q| params.include?(q.split('=').first) }
|
||||
uri = uri.split('?').first
|
||||
if new_params.count > 0
|
||||
"#{uri}?#{new_params.join('&')}"
|
||||
else
|
||||
uri
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user