diff --git a/app/assets/javascripts/channels/meeting_updates.js b/app/assets/javascripts/channels/meeting_updates.js
index ddde60f8..0cf1ba32 100644
--- a/app/assets/javascripts/channels/meeting_updates.js
+++ b/app/assets/javascripts/channels/meeting_updates.js
@@ -62,13 +62,13 @@
};
$(document).on("turbolinks:load", function() {
+ // disable meeting updates if enabled from a previous page
+ if (App.meeting_update) {
+ disableMeetingUpdates();
+ }
if ($("body[data-controller=landing]").get(0)) {
if ($("body[data-action=rooms]").get(0)) {
- // disable meeting updates if enabled from a previous page
- if (App.meeting_update) {
- disableMeetingUpdates();
- }
- if ($(".page-wrapper.rooms").data('main-room') === false) {
+ if (!$(".page-wrapper.rooms").data('main-room')) {
enableMeetingUpdates();
}
}
diff --git a/app/assets/javascripts/channels/recording_update.js b/app/assets/javascripts/channels/recording_update.js
index 2b517ccd..eb8a93c4 100644
--- a/app/assets/javascripts/channels/recording_update.js
+++ b/app/assets/javascripts/channels/recording_update.js
@@ -16,10 +16,11 @@
(function() {
- var initRooms = function() {
- App.messages = App.cable.subscriptions.create({
+ var enableRecordingUpdates = function() {
+ App.recording_update = App.cable.subscriptions.create({
channel: 'RecordingUpdatesChannel',
- encrypted_id: $(".page-wrapper").data('id')
+ admin_id: $(".page-wrapper.rooms").data('admin-id'),
+ meeting_id: $(".page-wrapper.rooms").data('id')
},
{
received: function(data) {
@@ -57,10 +58,19 @@
});
};
+ var disableRecordingUpdates = function() {
+ App.recording_update.unsubscribe();
+ delete App.recording_update
+ };
+
$(document).on("turbolinks:load", function() {
+ // disable recording updates if enabled from a previous page
+ if (App.recording_update) {
+ disableRecordingUpdates();
+ }
if ($("body[data-controller=landing]").get(0)) {
if ($("body[data-action=rooms]").get(0)) {
- initRooms();
+ enableRecordingUpdates();
}
}
});
diff --git a/app/assets/javascripts/recordings.coffee b/app/assets/javascripts/recordings.coffee
index af206b5f..25696d27 100644
--- a/app/assets/javascripts/recordings.coffee
+++ b/app/assets/javascripts/recordings.coffee
@@ -34,6 +34,7 @@ class @Recordings
},
columns: [
{ data: "start_time" },
+ { data: "name", visible: $(".page-wrapper.rooms").data('main-room') },
{ data: "previews", orderable: false },
{ data: "duration", orderable: false },
{ data: "playbacks", orderable: false },
@@ -55,7 +56,7 @@ class @Recordings
return data
},
{
- targets: 1,
+ targets: 2,
render: (data, type, row) ->
if type == 'display'
str = ''
@@ -66,7 +67,7 @@ class @Recordings
return data
},
{
- targets: 3,
+ targets: 4,
render: (data, type, row) ->
if type == 'display'
str = ''
@@ -157,7 +158,7 @@ class @Recordings
# refresh the recordings from the server
refresh: ->
table_api = this.table.api()
- $.get "/rooms/"+Meeting.getInstance().getAdminId()+"/recordings", (data) =>
+ $.get @getRecordingsURL(), (data) =>
@setOwner(data.is_owner)
if !@owner
table_api.column(-1).visible(false)
@@ -172,11 +173,12 @@ class @Recordings
# setup click handlers for the action buttons
setupActionHandlers: ->
table_api = this.table.api()
+ recordingsObject = this
@getTable().on 'click', '.recording-update', (event) ->
btn = $(this)
row = table_api.row($(this).closest('tr')).data()
- url = $('.meeting-url').val()
+ url = recordingsObject.getRecordingsURL()
id = row.id
published = btn.data('visibility') == "unlisted" ||
@@ -189,7 +191,7 @@ class @Recordings
data["meta_" + GreenLight.META_LISTED] = listed.toString();
$.ajax({
method: 'PATCH',
- url: url+'/recordings/'+id,
+ url: url+'/'+id,
data: data
}).done((data) ->
@@ -200,12 +202,12 @@ class @Recordings
@getTable().on 'click', '.recording-delete', (event) ->
btn = $(this)
row = table_api.row($(this).closest('tr')).data()
- url = $('.meeting-url').val()
+ url = recordingsObject.getRecordingsURL()
id = row.id
btn.prop('disabled', true)
$.ajax({
method: 'DELETE',
- url: url+'/recordings/'+id
+ url: url+'/'+id
}).done((data) ->
).fail((data) ->
@@ -218,6 +220,13 @@ class @Recordings
getTable: ->
@table
+ getRecordingsURL: ->
+ if $(".page-wrapper.rooms").data('main-room')
+ base_url = '/rooms/'+Meeting.getInstance().getAdminId()
+ else
+ base_url = $('.meeting-url').val()
+ base_url+'/recordings'
+
isOwner: ->
@owner
diff --git a/app/channels/recording_updates_channel.rb b/app/channels/recording_updates_channel.rb
index 3e598a9f..f98bb617 100644
--- a/app/channels/recording_updates_channel.rb
+++ b/app/channels/recording_updates_channel.rb
@@ -16,6 +16,11 @@
class RecordingUpdatesChannel < ApplicationCable::Channel
def subscribed
- stream_from "#{params[:encrypted_id]}_recording_updates_channel"
+ full_id = if params[:meeting_id].present?
+ "#{params[:admin_id]}-#{params[:meeting_id]}"
+ else
+ params[:admin_id]
+ end
+ stream_from "#{full_id}_recording_updates_channel"
end
end
diff --git a/app/controllers/bbb_controller.rb b/app/controllers/bbb_controller.rb
index 1ef59478..2ee0f447 100644
--- a/app/controllers/bbb_controller.rb
+++ b/app/controllers/bbb_controller.rb
@@ -24,6 +24,7 @@ class BbbController < ApplicationController
before_action :validate_checksum, only: :callback
# GET /:resource/:id/join
+ # GET /:resource/:room_id/:id/join
def join
if params[:name].blank?
return render_bbb_response(
@@ -56,6 +57,7 @@ class BbbController < ApplicationController
wait_for_moderator: true,
meeting_recorded: true,
meeting_name: meeting_name,
+ room_owner: params[:room_id],
user_is_moderator: current_user == user
}
else
@@ -102,6 +104,7 @@ class BbbController < ApplicationController
end
# DELETE /rooms/:id/end
+ # DELETE /rooms/:room_id/:id/end
def end
load_and_authorize_room_owner!
@@ -113,30 +116,37 @@ class BbbController < ApplicationController
end
# GET /rooms/:id/recordings
+ # GET /rooms/:room_id/:id/recordings
def recordings
load_room!
# bbb_res = bbb_get_recordings "#{@user.encrypted_id}-#{params[:id]}"
- bbb_res = bbb_get_recordings "#{@user.encrypted_id}"
+ options = { "meta_room-id": @user.encrypted_id }
+ if params[:id]
+ options["meta_meeting-name"] = params[:id]
+ end
+ bbb_res = bbb_get_recordings(options)
render_bbb_response bbb_res, bbb_res[:recordings]
end
# PATCH /rooms/:id/recordings/:record_id
+ # PATCH /rooms/:room_id/:id/recordings/:record_id
def update_recordings
published = params[:published] == 'true'
metadata = params.select{ |k, v| k.match(/^meta_/) }
bbb_res = bbb_update_recordings(params[:record_id], published, metadata)
if bbb_res[:returncode]
- RecordingUpdatesJob.perform_later(@user.encrypted_id, params[:record_id])
+ RecordingUpdatesJob.perform_later(@user.encrypted_id, params[:record_id], params[:id])
end
render_bbb_response bbb_res
end
# DELETE /rooms/:id/recordings/:record_id
+ # DELETE /rooms/:room_id/:id/recordings/:record_id
def delete_recordings
bbb_res = bbb_delete_recordings(params[:record_id])
if bbb_res[:returncode]
- RecordingDeletesJob.perform_later(@user.encrypted_id, params[:record_id])
+ RecordingDeletesJob.perform_later(@user.encrypted_id, params[:record_id], params[:id])
end
render_bbb_response bbb_res
end
@@ -161,7 +171,7 @@ class BbbController < ApplicationController
def authorize_recording_owner!
load_and_authorize_room_owner!
- recordings = bbb_get_recordings(params[:room_id])[:recordings]
+ recordings = bbb_get_recordings({recordID: params[:record_id]})[:recordings]
recordings.each do |recording|
if recording[:recordID] == params[:record_id]
return true
@@ -194,7 +204,7 @@ class BbbController < ApplicationController
# 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 in the event we wouldn't need this
- rec_info = bbb_get_recordings(token, record_id)
+ rec_info = bbb_get_recordings({recordID: record_id})
rec_info = rec_info[:recordings].first
RecordingCreatedJob.perform_later(token, parse_recording_for_view(rec_info))
diff --git a/app/jobs/recording_deletes_job.rb b/app/jobs/recording_deletes_job.rb
index 74df9abd..10a144e3 100644
--- a/app/jobs/recording_deletes_job.rb
+++ b/app/jobs/recording_deletes_job.rb
@@ -19,16 +19,21 @@ class RecordingDeletesJob < ApplicationJob
queue_as :default
- def perform(room, record_id)
+ def perform(room, record_id, meeting=nil)
tries = 0
sleep_time = 2
while tries < 4
- bbb_res = bbb_get_recordings(nil, record_id)
+ bbb_res = bbb_get_recordings({recordID: record_id})
if !bbb_res[:recordings] || bbb_res[:messageKey] == 'noRecordings'
+ full_id = room
+ full_id += "-#{recording[:metadata][:"meeting-name"]}"
ActionCable.server.broadcast "#{room}_recording_updates_channel",
action: 'delete',
id: record_id
+ ActionCable.server.broadcast "#{full_id}_recording_updates_channel",
+ action: 'delete',
+ id: record_id
break
end
sleep sleep_time
diff --git a/app/jobs/recording_updates_job.rb b/app/jobs/recording_updates_job.rb
index 9dafbb2f..319d016c 100644
--- a/app/jobs/recording_updates_job.rb
+++ b/app/jobs/recording_updates_job.rb
@@ -19,13 +19,20 @@ class RecordingUpdatesJob < ApplicationJob
queue_as :default
- def perform(room, record_id)
- bbb_res = bbb_get_recordings(nil, record_id)
+ def perform(room, record_id, meeting=nil)
+ bbb_res = bbb_get_recordings({recordID: record_id})
recording = bbb_res[:recordings].first
+ full_id = room
+ full_id += "-#{recording[:metadata][:"meeting-name"]}"
ActionCable.server.broadcast "#{room}_recording_updates_channel",
action: 'update',
id: record_id,
published: recording[:published],
listed: bbb_is_recording_listed(recording)
+ ActionCable.server.broadcast "#{full_id}_recording_updates_channel",
+ action: 'update',
+ id: record_id,
+ published: recording[:published],
+ listed: bbb_is_recording_listed(recording)
end
end
diff --git a/app/lib/bbb_api.rb b/app/lib/bbb_api.rb
index 35f3c450..56a68606 100644
--- a/app/lib/bbb_api.rb
+++ b/app/lib/bbb_api.rb
@@ -47,6 +47,7 @@ module BbbApi
options[:wait_for_moderator] ||= false
options[:meeting_logout_url] ||= nil
options[:meeting_name] ||= meeting_token
+ options[:room_owner] ||= nil
if !bbb
return call_invalid_res
@@ -81,6 +82,12 @@ module BbbApi
{ "meta_#{BbbApi::META_HOOK_URL}": options[:hook_url] }
) if options[:hook_url]
+ # these parameters are used to filter recordings by room and meeting
+ meeting_options.merge!(
+ { "meta_room-id": options[:room_owner],
+ "meta_meeting-name": options[:meeting_name]}
+ ) if options[:room_owner]
+
if Rails.configuration.use_webhooks
webhook_register(options[:hook_url], meeting_id)
end
@@ -114,13 +121,9 @@ module BbbApi
response_data = bbb_exception_res exc
end
- def bbb_get_recordings(meeting_id, record_id=nil)
- options={}
- if record_id
- options[:recordID] = record_id
- end
- if meeting_id
- options[:meetingID] = bbb_meeting_id(meeting_id)
+ def bbb_get_recordings(options={})
+ if options[:meetingID]
+ options[:meetingID] = bbb_meeting_id(options[:meetingID])
end
res = bbb_safe_execute :get_recordings, options
diff --git a/app/views/landing/rooms.html.erb b/app/views/landing/rooms.html.erb
index 6184ad6f..ff613273 100644
--- a/app/views/landing/rooms.html.erb
+++ b/app/views/landing/rooms.html.erb
@@ -36,6 +36,7 @@ with BigBlueButton; if not, see
<%= t('date_recorded') %> | +<%= t('name') %> | <%= t('thumbnails') %> | <%= t('duration') %> | <%= t('views') %> | diff --git a/config/locales/en-us.yml b/config/locales/en-us.yml index f63662a4..df7a651f 100644 --- a/config/locales/en-us.yml +++ b/config/locales/en-us.yml @@ -88,6 +88,7 @@ en-US: body: "You have been invited by %{user} to a meeting.\n\nPlease open the following page in your web browser: &&URL&&" subject: "%{user} invited you to a meeting" my_room: my room + name: Name no: No notification_mailer: recording_ready_email: diff --git a/config/routes.rb b/config/routes.rb index 8725dff3..5817bb61 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -28,18 +28,28 @@ Rails.application.routes.draw do # There are two resources [meetings|rooms] # meetings offer a landing page for NON authenticated users to create and join session in BigBlueButton # rooms offer a customized landing page for authenticated users to create and join session in BigBlueButton + + # recording routes for updating, deleting and viewing recordings + get '/rooms/:room_id/recordings', to: 'bbb#recordings', defaults: {format: 'json'} + patch '/rooms/:room_id/recordings/:record_id', to: 'bbb#update_recordings', defaults: {format: 'json'} + delete '/rooms/:room_id/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {format: 'json'} + get '/rooms/:room_id/:id/recordings', to: 'bbb#recordings', defaults: {format: 'json'} + patch '/rooms/:room_id/:id/recordings/:record_id', to: 'bbb#update_recordings', defaults: {format: 'json'} + delete '/rooms/:room_id/:id/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {format: 'json'} + + # room routes for joining, ending, waiting and refreshing authenticated meetings + get '/rooms/:room_id', to: 'landing#resource', resource: 'rooms' + get '/rooms/:room_id/:id', to: 'landing#resource', resource: 'rooms' + get '/rooms/:room_id/:id/join', to: 'bbb#join', resource: 'rooms', defaults: {format: 'json'} + delete '/rooms/:room_id/:id/end', to: 'bbb#end', defaults: {format: 'json'} + + # routes shared between meetings and rooms get '/:resource/:id', to: 'landing#resource', as: :resource get '/:resource/:id/join', to: 'bbb#join', as: :bbb_join, defaults: {format: 'json'} - - get '/rooms/:room_id/recordings', to: 'bbb#recordings', defaults: {format: 'json'} post '/:resource/:id/callback', to: 'bbb#callback' #, defaults: {format: 'json'} - patch '/rooms/:id/recordings/:record_id', to: 'bbb#update_recordings', defaults: {format: 'json'} - delete '/rooms/:id/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {format: 'json'} + get '/:resource/:room_id/:id/wait', to: 'landing#wait_for_moderator' get '/:resource/:room_id/:id/session_status_refresh', to: 'landing#session_status_refresh' - delete '/rooms/:room_id/:id/end', to: 'bbb#end', defaults: {format: 'json'} - get '/rooms/:room_id/:id', to: 'landing#resource', resource: 'rooms' - get '/:resource/:room_id/:id/join', to: 'bbb#join', defaults: {format: 'json'} root to: 'landing#index', :resource => 'meetings'
---|