diff --git a/app/assets/javascripts/active_meetings.js b/app/assets/javascripts/active_meetings.js
index 9a578b49..aef51e6a 100644
--- a/app/assets/javascripts/active_meetings.js
+++ b/app/assets/javascripts/active_meetings.js
@@ -31,22 +31,41 @@ var updatePreviousMeetings = function(){
});
}
+// Ignore excess on either side of user_id.
+var trimUserId = function(user_id){
+ components = user_id.split('_')
+ return components.sort(function (a, b) {return b.length - a.length;})[0]
+}
+
+// Finds a user by their user_id.
+var findByUserId = function(users, user_id){
+ for(i = 0; i < users.length; i++){
+ if(trimUserId(users[i]['user_id']) == trimUserId(user_id)){
+ return i
+ }
+ }
+ return undefined
+}
+
// Adds a user to a meeting.
var addUser = function(data){
if(data['role'] == 'MODERATOR'){
- MEETINGS[data['meeting']]['moderators'].push(data['user'])
+ MEETINGS[data['meeting']]['moderators'].push({'name': data['user'], 'user_id': data['user_id']})
} else {
- MEETINGS[data['meeting']]['participants'].push(data['user'])
+ MEETINGS[data['meeting']]['participants'].push({'name':data['user'], 'user_id': data['user_id']})
}
updateMeetingText(MEETINGS[data['meeting']])
}
// Removes a user from a meeting.
var removeUser = function(data){
- if(data['role'] == 'MODERATOR'){
- MEETINGS[data['meeting']]['moderators'].splice(MEETINGS[data['meeting']]['moderators'].indexOf(data['user']), 1);
+ user = findByUserId(MEETINGS[data['meeting']]['moderators'], data['user_id'])
+ if(user == undefined){
+ user = findByUserId(MEETINGS[data['meeting']]['participants'], data['user_id']);
+ if(user == undefined){ return; }
+ MEETINGS[data['meeting']]['participants'].splice(user, 1);
} else {
- MEETINGS[data['meeting']]['participants'].splice(MEETINGS[data['meeting']]['participants'].indexOf(data['user']), 1);
+ MEETINGS[data['meeting']]['moderators'].splice(user, 1);
}
updateMeetingText(MEETINGS[data['meeting']])
}
@@ -60,14 +79,15 @@ var updateMeetingText = function(m){
if(m['moderators'].length + m['participants'].length == 0){
list = '(empty)'
} else {
- list = m['moderators'].join('(mod), ') + (m['moderators'].length > 0 ? '(mod)' : '') +
- (m['participants'].length > 0 && m['moderators'].length != 0 ? ', ' : '') + m['participants'].join(', ')
+ list = m['moderators'].map(function(x){ return x['name']; }).join('(mod), ') +
+ (m['moderators'].length > 0 ? '(mod)' : '') +
+ (m['participants'].length > 0 && m['moderators'].length != 0 ? ', ' : '') +
+ (m['participants'].map(function(x){ return x['name']; }).join(', '))
}
body = '' + m['name'] + ': ' + list + ''
// Otherwise it hasn't started (users waiting the join).
} else {
- body = '' + m['name'] + ' (not yet started): ' +
- m['users'].join(', ') + ''
+ body = '' + m['name'] + ' (not yet started): ' + m['users'].join(', ') + ''
}
// If the item doesn't exist, add it and set up join meeting event.
@@ -91,65 +111,41 @@ var initialPopulate = function(){
// Only populate on room resources.
var chopped = window.location.href.split('/')
if (!window.location.href.includes('rooms') || chopped[chopped.length - 2] == $('body').data('current-user')) { return; }
- $.get((window.location.href + '/request').replace('#', ''), function(data){
- var meetings = data['active']['meetings']
- var waiting = data['waiting']
-
- jQuery.each(waiting[$('body').data('current-user')], function(name, users){
- WAITING[name] = {'name': name,
- 'users': users}
- updateMeetingText(WAITING[name])
- });
-
- for(var i = 0; i < meetings.length; i++){
- // Make sure the meeting actually belongs to the current user.
- if(meetings[i]['metadata']['room-id'] != $('body').data('current-user')) { continue; }
- var name = meetings[i]['meetingName']
+
+ $.post((window.location.href + '/statuses').replace('#', ''), {previously_joined: getPreviouslyJoined()})
+ .done(function(data) {
- var attendees;
- if(meetings[i]['attendees']['attendee'] instanceof Array){
- attendees = meetings[i]['attendees']['attendee']
- } else {
- attendees = [meetings[i]['attendees']['attendee']]
- }
+ // Populate waiting meetings.
+ Object.keys(data['waiting']).forEach(function(key) {
+ WAITING[name] = {'name': key, 'users': data['waiting'][key]}
+ updateMeetingText(WAITING[name])
+ })
- var participants = []
- var moderators = []
-
- jQuery.each(attendees, function(i, attendee){
- // The API doesn't return a empty array when empty, just undefined.
- if(attendee != undefined){
- if(attendee['role'] == "MODERATOR"){
- moderators.push(attendee['fullName'])
- } else {
- participants.push(attendee['fullName'])
- }
- }
- });
-
- // Create meeting.
- MEETINGS[name] = {'name': name,
- 'participants': participants,
- 'moderators': moderators}
-
- if(isPreviouslyJoined(name)){
+ // Add the meetings to the active meetings list.
+ for(var i = 0; i < data['active'].length; i++){
+ var meeting = data['active'][i]
+
+ var name = meeting['name']
+ var participants = meeting['participants']
+ var moderators = meeting['moderators']
+
+ // Create meeting.
+ MEETINGS[name] = {'name': name, 'participants': participants, 'moderators': moderators}
updateMeetingText(MEETINGS[name])
}
- }
-
- }).done(function(){
- // Remove from previous meetings if they are active.
- updatePreviousMeetings();
- $('.hidden-list').show();
- $('.active-spinner').hide();
- });
+
+ // Remove from previous meetings if they are active.
+ updatePreviousMeetings();
+ $('.hidden-list').show();
+ $('.active-spinner').hide();
+ });
}
-// Checks if a meeting has been prveiously joined by the user.
-var isPreviouslyJoined = function(meeting){
+// Gets a list of known previously joined meetings.
+var getPreviouslyJoined = function(){
var joinedMeetings = localStorage.getItem('joinedRooms-' + $('body').data('current-user'));
- if (joinedMeetings == '' || joinedMeetings == null){ return false; }
- return joinedMeetings.split(',').indexOf(meeting) >= 0
+ if (joinedMeetings == '' || joinedMeetings == null){ return []; }
+ return joinedMeetings.split(',')
}
// Removes an active meeting.
@@ -183,7 +179,6 @@ var joinMeeting = function(meeting_name){
// Only need to register for logged in users.
$(document).on('turbolinks:load', function(){
if($('body').data('current-user')){
-
MEETINGS = {}
// Ensure actives is empty.
$('.actives').empty();
diff --git a/app/controllers/bbb_controller.rb b/app/controllers/bbb_controller.rb
index 6134e320..01491635 100644
--- a/app/controllers/bbb_controller.rb
+++ b/app/controllers/bbb_controller.rb
@@ -259,7 +259,12 @@ class BbbController < ApplicationController
end
def treat_callback_event(event)
- eventName = (event.present? && event['header'].present?) ? event['header']['name'] : nil
+ # Check if the event is a BigBlueButton 2.0 event.
+ if event.has_key?('envelope')
+ eventName = (event.present? && event['envelope'].present?) ? event['envelope']['name'] : nil
+ else # The event came from BigBlueButton 1.1 (or earlier).
+ eventName = (event.present? && event['header'].present?) ? event['header']['name'] : nil
+ end
# a recording is ready
if eventName == "publish_ended"
@@ -286,11 +291,11 @@ class BbbController < ApplicationController
else
logger.error "Bad format for event #{event}, won't process"
end
- elsif eventName == "meeting_created_message"
+ elsif eventName == "meeting_created_message" || eventName == "MeetingCreatedEvtMsg"
# Fire an Actioncable event that updates _previously_joined for the client.
- actioncable_event('create', params[:id], params[:room_id])
- elsif eventName == "meeting_destroyed_event"
- actioncable_event('destroy', params[:id], params[:room_id])
+ actioncable_event('create')
+ elsif eventName == "meeting_destroyed_event" || eventName == "MeetingEndedEvtMsg"
+ actioncable_event('destroy')
# Since the meeting is destroyed we have no way get the callback url to remove the meeting, so we must build it.
remove_url = build_callback_url(params[:id], params[:room_id])
@@ -298,9 +303,13 @@ class BbbController < ApplicationController
# Remove webhook for the meeting.
webhook_remove(remove_url)
elsif eventName == "user_joined_message"
- actioncable_event('join', params[:id], params[:room_id], event['payload']['user']['name'], event['payload']['user']['role'])
+ actioncable_event('join', {user_id: event['payload']['user']['extern_userid'], user: event['payload']['user']['name'], role: event['payload']['user']['role']})
+ elsif eventName == "UserJoinedMeetingEvtMsg"
+ actioncable_event('join', {user_id: event['core']['body']['intId'], user: event['core']['body']['name'], role: event['core']['body']['role']})
elsif eventName == "user_left_message"
- actioncable_event('leave', params[:id], params[:room_id], event['payload']['user']['name'], event['payload']['user']['role'])
+ actioncable_event('leave', {user_id: event['payload']['user']['extern_userid']})
+ elsif eventName == "UserLeftMeetingEvtMsg"
+ actioncable_event('leave', {user_id: event['core']['body']['intId']})
else
logger.info "Callback event will not be treated. Event name: #{eventName}"
end
@@ -312,13 +321,9 @@ class BbbController < ApplicationController
"#{request.base_url}#{relative_root}/rooms/#{room_id}/#{URI.encode(id)}/callback"
end
- def actioncable_event(method, id, room_id, user = 'none', role = 'none')
- ActionCable.server.broadcast 'refresh_meetings',
- method: method,
- meeting: id,
- room: room_id,
- user: user,
- role: role
+ def actioncable_event(method, data = {})
+ data = {method: method, meeting: params[:id], room: params[:room_id]}.merge(data)
+ ActionCable.server.broadcast('refresh_meetings', data)
end
# Validates the checksum received in a callback call.
diff --git a/app/controllers/landing_controller.rb b/app/controllers/landing_controller.rb
index a6f6aa37..8cdeda16 100644
--- a/app/controllers/landing_controller.rb
+++ b/app/controllers/landing_controller.rb
@@ -44,9 +44,38 @@ class LandingController < ApplicationController
# If someone tries to access the guest landing when guest access is enabled, just send them to root.
redirect_to root_url unless Rails.configuration.disable_guest_access
end
-
- def send_meetings_data
- render json: {active: bbb.get_meetings, waiting: WaitingList.waiting}
+
+ # Sends data on meetings that the current user has previously joined.
+ def get_previous_meeting_statuses
+ previously_joined = params[:previously_joined]
+ active_meetings = bbb.get_meetings[:meetings]
+ payload = {active: [], waiting: []}
+ # Find meetings that are owned by the current user and also active.
+ active_meetings.each do |m|
+ if m[:metadata].has_key?(:'room-id')
+ if previously_joined.include?(m[:meetingName])&& m[:metadata][:'room-id'] == current_user[:encrypted_id]
+ if m[:attendees] == {}
+ attendees = []
+ else
+ attendees = m[:attendees][:attendee]
+ attendees = [attendees] unless attendees.is_a?(Array)
+ end
+ participants = []
+ moderators = []
+ attendees.each do |a|
+ if a[:role] == 'MODERATOR'
+ moderators << {name: a[:fullName], user_id: a[:userID]}
+ else
+ participants << {name: a[:fullName], user_id: a[:userID]}
+ end
+ end
+ payload[:active] << {name: m[:meetingName], moderators: moderators, participants: participants}
+ end
+ end
+ end
+ # Add the waiting meetings.
+ payload[:waiting] = WaitingList.waiting[current_user[:encrypted_id]] || {}
+ render json: payload
end
def wait_for_moderator
diff --git a/config/routes.rb b/config/routes.rb
index faa14a1f..8c854167 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -51,7 +51,7 @@ Rails.application.routes.draw do
post '/:room_id/:id/callback', to: 'bbb#callback', :constraints => {:id => disallow_slash, :room_id => disallow_slash}
# routes shared between meetings and rooms
- get '/(:room_id)/request', to: 'landing#send_meetings_data', :defaults => { :format => 'xml' }
+ post '/(:room_id)/statuses', to: 'landing#get_previous_meeting_statuses'
get '/(:room_id)/:id/join', to: 'bbb#join', defaults: {room_id: nil, format: 'json'}, :constraints => {:id => disallow_slash, :room_id => disallow_slash}
get '/(:room_id)/:id', to: 'landing#resource', as: :meeting_room, defaults: {room_id: nil}, :constraints => {:id => disallow_slash, :room_id => disallow_slash}
end