forked from External/greenlight
commit
5a8e6026d9
|
@ -0,0 +1,39 @@
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var sessionStatusRefresh = function(url) {
|
||||||
|
$.get(url + "/session_status_refresh", function(html) {
|
||||||
|
$(".join-form-wrapper").html(html);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var initRooms = function() {
|
||||||
|
App.messages = App.cable.subscriptions.create({
|
||||||
|
channel: 'MeetingUpdatesChannel',
|
||||||
|
username: getRoomName()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
received: function(data) {
|
||||||
|
if (data.action === 'moderator_joined') {
|
||||||
|
if (!Meeting.getInstance().getModJoined()) {
|
||||||
|
Meeting.getInstance().setModJoined(true);
|
||||||
|
if (Meeting.getInstance().getWaitingForMod()) {
|
||||||
|
loopJoin();
|
||||||
|
} else {
|
||||||
|
sessionStatusRefresh($('.meeting-url').val());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (data.action === 'meeting_ended') {
|
||||||
|
sessionStatusRefresh($('.meeting-url').val());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).on("turbolinks:load", function() {
|
||||||
|
if ($("body[data-controller=landing]").get(0)) {
|
||||||
|
if ($("body[data-action=rooms]").get(0)) {
|
||||||
|
initRooms();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).call(this);
|
|
@ -1,27 +0,0 @@
|
||||||
(function() {
|
|
||||||
|
|
||||||
var initRooms = function() {
|
|
||||||
App.messages = App.cable.subscriptions.create({
|
|
||||||
channel: 'ModeratorJoinsChannel',
|
|
||||||
username: getRoomName()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
received: function(data) {
|
|
||||||
if (!Meeting.getInstance().getModJoined()) {
|
|
||||||
Meeting.getInstance().setModJoined(true);
|
|
||||||
if (Meeting.getInstance().getWaitingForMod()) {
|
|
||||||
loopJoin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$(document).on("turbolinks:load", function() {
|
|
||||||
if ($("body[data-controller=landing]").get(0)) {
|
|
||||||
if ($("body[data-action=rooms]").get(0)) {
|
|
||||||
initRooms();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).call(this);
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
var init = function() {
|
var init = function() {
|
||||||
|
|
||||||
$('.meeting-join').click (function (event) {
|
$('.center-panel').on ('click', '.meeting-join', function (event) {
|
||||||
var url = $('.meeting-url').val();
|
var url = $('.meeting-url').val();
|
||||||
var name = $('.meeting-user-name').val();
|
var name = $('.meeting-user-name').val();
|
||||||
Meeting.getInstance().setURL(url);
|
Meeting.getInstance().setURL(url);
|
||||||
|
@ -34,7 +34,19 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.meeting-url-copy').click (function (e) {
|
$('.center-panel').on ('click', '.meeting-end', function (event) {
|
||||||
|
var jqxhr = Meeting.getInstance().endMeeting();
|
||||||
|
var btn = $(this);
|
||||||
|
btn.prop("disabled", true);
|
||||||
|
jqxhr.done(function(data) {
|
||||||
|
|
||||||
|
});
|
||||||
|
jqxhr.fail(function(xhr, status, error) {
|
||||||
|
console.info("meeting end failed");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.center-panel').on ('click', '.meeting-url-copy', function (event) {
|
||||||
meetingURL = $('.meeting-url');
|
meetingURL = $('.meeting-url');
|
||||||
meetingURL.select();
|
meetingURL.select();
|
||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
|
|
|
@ -36,6 +36,13 @@ class Meeting {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
endMeeting() {
|
||||||
|
return $.ajax({
|
||||||
|
url: this.url + "/end",
|
||||||
|
type: 'DELETE'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setURL(url) {
|
setURL(url) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class MeetingUpdatesChannel < ApplicationCable::Channel
|
||||||
|
def subscribed
|
||||||
|
stream_from "#{params[:username]}_meeting_updates_channel"
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +0,0 @@
|
||||||
class ModeratorJoinsChannel < ApplicationCable::Channel
|
|
||||||
def subscribed
|
|
||||||
stream_from "moderator_#{params[:username]}_join_channel"
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,7 +1,8 @@
|
||||||
class BbbController < ApplicationController
|
class BbbController < ApplicationController
|
||||||
include BbbApi
|
include BbbApi
|
||||||
|
|
||||||
before_action :authorize_owner_recording, only: [:update_recordings, :delete_recordings]
|
before_action :authorize_recording_owner!, only: [:update_recordings, :delete_recordings]
|
||||||
|
before_action :load_and_authorize_room_owner!, only: [:end]
|
||||||
|
|
||||||
# GET /:resource/:id/join
|
# GET /:resource/:id/join
|
||||||
def join
|
def join
|
||||||
|
@ -28,20 +29,29 @@ class BbbController < ApplicationController
|
||||||
)
|
)
|
||||||
|
|
||||||
if bbb_res[:returncode] && current_user && current_user == user
|
if bbb_res[:returncode] && current_user && current_user == user
|
||||||
ActionCable.server.broadcast "moderator_#{user.username}_join_channel",
|
ActionCable.server.broadcast "#{user.username}_meeting_updates_channel",
|
||||||
moderator: "joined"
|
action: 'moderator_joined',
|
||||||
|
moderator: 'joined'
|
||||||
end
|
end
|
||||||
|
|
||||||
render_bbb_response bbb_res, bbb_res[:response]
|
render_bbb_response bbb_res, bbb_res[:response]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# DELETE /rooms/:id/end
|
||||||
|
def end
|
||||||
|
load_and_authorize_room_owner!
|
||||||
|
|
||||||
|
bbb_res = bbb_end_meeting @user.username
|
||||||
|
if bbb_res[:returncode]
|
||||||
|
EndMeetingJob.perform_later(@user.username)
|
||||||
|
end
|
||||||
|
render_bbb_response bbb_res
|
||||||
|
end
|
||||||
|
|
||||||
# GET /rooms/:id/recordings
|
# GET /rooms/:id/recordings
|
||||||
def recordings
|
def recordings
|
||||||
@user = User.find_by username: params[:id]
|
load_room!
|
||||||
if !@user
|
|
||||||
render head(:not_found) && return
|
|
||||||
end
|
|
||||||
|
|
||||||
bbb_res = bbb_get_recordings @user.username
|
bbb_res = bbb_get_recordings @user.username
|
||||||
render_bbb_response bbb_res, bbb_res[:recordings]
|
render_bbb_response bbb_res, bbb_res[:recordings]
|
||||||
|
@ -64,18 +74,27 @@ class BbbController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def authorize_owner_recording
|
def load_room!
|
||||||
user = User.find_by username: params[:id]
|
@user = User.find_by username: params[:id]
|
||||||
if !user
|
if !@user
|
||||||
render head(:not_found) && return
|
render head(:not_found) && return
|
||||||
elsif !current_user || current_user != user
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_and_authorize_room_owner!
|
||||||
|
load_room!
|
||||||
|
|
||||||
|
if !current_user || current_user != @user
|
||||||
render head(:unauthorized) && return
|
render head(:unauthorized) && return
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_recording_owner!
|
||||||
|
load_and_authorize_room_owner!
|
||||||
|
|
||||||
recordings = bbb_get_recordings(params[:id])[:recordings]
|
recordings = bbb_get_recordings(params[:id])[:recordings]
|
||||||
recordings.each do |recording|
|
recordings.each do |recording|
|
||||||
if recording[:recordID] == params[:record_id]
|
if recording[:recordID] == params[:record_id]
|
||||||
@user = user
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -87,6 +106,6 @@ class BbbController < ApplicationController
|
||||||
@message = bbb_res[:message]
|
@message = bbb_res[:message]
|
||||||
@status = bbb_res[:status]
|
@status = bbb_res[:status]
|
||||||
@response = response
|
@response = response
|
||||||
render status: @status && return
|
render status: @status
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
class LandingController < ApplicationController
|
class LandingController < ApplicationController
|
||||||
|
include BbbApi
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if params[:resource] == 'meetings'
|
if params[:resource] == 'meetings'
|
||||||
|
@ -14,6 +15,17 @@ class LandingController < ApplicationController
|
||||||
render layout: false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def session_status_refresh
|
||||||
|
@user = User.find_by(username: params[:id])
|
||||||
|
if @user.nil?
|
||||||
|
render head(:not_found) && return
|
||||||
|
end
|
||||||
|
|
||||||
|
@meeting_running = bbb_get_meeting_info(@user.username)[:returncode]
|
||||||
|
|
||||||
|
render layout: false
|
||||||
|
end
|
||||||
|
|
||||||
def admin?
|
def admin?
|
||||||
@user && @user == current_user
|
@user && @user == current_user
|
||||||
end
|
end
|
||||||
|
@ -29,11 +41,15 @@ class LandingController < ApplicationController
|
||||||
|
|
||||||
def render_room
|
def render_room
|
||||||
params[:action] = 'rooms'
|
params[:action] = 'rooms'
|
||||||
|
|
||||||
@user = User.find_by(username: params[:id])
|
@user = User.find_by(username: params[:id])
|
||||||
if @user.nil?
|
if @user.nil?
|
||||||
redirect_to root_path
|
redirect_to root_path
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@meeting_running = bbb_get_meeting_info(@user.username)[:returncode]
|
||||||
|
|
||||||
render :action => 'rooms'
|
render :action => 'rooms'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
class EndMeetingJob < ApplicationJob
|
||||||
|
include BbbApi
|
||||||
|
|
||||||
|
queue_as :default
|
||||||
|
|
||||||
|
def perform(room)
|
||||||
|
tries = 0
|
||||||
|
sleep_time = 2
|
||||||
|
|
||||||
|
while tries < 4
|
||||||
|
bbb_res = bbb_get_meeting_info(room)
|
||||||
|
|
||||||
|
if !bbb_res[:returncode]
|
||||||
|
ActionCable.server.broadcast "#{room}_meeting_updates_channel",
|
||||||
|
action: 'meeting_ended'
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
sleep sleep_time
|
||||||
|
sleep_time = sleep_time * 2
|
||||||
|
tries += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,6 +11,10 @@ module BbbApi
|
||||||
@bbb ||= BigBlueButton::BigBlueButtonApi.new(bbb_endpoint + "api", bbb_secret, "0.8", true)
|
@bbb ||= BigBlueButton::BigBlueButtonApi.new(bbb_endpoint + "api", bbb_secret, "0.8", true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def bbb_meeting_id(id)
|
||||||
|
Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base]+id).to_s
|
||||||
|
end
|
||||||
|
|
||||||
def random_password(length)
|
def random_password(length)
|
||||||
o = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten
|
o = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten
|
||||||
password = (0...length).map { o[rand(o.length)] }.join
|
password = (0...length).map { o[rand(o.length)] }.join
|
||||||
|
@ -26,7 +30,7 @@ module BbbApi
|
||||||
if !bbb
|
if !bbb
|
||||||
return call_invalid_res
|
return call_invalid_res
|
||||||
else
|
else
|
||||||
meeting_id = (Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base]+meeting_token)).to_s
|
meeting_id = bbb_meeting_id(meeting_token)
|
||||||
|
|
||||||
# See if the meeting is running
|
# See if the meeting is running
|
||||||
begin
|
begin
|
||||||
|
@ -63,10 +67,17 @@ module BbbApi
|
||||||
password = bbb_meeting_info[:attendeePW]
|
password = bbb_meeting_info[:attendeePW]
|
||||||
end
|
end
|
||||||
join_url = bbb.join_meeting_url(meeting_id, full_name, password )
|
join_url = bbb.join_meeting_url(meeting_id, full_name, password )
|
||||||
return success_res(join_url)
|
return success_join_res(join_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def bbb_get_meeting_info(id)
|
||||||
|
meeting_id = bbb_meeting_id(id)
|
||||||
|
response_data = bbb.get_meeting_info(meeting_id, nil)
|
||||||
|
rescue BigBlueButton::BigBlueButtonException => exc
|
||||||
|
response_data = bbb_exception_res exc
|
||||||
|
end
|
||||||
|
|
||||||
def bbb_get_recordings(meeting_id, record_id=nil)
|
def bbb_get_recordings(meeting_id, record_id=nil)
|
||||||
options={}
|
options={}
|
||||||
if record_id
|
if record_id
|
||||||
|
@ -124,6 +135,22 @@ module BbbApi
|
||||||
res
|
res
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def bbb_end_meeting(id)
|
||||||
|
# get meeting info for moderator password
|
||||||
|
meeting_id = bbb_meeting_id(id)
|
||||||
|
bbb_meeting_info = bbb.get_meeting_info(meeting_id, nil)
|
||||||
|
|
||||||
|
response_data = if bbb_meeting_info.is_a?(Hash) && bbb_meeting_info[:moderatorPW]
|
||||||
|
bbb.end_meeting(meeting_id, bbb_meeting_info[:moderatorPW])
|
||||||
|
else
|
||||||
|
{}
|
||||||
|
end
|
||||||
|
response_data[:status] = :ok
|
||||||
|
response_data
|
||||||
|
rescue BigBlueButton::BigBlueButtonException => exc
|
||||||
|
response_data = bbb_exception_res exc
|
||||||
|
end
|
||||||
|
|
||||||
def bbb_update_recordings(id, published)
|
def bbb_update_recordings(id, published)
|
||||||
bbb_safe_execute :publish_recordings, id, published
|
bbb_safe_execute :publish_recordings, id, published
|
||||||
end
|
end
|
||||||
|
@ -147,7 +174,7 @@ module BbbApi
|
||||||
response_data
|
response_data
|
||||||
end
|
end
|
||||||
|
|
||||||
def success_res(join_url)
|
def success_join_res(join_url)
|
||||||
{
|
{
|
||||||
returncode: true,
|
returncode: true,
|
||||||
messageKey: "ok",
|
messageKey: "ok",
|
||||||
|
@ -178,10 +205,19 @@ module BbbApi
|
||||||
end
|
end
|
||||||
|
|
||||||
def bbb_exception_res(exc)
|
def bbb_exception_res(exc)
|
||||||
{
|
res = {
|
||||||
returncode: false,
|
returncode: false,
|
||||||
messageKey: 'BBB'+exc.key.capitalize.underscore,
|
messageKey: 'BBB'+exc.key.capitalize.underscore,
|
||||||
message: exc.message,
|
message: exc.message,
|
||||||
|
status: :unprocessable_entity
|
||||||
|
}
|
||||||
|
if res[:messageKey] == 'BBBnotfound'
|
||||||
|
res[:status] = :not_found
|
||||||
|
end
|
||||||
|
res
|
||||||
|
rescue
|
||||||
|
{
|
||||||
|
returncode: false,
|
||||||
status: :internal_server_error
|
status: :internal_server_error
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
json.partial! 'bbb', messageKey: @messageKey, message: @message, status: @status
|
|
@ -25,7 +25,7 @@
|
||||||
<%= render layout: 'shared/center_panel' do %>
|
<%= render layout: 'shared/center_panel' do %>
|
||||||
<div class="center-block col-sm-8">
|
<div class="center-block col-sm-8">
|
||||||
<%= render 'shared/meeting_url', hidden: false %>
|
<%= render 'shared/meeting_url', hidden: false %>
|
||||||
<%= render 'shared/join_form', user: current_user %>
|
<%= render 'shared/join_form' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,9 @@
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= render 'shared/meeting_url', hidden: true %>
|
<%= render 'shared/meeting_url', hidden: true %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= render 'shared/join_form', user: current_user %>
|
<div class="join-form-wrapper">
|
||||||
|
<%= render 'shared/join_form' %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<%= render 'shared/join_form' %>
|
|
@ -1,14 +1,27 @@
|
||||||
<div class="join-form input-group input-spacing">
|
<div class="join-form input-group input-spacing">
|
||||||
<% if current_user %>
|
<% if current_user %>
|
||||||
<% @current_user = user %>
|
<% @current_user = current_user %>
|
||||||
<%= text_field :current_user, :name, class: 'form-control meeting-user-name', type: 'hidden' %>
|
<%= text_field :current_user, :name, class: 'form-control meeting-user-name', type: 'hidden' %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= text_field :nil, :nil, class: 'form-control meeting-user-name', placeholder: t('enter_name') %>
|
<%= text_field :nil, :nil, class: 'form-control meeting-user-name', placeholder: t('enter_name') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if admin? %>
|
<% if admin? %>
|
||||||
<button type="button" class="btn btn-primary center-block meeting-join">
|
<% if @meeting_running %>
|
||||||
<%= t('start') %>
|
<div class="col-sm-6">
|
||||||
</button>
|
<button type="button" class="btn btn-primary meeting-join pull-right">
|
||||||
|
<%= t('join') %>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<button type="button" class="btn btn-danger meeting-end pull-left">
|
||||||
|
<%= t('end') %>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<button type="button" class="btn btn-primary center-block meeting-join">
|
||||||
|
<%= t('start') %>
|
||||||
|
</button>
|
||||||
|
<% end %>
|
||||||
<% elsif current_user %>
|
<% elsif current_user %>
|
||||||
<button type="button" class="btn btn-primary center-block meeting-join">
|
<button type="button" class="btn btn-primary center-block meeting-join">
|
||||||
<%= t('join') %>
|
<%= t('join') %>
|
||||||
|
|
|
@ -24,6 +24,7 @@ en-US:
|
||||||
are_you: Are you %{name} ?
|
are_you: Are you %{name} ?
|
||||||
date_recorded: Date Recorded
|
date_recorded: Date Recorded
|
||||||
duration: Duration
|
duration: Duration
|
||||||
|
end: End
|
||||||
enter_name: Enter your name
|
enter_name: Enter your name
|
||||||
greet_user: Welcome, %{name}
|
greet_user: Welcome, %{name}
|
||||||
greet_guest: Welcome to %{name} Meeting Space
|
greet_guest: Welcome to %{name} Meeting Space
|
||||||
|
|
|
@ -13,6 +13,8 @@ Rails.application.routes.draw do
|
||||||
get '/:resource/:id', to: 'landing#index', as: :resource
|
get '/:resource/:id', to: 'landing#index', as: :resource
|
||||||
get '/:resource/:id/join', to: 'bbb#join', as: :bbb_join, defaults: {format: 'json'}
|
get '/:resource/:id/join', to: 'bbb#join', as: :bbb_join, defaults: {format: 'json'}
|
||||||
get '/:resource/:id/wait', to: 'landing#wait_for_moderator'
|
get '/:resource/:id/wait', to: 'landing#wait_for_moderator'
|
||||||
|
get '/:resource/:id/session_status_refresh', to: 'landing#session_status_refresh'
|
||||||
|
delete '/rooms/:id/end', to: 'bbb#end', defaults: {format: 'json'}
|
||||||
get '/rooms/:id/recordings', to: 'bbb#recordings', defaults: {format: 'json'}
|
get '/rooms/:id/recordings', to: 'bbb#recordings', defaults: {format: 'json'}
|
||||||
patch '/rooms/:id/recordings/:record_id', to: 'bbb#update_recordings', 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'}
|
delete '/rooms/:id/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {format: 'json'}
|
||||||
|
|
Loading…
Reference in New Issue