forked from External/greenlight
Merge branch 'v2.2.1-alpha' into master
This commit is contained in:
@ -43,9 +43,9 @@ $(document).on('turbolinks:load', function(){
|
||||
|
||||
window.location.replace(url);
|
||||
})
|
||||
|
||||
/* COLOR SELECTORS */
|
||||
}
|
||||
|
||||
if (controller == "admins" && action == "site_settings") {
|
||||
loadColourSelectors()
|
||||
}
|
||||
|
||||
|
41
app/assets/javascripts/recording.js
Normal file
41
app/assets/javascripts/recording.js
Normal file
@ -0,0 +1,41 @@
|
||||
// BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
//
|
||||
// Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU Lesser General Public License as published by the Free Software
|
||||
// Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
// PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License along
|
||||
// with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Handle changing of settings tabs.
|
||||
$(document).on('turbolinks:load', function(){
|
||||
var controller = $("body").data('controller');
|
||||
var action = $("body").data('action');
|
||||
|
||||
if (controller == "rooms" && action == "show"
|
||||
|| controller == "rooms" && action == "update"
|
||||
|| controller == "users" && action == "recordings"
|
||||
|| controller == "admins" && action == "server_recordings"){
|
||||
// Handle recording emails.
|
||||
$('.email-link').each(function(){
|
||||
$(this).click(function(){
|
||||
var subject = $(".username").text() + " " + t('room.mailer.subject');
|
||||
var body = t('room.mailer.body') + "\n\n" + $(this).attr("data-pres-link");
|
||||
var autogenerated = "\n\n" + t('room.mailer.autogenerated') + "\n";
|
||||
var footer = t('room.mailer.footer');
|
||||
|
||||
var url = "mailto:?subject=" + encodeURIComponent(subject) + "&body=" + encodeURIComponent(body) + encodeURIComponent(autogenerated) + encodeURIComponent(footer);
|
||||
var win = window.open(url, '_blank');
|
||||
|
||||
win.focus();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
@ -18,7 +18,10 @@ $(document).on('turbolinks:load', function(){
|
||||
var controller = $("body").data('controller');
|
||||
var action = $("body").data('action');
|
||||
|
||||
if(controller == "rooms" && action == "show" || controller == "rooms" && action == "update" || controller == "users" && action == "recordings"){
|
||||
if(controller == "rooms" && action == "show"
|
||||
|| controller == "rooms" && action == "update"
|
||||
|| controller == "users" && action == "recordings"
|
||||
|| controller == "admins" && action == "server_recordings"){
|
||||
|
||||
// Set a room header rename event
|
||||
var configure_room_header = function(room_title){
|
||||
|
@ -39,29 +39,18 @@ $(document).on('turbolinks:load', function(){
|
||||
}, 2000)
|
||||
}
|
||||
});
|
||||
|
||||
// Handle recording emails.
|
||||
$('.email-link').each(function(){
|
||||
$(this).click(function(){
|
||||
var subject = $(".username").text() + " " + t('room.mailer.subject');
|
||||
var body = t('room.mailer.body') + "\n\n" + $(this).attr("data-pres-link");
|
||||
var autogenerated = "\n\n" + t('room.mailer.autogenerated') + "\n";
|
||||
var footer = t('room.mailer.footer');
|
||||
|
||||
var url = "mailto:?subject=" + encodeURIComponent(subject) + "&body=" + encodeURIComponent(body) + encodeURIComponent(autogenerated) + encodeURIComponent(footer);
|
||||
var win = window.open(url, '_blank');
|
||||
|
||||
win.focus();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Display and update all fields related to creating a room in the createRoomModal
|
||||
$("#create-room-block").click(function(){
|
||||
$("#create-room-name").val("")
|
||||
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code_placeholder") %>")
|
||||
$("#room_access_code").val(null)
|
||||
|
||||
$("#createRoomModal form").attr("action", $("body").data('relative-root'))
|
||||
updateDropdown($(".dropdown-item[value='default']"))
|
||||
$("#room_mute_on_join").prop("checked", false)
|
||||
$("#room_anyone_can_start").prop("checked", false)
|
||||
|
||||
//show all elements & their children with a create-only class
|
||||
$(".create-only").each(function() {
|
||||
@ -95,6 +84,16 @@ $(document).on('turbolinks:load', function(){
|
||||
})
|
||||
|
||||
updateCurrentSettings($(this).closest("#room-block").data("room-settings"))
|
||||
|
||||
accessCode = $(this).closest("#room-block").data("room-access-code")
|
||||
|
||||
if(accessCode){
|
||||
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code") %>: " + accessCode)
|
||||
$("#room_access_code").val(accessCode)
|
||||
} else{
|
||||
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code_placeholder") %>")
|
||||
$("#room_access_code").val(null)
|
||||
}
|
||||
})
|
||||
|
||||
//Update the createRoomModal to show the correct current settings
|
||||
@ -106,6 +105,12 @@ $(document).on('turbolinks:load', function(){
|
||||
$("#room_mute_on_join").prop("checked", false)
|
||||
}
|
||||
|
||||
if(settings.anyoneCanStart){
|
||||
$("#room_anyone_can_start").prop("checked", true)
|
||||
} else { //default option
|
||||
$("#room_anyone_can_start").prop("checked", false)
|
||||
}
|
||||
|
||||
//set dropdown value
|
||||
if (settings.joinViaHtml5) {
|
||||
updateDropdown($(".dropdown-item[value='html5']"))
|
||||
@ -122,3 +127,21 @@ function updateDropdown(element) {
|
||||
$("#dropdown-trigger").text(element.text())
|
||||
$("#room_client").val(element.val())
|
||||
}
|
||||
|
||||
function generateAccessCode(){
|
||||
const accessCodeLength = 6
|
||||
var validCharacters = "0123456789"
|
||||
var accessCode = ""
|
||||
|
||||
for( var i = 0; i < accessCodeLength; i++){
|
||||
accessCode += validCharacters.charAt(Math.floor(Math.random() * validCharacters.length));
|
||||
}
|
||||
|
||||
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code") %>: " + accessCode)
|
||||
$("#room_access_code").val(accessCode)
|
||||
}
|
||||
|
||||
function ResetAccessCode(){
|
||||
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code_placeholder") %>")
|
||||
$("#room_access_code").val(null)
|
||||
}
|
||||
|
@ -22,7 +22,8 @@ $(document).on('turbolinks:load', function(){
|
||||
(controller == "rooms" && action == "show") ||
|
||||
(controller == "rooms" && action == "update") ||
|
||||
(controller == "rooms" && action == "join") ||
|
||||
(controller == "users" && action == "recordings")) {
|
||||
(controller == "users" && action == "recordings") ||
|
||||
(controller == "admins" && action == "server_recordings")) {
|
||||
// Submit search if the user hits enter
|
||||
$("#search-input").keypress(function(key) {
|
||||
var keyPressed = key.which
|
||||
|
@ -20,7 +20,7 @@ $(document).on('turbolinks:load', function(){
|
||||
var action = $("body").data('action');
|
||||
|
||||
// Only run on the settings page.
|
||||
if ((controller == "users" && action == "edit") || (controller == "users" && action == "update") || (controller == "admins" && action == "index")){
|
||||
if ((controller == "users" && action == "edit") || (controller == "users" && action == "update")){
|
||||
var settingsButtons = $('.setting-btn');
|
||||
var settingsViews = $('.setting-view');
|
||||
|
||||
|
@ -18,7 +18,10 @@ $(document).on('turbolinks:load', function(){
|
||||
var controller = $("body").data('controller');
|
||||
var action = $("body").data('action');
|
||||
|
||||
if(controller == "rooms" && action == "show" || controller == "rooms" && action == "update" || controller == "users" && action == "recordings"){
|
||||
if(controller == "rooms" && action == "show"
|
||||
|| controller == "rooms" && action == "update"
|
||||
|| controller == "users" && action == "recordings"
|
||||
|| controller == "admins" && action == "server_recordings"){
|
||||
|
||||
// Choose active header
|
||||
// (Name, Length or Users)
|
||||
|
@ -65,3 +65,7 @@
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
}
|
||||
|
||||
.allow-icon-click{
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ a {
|
||||
color: #6e7687 !important;
|
||||
&:hover {
|
||||
color: $primary-color !important;
|
||||
background-color: $primary-color-lighten !important;
|
||||
}
|
||||
&:active {
|
||||
background-color: $primary-color-lighten !important;
|
||||
@ -130,6 +131,7 @@ input:focus, select:focus {
|
||||
}
|
||||
|
||||
& a {
|
||||
color: $primary-color !important;
|
||||
border-color: $primary-color !important;
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,11 @@ class AdminsController < ApplicationController
|
||||
include Pagy::Backend
|
||||
include Themer
|
||||
include Emailer
|
||||
include Recorder
|
||||
|
||||
manage_users = [:edit_user, :promote, :demote, :ban_user, :unban_user, :approve]
|
||||
site_settings = [:branding, :coloring, :coloring_lighten, :coloring_darken,
|
||||
:registration_method, :room_authentication, :room_limit]
|
||||
:registration_method, :room_authentication, :room_limit, :default_recording_visibility]
|
||||
|
||||
authorize_resource class: false
|
||||
before_action :find_user, only: manage_users
|
||||
@ -40,11 +41,27 @@ class AdminsController < ApplicationController
|
||||
@pagy, @users = pagy(user_list)
|
||||
end
|
||||
|
||||
# GET /admins/site_settings
|
||||
def site_settings
|
||||
end
|
||||
|
||||
# GET /admins/server_recordings
|
||||
def server_recordings
|
||||
server_rooms = if Rails.configuration.loadbalanced_configuration
|
||||
Room.includes(:owner).where(users: { provider: user_settings_provider }).pluck(:bbb_id)
|
||||
else
|
||||
Room.pluck(:bbb_id)
|
||||
end
|
||||
|
||||
@search, @order_column, @order_direction, recs =
|
||||
all_recordings(server_rooms, @user_domain, params.permit(:search, :column, :direction), true, true)
|
||||
@pagy, @recordings = pagy_array(recs)
|
||||
end
|
||||
|
||||
# MANAGE USERS
|
||||
|
||||
# GET /admins/edit/:user_uid
|
||||
def edit_user
|
||||
render "admins/index", locals: { setting_id: "account" }
|
||||
end
|
||||
|
||||
# POST /admins/promote/:user_uid
|
||||
@ -111,7 +128,7 @@ class AdminsController < ApplicationController
|
||||
# POST /admins/branding
|
||||
def branding
|
||||
@settings.update_value("Branding Image", params[:url])
|
||||
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
end
|
||||
|
||||
# POST /admins/color
|
||||
@ -119,23 +136,23 @@ class AdminsController < ApplicationController
|
||||
@settings.update_value("Primary Color", params[:color])
|
||||
@settings.update_value("Primary Color Lighten", color_lighten(params[:color]))
|
||||
@settings.update_value("Primary Color Darken", color_darken(params[:color]))
|
||||
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
end
|
||||
|
||||
def coloring_lighten
|
||||
@settings.update_value("Primary Color Lighten", params[:color])
|
||||
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
end
|
||||
|
||||
def coloring_darken
|
||||
@settings.update_value("Primary Color Darken", params[:color])
|
||||
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
end
|
||||
|
||||
# POST /admins/room_authentication
|
||||
def room_authentication
|
||||
@settings.update_value("Room Authentication", params[:value])
|
||||
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
end
|
||||
|
||||
# POST /admins/registration_method/:method
|
||||
@ -144,11 +161,11 @@ class AdminsController < ApplicationController
|
||||
|
||||
# Only allow change to Join by Invitation if user has emails enabled
|
||||
if !Rails.configuration.enable_email_verification && new_method == Rails.configuration.registration_methods[:invite]
|
||||
redirect_to admins_path,
|
||||
redirect_to admin_site_settings_path,
|
||||
flash: { alert: I18n.t("administrator.flash.invite_email_verification") }
|
||||
else
|
||||
@settings.update_value("Registration Method", new_method)
|
||||
redirect_to admins_path,
|
||||
redirect_to admin_site_settings_path,
|
||||
flash: { success: I18n.t("administrator.flash.registration_method_updated") }
|
||||
end
|
||||
end
|
||||
@ -156,13 +173,20 @@ class AdminsController < ApplicationController
|
||||
# POST /admins/room_limit
|
||||
def room_limit
|
||||
@settings.update_value("Room Limit", params[:limit])
|
||||
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") }
|
||||
end
|
||||
|
||||
# POST /admins/default_recording_visibility
|
||||
def default_recording_visibility
|
||||
@settings.update_value("Default Recording Visibility", params[:visibility])
|
||||
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.settings") + ". " +
|
||||
I18n.t("administrator.site_settings.recording_visibility.warning") }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_user
|
||||
@user = User.find_by!(uid: params[:user_uid])
|
||||
@user = User.where(uid: params[:user_uid]).includes(:roles).first
|
||||
end
|
||||
|
||||
def find_setting
|
||||
@ -176,21 +200,19 @@ class AdminsController < ApplicationController
|
||||
|
||||
# Gets the list of users based on your configuration
|
||||
def user_list
|
||||
initial_list = if current_user.has_role? :super_admin
|
||||
User.where.not(id: current_user.id)
|
||||
initial_list = if current_user.has_cached_role? :super_admin
|
||||
User.where.not(id: current_user.id).includes(:roles)
|
||||
else
|
||||
User.without_role(:super_admin).where.not(id: current_user.id)
|
||||
User.without_role(:super_admin).where.not(id: current_user.id).includes(:roles)
|
||||
end
|
||||
|
||||
list = @role.present? ? initial_list.with_role(@role.to_sym) : initial_list
|
||||
|
||||
if Rails.configuration.loadbalanced_configuration
|
||||
list.where(provider: user_settings_provider)
|
||||
.admins_search(@search)
|
||||
.admins_order(@order_column, @order_direction)
|
||||
initial_list.where(provider: user_settings_provider)
|
||||
.admins_search(@search, @role)
|
||||
.admins_order(@order_column, @order_direction)
|
||||
else
|
||||
list.admins_search(@search)
|
||||
.admins_order(@order_column, @order_direction)
|
||||
initial_list.admins_search(@search, @role)
|
||||
.admins_order(@order_column, @order_direction)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -121,6 +121,9 @@ class ApplicationController < ActionController::Base
|
||||
meeting_logout_url: request.base_url + logout_room_path(@room),
|
||||
meeting_recorded: true,
|
||||
moderator_message: "#{invite_msg}\n\n#{request.base_url + room_path(@room)}",
|
||||
host: request.host,
|
||||
recording_default_visibility: Setting.find_or_create_by!(provider: user_settings_provider)
|
||||
.get_value("Default Recording Visibility") == "public"
|
||||
}
|
||||
end
|
||||
|
||||
@ -131,7 +134,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
# Checks to make sure that the admin has changed his password from the default
|
||||
def check_admin_password
|
||||
if current_user&.has_role?(:admin) && current_user&.greenlight_account? &&
|
||||
if current_user&.has_cached_role?(:admin) && current_user&.greenlight_account? &&
|
||||
current_user&.authenticate(Rails.configuration.admin_password_default)
|
||||
|
||||
flash.now[:alert] = I18n.t("default_admin",
|
||||
@ -179,10 +182,10 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
# Checks if the user is banned and logs him out if he is
|
||||
def check_user_role
|
||||
if current_user&.has_role? :denied
|
||||
if current_user&.has_cached_role? :denied
|
||||
session.delete(:user_id)
|
||||
redirect_to root_path, flash: { alert: I18n.t("registration.banned.fail") }
|
||||
elsif current_user&.has_role? :pending
|
||||
elsif current_user&.has_cached_role? :pending
|
||||
session.delete(:user_id)
|
||||
redirect_to root_path, flash: { alert: I18n.t("registration.approval.fail") }
|
||||
end
|
||||
|
@ -64,13 +64,19 @@ module Emailer
|
||||
def send_approval_user_signup_email(user)
|
||||
return unless Rails.configuration.enable_email_verification
|
||||
|
||||
UserMailer.approval_user_signup(user, admins_url, logo_image, user_color, admin_emails).deliver_now
|
||||
admin_emails = admin_emails()
|
||||
unless admin_emails.empty?
|
||||
UserMailer.approval_user_signup(user, admins_url, logo_image, user_color, admin_emails).deliver_now
|
||||
end
|
||||
end
|
||||
|
||||
def send_invite_user_signup_email(user)
|
||||
return unless Rails.configuration.enable_email_verification
|
||||
|
||||
UserMailer.invite_user_signup(user, admins_url, logo_image, user_color, admin_emails).deliver_now
|
||||
admin_emails = admin_emails()
|
||||
unless admin_emails.empty?
|
||||
UserMailer.invite_user_signup(user, admins_url, logo_image, user_color, admin_emails).deliver_now
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -16,14 +16,53 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
module APIConcern
|
||||
module Recorder
|
||||
extend ActiveSupport::Concern
|
||||
include ::BbbApi
|
||||
|
||||
# Fetches all recordings for a room.
|
||||
def recordings(room_bbb_id, provider, search_params = {}, ret_search_params = false)
|
||||
res = bbb(provider).get_recordings(meetingID: room_bbb_id)
|
||||
|
||||
format_recordings(res, search_params, ret_search_params)
|
||||
end
|
||||
|
||||
# Fetches a rooms public recordings.
|
||||
def public_recordings(room_bbb_id, provider, search_params = {}, ret_search_params = false)
|
||||
search, order_col, order_dir, recs = recordings(room_bbb_id, provider, search_params, ret_search_params)
|
||||
[search, order_col, order_dir, recs.select { |r| r[:metadata][:"gl-listed"] == "true" }]
|
||||
end
|
||||
|
||||
# Makes paginated API calls to get recordings
|
||||
def all_recordings(room_bbb_ids, provider, search_params = {}, ret_search_params = false, search_name = false)
|
||||
pag_num = Rails.configuration.pagination_number
|
||||
|
||||
pag_loops = room_bbb_ids.length / pag_num - 1
|
||||
|
||||
res = { recordings: [] }
|
||||
|
||||
(0..pag_loops).each do |i|
|
||||
pag_rooms = room_bbb_ids[pag_num * i, pag_num]
|
||||
|
||||
# bbb.get_recordings returns an object
|
||||
# take only the array portion of the object that is returned
|
||||
full_res = bbb(provider).get_recordings(meetingID: pag_rooms)
|
||||
res[:recordings].push(*full_res[:recordings])
|
||||
end
|
||||
|
||||
last_pag_room = room_bbb_ids[pag_num * (pag_loops + 1), room_bbb_ids.length % pag_num]
|
||||
|
||||
full_res = bbb(provider).get_recordings(meetingID: last_pag_room)
|
||||
res[:recordings].push(*full_res[:recordings])
|
||||
|
||||
format_recordings(res, search_params, ret_search_params, search_name)
|
||||
end
|
||||
|
||||
# Format, filter, and sort recordings to match their current use in the app
|
||||
def format_recordings(api_res, search_params, ret_search_params)
|
||||
def format_recordings(api_res, search_params, ret_search_params, search_name = false)
|
||||
search = search_params[:search] || ""
|
||||
order_col = search_params[:column] && search_params[:direction] != "none" ? search_params[:column] : "end_time"
|
||||
order_dir = search_params[:column] && search_params[:direction] != "none" ? search_params[:direction] : "asc"
|
||||
order_dir = search_params[:column] && search_params[:direction] != "none" ? search_params[:direction] : "desc"
|
||||
|
||||
search = search.downcase
|
||||
|
||||
@ -40,7 +79,7 @@ module APIConcern
|
||||
r.delete(:playback)
|
||||
end
|
||||
|
||||
recs = filter_recordings(api_res, search)
|
||||
recs = filter_recordings(api_res, search, search_name)
|
||||
recs = sort_recordings(recs, order_col, order_dir)
|
||||
|
||||
if ret_search_params
|
||||
@ -50,7 +89,7 @@ module APIConcern
|
||||
end
|
||||
end
|
||||
|
||||
def filter_recordings(api_res, search)
|
||||
def filter_recordings(api_res, search, search_name = false)
|
||||
api_res[:recordings].select do |r|
|
||||
(!r[:metadata].nil? && ((!r[:metadata][:name].nil? &&
|
||||
r[:metadata][:name].downcase.include?(search)) ||
|
||||
@ -59,33 +98,34 @@ module APIConcern
|
||||
((r[:metadata].nil? || r[:metadata][:name].nil?) &&
|
||||
r[:name].downcase.include?(search)) ||
|
||||
r[:participants].include?(search) ||
|
||||
!r[:playbacks].select { |p| p[:type].downcase.include?(search) }.empty?
|
||||
!r[:playbacks].select { |p| p[:type].downcase.include?(search) }.empty? ||
|
||||
(search_name && Room.find_by(bbb_id: r[:meetingID]).owner.email.downcase.include?(search))
|
||||
end
|
||||
end
|
||||
|
||||
def sort_recordings(recs, order_col, order_dir)
|
||||
recs = case order_col
|
||||
when "end_time"
|
||||
recs.sort_by { |r| r[:endTime] }
|
||||
recs.sort_by { |r| r[:endTime] }
|
||||
when "name"
|
||||
recs.sort_by do |r|
|
||||
if !r[:metadata].nil? && !r[:metadata][:name].nil?
|
||||
r[:metadata][:name].downcase
|
||||
else
|
||||
r[:name].downcase
|
||||
end
|
||||
end
|
||||
recs.sort_by do |r|
|
||||
if !r[:metadata].nil? && !r[:metadata][:name].nil?
|
||||
r[:metadata][:name].downcase
|
||||
else
|
||||
r[:name].downcase
|
||||
end
|
||||
end
|
||||
when "length"
|
||||
recs.sort_by { |r| r[:playbacks].reject { |p| p[:type] == "statistics" }.first[:length] }
|
||||
recs.sort_by { |r| r[:playbacks].reject { |p| p[:type] == "statistics" }.first[:length] }
|
||||
when "users"
|
||||
recs.sort_by { |r| r[:participants] }
|
||||
recs.sort_by { |r| r[:participants] }
|
||||
when "visibility"
|
||||
recs.sort_by { |r| r[:metadata][:"gl-listed"] }
|
||||
recs.sort_by { |r| r[:metadata][:"gl-listed"] }
|
||||
when "formats"
|
||||
recs.sort_by { |r| r[:playbacks].first[:type].downcase }
|
||||
else
|
||||
recs.sort_by { |r| r[:endTime] }
|
||||
end
|
||||
recs.sort_by { |r| r[:playbacks].first[:type].downcase }
|
||||
else
|
||||
recs.sort_by { |r| r[:endTime] }
|
||||
end
|
||||
|
||||
if order_dir == 'asc'
|
||||
recs
|
@ -24,7 +24,7 @@ module Themer
|
||||
# Uses the built in Sass Engine to lighten the color
|
||||
|
||||
dummy_scss = "h1 { color: $lighten; }"
|
||||
compiled = Sass::Engine.new("$lighten:lighten(#{color}, 40%);" + dummy_scss, syntax: :scss).render
|
||||
compiled = SassC::Engine.new("$lighten:lighten(#{color}, 40%);" + dummy_scss, syntax: :scss).render
|
||||
|
||||
string_locater = 'color: '
|
||||
color_start = compiled.index(string_locater) + string_locater.length
|
||||
@ -37,7 +37,7 @@ module Themer
|
||||
# Uses the built in Sass Engine to darken the color
|
||||
|
||||
dummy_scss = "h1 { color: $darken; }"
|
||||
compiled = Sass::Engine.new("$darken:darken(#{color}, 10%);" + dummy_scss, syntax: :scss).render
|
||||
compiled = SassC::Engine.new("$darken:darken(#{color}, 10%);" + dummy_scss, syntax: :scss).render
|
||||
|
||||
string_locater = 'color: '
|
||||
color_start = compiled.index(string_locater) + string_locater.length
|
||||
|
@ -50,6 +50,11 @@ class RecordingsController < ApplicationController
|
||||
|
||||
# Ensure the user is logged into the room they are accessing.
|
||||
def verify_room_ownership
|
||||
redirect_to root_path unless @room.owned_by?(current_user)
|
||||
if !current_user ||
|
||||
!@room.owned_by?(current_user) ||
|
||||
!current_user.has_cached_role?(:admin) ||
|
||||
!current_user.has_cached_role?(:super_admin)
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -19,12 +19,13 @@
|
||||
class RoomsController < ApplicationController
|
||||
include RecordingsHelper
|
||||
include Pagy::Backend
|
||||
include Recorder
|
||||
|
||||
before_action :validate_accepted_terms, unless: -> { !Rails.configuration.terms }
|
||||
before_action :validate_verified_email, except: [:show, :join],
|
||||
unless: -> { !Rails.configuration.enable_email_verification }
|
||||
before_action :find_room, except: :create
|
||||
before_action :verify_room_ownership, except: [:create, :show, :join, :logout]
|
||||
before_action :verify_room_ownership, except: [:create, :show, :join, :logout, :login]
|
||||
before_action :verify_room_owner_verified, only: [:show, :join],
|
||||
unless: -> { !Rails.configuration.enable_email_verification }
|
||||
before_action :verify_user_not_admin, only: [:show]
|
||||
@ -35,9 +36,10 @@ class RoomsController < ApplicationController
|
||||
|
||||
return redirect_to current_user.main_room, flash: { alert: I18n.t("room.room_limit") } if room_limit_exceeded
|
||||
|
||||
@room = Room.new(name: room_params[:name])
|
||||
@room = Room.new(name: room_params[:name], access_code: room_params[:access_code])
|
||||
@room.owner = current_user
|
||||
@room.room_settings = create_room_settings_string(room_params[:mute_on_join], room_params[:client])
|
||||
@room.room_settings = create_room_settings_string(room_params[:mute_on_join], room_params[:client],
|
||||
room_params[:anyone_can_start])
|
||||
|
||||
if @room.save
|
||||
if room_params[:auto_join] == "1"
|
||||
@ -54,13 +56,15 @@ class RoomsController < ApplicationController
|
||||
|
||||
# GET /:room_uid
|
||||
def show
|
||||
@is_running = @room.running?
|
||||
@anyone_can_start = JSON.parse(@room[:room_settings])["anyoneCanStart"]
|
||||
|
||||
if current_user && @room.owned_by?(current_user)
|
||||
@search, @order_column, @order_direction, recs =
|
||||
@room.recordings(params.permit(:search, :column, :direction), true)
|
||||
recordings(@room.bbb_id, @user_domain, params.permit(:search, :column, :direction), true)
|
||||
|
||||
@pagy, @recordings = pagy_array(recs)
|
||||
|
||||
@is_running = @room.running?
|
||||
else
|
||||
# Get users name
|
||||
@name = if current_user
|
||||
@ -72,7 +76,7 @@ class RoomsController < ApplicationController
|
||||
end
|
||||
|
||||
@search, @order_column, @order_direction, pub_recs =
|
||||
@room.public_recordings(params.permit(:search, :column, :direction), true)
|
||||
public_recordings(@room.bbb_id, @user_domain, params.permit(:search, :column, :direction), true)
|
||||
|
||||
@pagy, @public_recordings = pagy_array(pub_recs)
|
||||
|
||||
@ -105,6 +109,12 @@ class RoomsController < ApplicationController
|
||||
|
||||
opts = default_meeting_options
|
||||
unless @room.owned_by?(current_user)
|
||||
# Don't allow users to join unless they have a valid access code or the room doesn't
|
||||
# have an access code
|
||||
if @room.access_code && !@room.access_code.empty? && @room.access_code != session[:access_code]
|
||||
return redirect_to room_path(room_uid: params[:room_uid]), flash: { alert: I18n.t("room.access_code_required") }
|
||||
end
|
||||
|
||||
# Assign join name if passed.
|
||||
if params[@room.invite_path]
|
||||
@join_name = params[@room.invite_path][:join_name]
|
||||
@ -117,31 +127,7 @@ class RoomsController < ApplicationController
|
||||
# create or update cookie with join name
|
||||
cookies.encrypted[:greenlight_name] = @join_name unless cookies.encrypted[:greenlight_name] == @join_name
|
||||
|
||||
if @room.running? || @room.owned_by?(current_user)
|
||||
# Determine if the user needs to join as a moderator.
|
||||
opts[:user_is_moderator] = @room.owned_by?(current_user)
|
||||
|
||||
# Check if the user has specified which client to use
|
||||
room_settings = JSON.parse(@room[:room_settings])
|
||||
opts[:join_via_html5] = room_settings["joinViaHtml5"] if room_settings["joinViaHtml5"]
|
||||
|
||||
if current_user
|
||||
redirect_to @room.join_path(current_user.name, opts, current_user.uid)
|
||||
else
|
||||
join_name = params[:join_name] || params[@room.invite_path][:join_name]
|
||||
redirect_to @room.join_path(join_name, opts)
|
||||
end
|
||||
else
|
||||
|
||||
search_params = params[@room.invite_path] || params
|
||||
@search, @order_column, @order_direction, pub_recs =
|
||||
@room.public_recordings(search_params.permit(:search, :column, :direction), true)
|
||||
|
||||
@pagy, @public_recordings = pagy_array(pub_recs)
|
||||
|
||||
# They need to wait until the meeting begins.
|
||||
render :wait
|
||||
end
|
||||
join_room(opts)
|
||||
end
|
||||
|
||||
# DELETE /:room_uid
|
||||
@ -184,6 +170,8 @@ class RoomsController < ApplicationController
|
||||
update_room_attributes("settings")
|
||||
# Update the rooms name if it has been changed
|
||||
update_room_attributes("name") if @room.name != room_params[:name]
|
||||
# Update the room's access code if it has changed
|
||||
update_room_attributes("access_code") if @room.access_code != room_params[:access_code]
|
||||
rescue StandardError
|
||||
flash[:alert] = I18n.t("room.update_settings_error")
|
||||
else
|
||||
@ -198,6 +186,15 @@ class RoomsController < ApplicationController
|
||||
redirect_to @room
|
||||
end
|
||||
|
||||
# POST /:room_uid/login
|
||||
def login
|
||||
session[:access_code] = room_params[:access_code]
|
||||
|
||||
flash[:alert] = I18n.t("room.access_code_required") if session[:access_code] != @room.access_code
|
||||
|
||||
redirect_to room_path(@room.uid)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_room_attributes(update_type)
|
||||
@ -205,13 +202,16 @@ class RoomsController < ApplicationController
|
||||
if update_type.eql? "name"
|
||||
@room.update_attributes(name: params[:room_name] || room_params[:name])
|
||||
elsif update_type.eql? "settings"
|
||||
room_settings_string = create_room_settings_string(room_params[:mute_on_join], room_params[:client])
|
||||
room_settings_string = create_room_settings_string(room_params[:mute_on_join], room_params[:client],
|
||||
room_params[:anyone_can_start])
|
||||
@room.update_attributes(room_settings: room_settings_string)
|
||||
elsif update_type.eql? "access_code"
|
||||
@room.update_attributes(access_code: room_params[:access_code])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_room_settings_string(mute_res, client_res)
|
||||
def create_room_settings_string(mute_res, client_res, start_res)
|
||||
room_settings = {}
|
||||
room_settings["muteOnStart"] = mute_res == "1"
|
||||
|
||||
@ -221,11 +221,13 @@ class RoomsController < ApplicationController
|
||||
room_settings["joinViaHtml5"] = false
|
||||
end
|
||||
|
||||
room_settings["anyoneCanStart"] = start_res == "1"
|
||||
|
||||
room_settings.to_json
|
||||
end
|
||||
|
||||
def room_params
|
||||
params.require(:room).permit(:name, :auto_join, :mute_on_join, :client)
|
||||
params.require(:room).permit(:name, :auto_join, :mute_on_join, :client, :access_code, :anyone_can_start)
|
||||
end
|
||||
|
||||
# Find the room from the uid.
|
||||
@ -274,7 +276,7 @@ class RoomsController < ApplicationController
|
||||
end
|
||||
|
||||
def verify_user_not_admin
|
||||
redirect_to admins_path if current_user && current_user&.has_role?(:super_admin)
|
||||
redirect_to admins_path if current_user && current_user&.has_cached_role?(:super_admin)
|
||||
end
|
||||
|
||||
def auth_required
|
||||
@ -287,8 +289,38 @@ class RoomsController < ApplicationController
|
||||
|
||||
# Does not apply to admin
|
||||
# 15+ option is used as unlimited
|
||||
return false if current_user&.has_role?(:admin) || limit == 15
|
||||
return false if current_user&.has_cached_role?(:admin) || limit == 15
|
||||
|
||||
current_user.rooms.count >= limit
|
||||
end
|
||||
|
||||
def join_room(opts)
|
||||
room_settings = JSON.parse(@room[:room_settings])
|
||||
|
||||
if @room.running? || @room.owned_by?(current_user) || room_settings["anyoneCanStart"]
|
||||
|
||||
# Determine if the user needs to join as a moderator.
|
||||
opts[:user_is_moderator] = @room.owned_by?(current_user) ||
|
||||
(room_settings["anyoneCanStart"] && !@room.running?)
|
||||
|
||||
# Check if the user has specified which client to use
|
||||
opts[:join_via_html5] = room_settings["joinViaHtml5"] if room_settings["joinViaHtml5"]
|
||||
|
||||
if current_user
|
||||
redirect_to @room.join_path(current_user.name, opts, current_user.uid)
|
||||
else
|
||||
join_name = params[:join_name] || params[@room.invite_path][:join_name]
|
||||
redirect_to @room.join_path(join_name, opts)
|
||||
end
|
||||
else
|
||||
search_params = params[@room.invite_path] || params
|
||||
@search, @order_column, @order_direction, pub_recs =
|
||||
public_recordings(@room.bbb_id, @user_domain, search_params.permit(:search, :column, :direction), true)
|
||||
|
||||
@pagy, @public_recordings = pagy_array(pub_recs)
|
||||
|
||||
# They need to wait until the meeting begins.
|
||||
render :wait
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -30,7 +30,7 @@ class ThemesController < ApplicationController
|
||||
@file_contents = File.read(file_name)
|
||||
|
||||
# Include the variables and covert scss file to css
|
||||
@compiled = Sass::Engine.new("$primary-color:#{color};" \
|
||||
@compiled = SassC::Engine.new("$primary-color:#{color};" \
|
||||
"$primary-color-lighten:#{lighten_color};" \
|
||||
"$primary-color-darken:#{darken_color};" +
|
||||
@file_contents, syntax: :scss).render
|
||||
|
@ -21,6 +21,7 @@ class UsersController < ApplicationController
|
||||
include Pagy::Backend
|
||||
include Emailer
|
||||
include Registrar
|
||||
include Recorder
|
||||
|
||||
before_action :find_user, only: [:edit, :update, :destroy]
|
||||
before_action :ensure_unauthenticated, only: [:new, :create]
|
||||
@ -66,6 +67,12 @@ class UsersController < ApplicationController
|
||||
flash[:alert] = I18n.t("registration.deprecated.new_signin")
|
||||
session[:old_twitter_user_id] = params[:old_twitter_user_id] unless params[:old_twitter_user_id].nil?
|
||||
end
|
||||
|
||||
providers = configured_providers
|
||||
if (!allow_user_signup? || !allow_greenlight_accounts?) && providers.count == 1 &&
|
||||
!Rails.configuration.loadbalanced_configuration
|
||||
return redirect_to "#{Rails.configuration.relative_url_root}/auth/#{providers.first}"
|
||||
end
|
||||
end
|
||||
|
||||
# GET /ldap_signin
|
||||
@ -103,6 +110,8 @@ class UsersController < ApplicationController
|
||||
|
||||
# PATCH /u/:user_uid/edit
|
||||
def update
|
||||
redirect_path = current_user.admin_of?(@user) ? admins_path : edit_user_path(@user)
|
||||
|
||||
if params[:setting] == "password"
|
||||
# Update the users password.
|
||||
errors = {}
|
||||
@ -123,7 +132,7 @@ class UsersController < ApplicationController
|
||||
if errors.empty? && @user.save
|
||||
# Notify the user that their account has been updated.
|
||||
flash[:success] = I18n.t("info_update_success")
|
||||
redirect_to edit_user_path(@user)
|
||||
redirect_to redirect_path
|
||||
else
|
||||
# Append custom errors.
|
||||
errors.each { |k, v| @user.errors.add(k, v) }
|
||||
@ -132,11 +141,11 @@ class UsersController < ApplicationController
|
||||
elsif user_params[:email] != @user.email && @user.update_attributes(user_params)
|
||||
@user.update_attributes(email_verified: false)
|
||||
flash[:success] = I18n.t("info_update_success")
|
||||
redirect_to edit_user_path(@user)
|
||||
redirect_to redirect_path
|
||||
elsif @user.update_attributes(user_params)
|
||||
update_locale(@user)
|
||||
flash[:success] = I18n.t("info_update_success")
|
||||
redirect_to edit_user_path(@user)
|
||||
redirect_to redirect_path
|
||||
else
|
||||
render :edit, params: { settings: params[:settings] }
|
||||
end
|
||||
@ -165,7 +174,8 @@ class UsersController < ApplicationController
|
||||
def recordings
|
||||
if current_user && current_user.uid == params[:user_uid]
|
||||
@search, @order_column, @order_direction, recs =
|
||||
current_user.all_recordings(params.permit(:search, :column, :direction), true)
|
||||
all_recordings(current_user.rooms.pluck(:bbb_id), current_user.provider,
|
||||
params.permit(:search, :column, :direction), true)
|
||||
@pagy, @recordings = pagy_array(recs)
|
||||
else
|
||||
redirect_to root_path
|
||||
@ -185,7 +195,7 @@ class UsersController < ApplicationController
|
||||
private
|
||||
|
||||
def find_user
|
||||
@user = User.find_by!(uid: params[:user_uid])
|
||||
@user = User.where(uid: params[:user_uid]).includes(:roles).first
|
||||
end
|
||||
|
||||
def ensure_unauthenticated
|
||||
|
@ -19,6 +19,18 @@
|
||||
module AdminsHelper
|
||||
include Pagy::Frontend
|
||||
|
||||
# Returns the action method of the current page
|
||||
def active_page
|
||||
route = Rails.application.routes.recognize_path(request.env['PATH_INFO'])
|
||||
|
||||
route[:action]
|
||||
end
|
||||
|
||||
# Gets the email of the room owner to which the recording belongs to
|
||||
def recording_owner_email(room_id)
|
||||
Room.find_by(bbb_id: room_id).owner.email
|
||||
end
|
||||
|
||||
def display_invite
|
||||
current_page?(admins_path) && invite_registration
|
||||
end
|
||||
@ -43,6 +55,15 @@ module AdminsHelper
|
||||
end
|
||||
end
|
||||
|
||||
def recording_default_visibility_string
|
||||
if Setting.find_or_create_by!(provider: user_settings_provider)
|
||||
.get_value("Default Recording Visibility") == "public"
|
||||
I18n.t("administrator.site_settings.recording_visibility.public")
|
||||
else
|
||||
I18n.t("administrator.site_settings.recording_visibility.private")
|
||||
end
|
||||
end
|
||||
|
||||
def registration_method_string
|
||||
case registration_method
|
||||
when Rails.configuration.registration_methods[:open]
|
||||
|
@ -107,7 +107,7 @@ module ApplicationHelper
|
||||
# Returns the page that the logo redirects to when clicked on
|
||||
def home_page
|
||||
return root_path unless current_user
|
||||
return admins_path if current_user.has_role? :super_admin
|
||||
return admins_path if current_user.has_cached_role? :super_admin
|
||||
current_user.main_room
|
||||
end
|
||||
end
|
||||
|
@ -37,7 +37,7 @@ module RoomsHelper
|
||||
|
||||
# Does not apply to admin or users that aren't signed in
|
||||
# 15+ option is used as unlimited
|
||||
return false if current_user&.has_role?(:admin) || limit == 15
|
||||
return false if current_user&.has_cached_role?(:admin) || limit == 15
|
||||
|
||||
current_user.rooms.length >= limit
|
||||
end
|
||||
@ -46,7 +46,7 @@ module RoomsHelper
|
||||
# Get how many rooms need to be deleted to reach allowed room number
|
||||
limit = Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Limit").to_i
|
||||
|
||||
return false if current_user&.has_role?(:admin) || limit == 15
|
||||
return false if current_user&.has_cached_role?(:admin) || limit == 15
|
||||
|
||||
@diff = current_user.rooms.count - limit
|
||||
@diff.positive? && current_user.rooms.pluck(:id).index(room.id) + 1 > limit
|
||||
|
@ -61,7 +61,17 @@ module SessionsHelper
|
||||
|
||||
# Retrieves the current user.
|
||||
def current_user
|
||||
@current_user ||= User.find_by(id: session[:user_id])
|
||||
@current_user ||= User.where(id: session[:user_id]).includes(:roles).first
|
||||
|
||||
if Rails.configuration.loadbalanced_configuration
|
||||
if @current_user && !@current_user.has_role?(:super_admin) &&
|
||||
@current_user.provider != @user_domain
|
||||
@current_user = nil
|
||||
session.clear
|
||||
end
|
||||
end
|
||||
|
||||
@current_user
|
||||
end
|
||||
|
||||
def generate_checksum(user_domain, redirect_url, secret)
|
||||
|
@ -31,7 +31,7 @@ module ThemingHelper
|
||||
|
||||
# Returns the user's provider in the settings context
|
||||
def user_settings_provider
|
||||
if Rails.configuration.loadbalanced_configuration && current_user && !current_user&.has_role?(:super_admin)
|
||||
if Rails.configuration.loadbalanced_configuration && current_user && !current_user&.has_cached_role?(:super_admin)
|
||||
current_user.provider
|
||||
elsif Rails.configuration.loadbalanced_configuration
|
||||
@user_domain
|
||||
|
@ -19,7 +19,6 @@
|
||||
require 'bbb_api'
|
||||
|
||||
class Room < ApplicationRecord
|
||||
include ::APIConcern
|
||||
include ::BbbApi
|
||||
|
||||
before_create :setup
|
||||
@ -40,7 +39,7 @@ class Room < ApplicationRecord
|
||||
|
||||
# Checks if a room is running on the BigBlueButton server.
|
||||
def running?
|
||||
bbb.is_meeting_running?(bbb_id)
|
||||
bbb(owner.provider).is_meeting_running?(bbb_id)
|
||||
end
|
||||
|
||||
# Determines the invite path for the room.
|
||||
@ -57,12 +56,15 @@ class Room < ApplicationRecord
|
||||
attendeePW: attendee_pw,
|
||||
moderatorOnlyMessage: options[:moderator_message],
|
||||
muteOnStart: options[:mute_on_start] || false,
|
||||
"meta_#{META_LISTED}": false,
|
||||
"meta_#{META_LISTED}": options[:recording_default_visibility] || false,
|
||||
"meta_bbb-origin-version": Greenlight::Application::VERSION,
|
||||
"meta_bbb-origin": "Greenlight",
|
||||
"meta_bbb-origin-server-name": options[:host]
|
||||
}
|
||||
|
||||
# Send the create request.
|
||||
begin
|
||||
meeting = bbb.create_meeting(name, bbb_id, create_options)
|
||||
meeting = bbb(owner.provider).create_meeting(name, bbb_id, create_options)
|
||||
# Update session info.
|
||||
unless meeting[:messageKey] == 'duplicateWarning'
|
||||
update_attributes(sessions: sessions + 1,
|
||||
@ -85,10 +87,10 @@ class Room < ApplicationRecord
|
||||
options[:user_is_moderator] ||= false
|
||||
options[:meeting_recorded] ||= false
|
||||
|
||||
return call_invalid_res unless bbb
|
||||
return call_invalid_res unless bbb(owner.provider)
|
||||
|
||||
# Get the meeting info.
|
||||
meeting_info = bbb.get_meeting_info(bbb_id, nil)
|
||||
meeting_info = bbb(owner.provider).get_meeting_info(bbb_id, nil)
|
||||
|
||||
# Determine the password to use when joining.
|
||||
password = if options[:user_is_moderator]
|
||||
@ -102,7 +104,7 @@ class Room < ApplicationRecord
|
||||
join_opts[:userID] = uid if uid
|
||||
join_opts[:joinViaHtml5] = options[:join_via_html5] if options[:join_via_html5]
|
||||
|
||||
bbb.join_meeting_url(bbb_id, name, password, join_opts)
|
||||
bbb(owner.provider).join_meeting_url(bbb_id, name, password, join_opts)
|
||||
end
|
||||
|
||||
# Notify waiting users that a meeting has started.
|
||||
@ -112,7 +114,7 @@ class Room < ApplicationRecord
|
||||
|
||||
# Retrieves all the users in a room.
|
||||
def participants
|
||||
res = bbb.get_meeting_info(bbb_id, nil)
|
||||
res = bbb(owner.provider).get_meeting_info(bbb_id, nil)
|
||||
res[:attendees].map do |att|
|
||||
User.find_by(uid: att[:userID], name: att[:fullName])
|
||||
end
|
||||
@ -121,27 +123,18 @@ class Room < ApplicationRecord
|
||||
[]
|
||||
end
|
||||
|
||||
# Fetches all recordings for a room.
|
||||
def recordings(search_params = {}, ret_search_params = false)
|
||||
res = bbb.get_recordings(meetingID: bbb_id)
|
||||
|
||||
format_recordings(res, search_params, ret_search_params)
|
||||
end
|
||||
|
||||
# Fetches a rooms public recordings.
|
||||
def public_recordings(search_params = {}, ret_search_params = false)
|
||||
search, order_col, order_dir, recs = recordings(search_params, ret_search_params)
|
||||
[search, order_col, order_dir, recs.select { |r| r[:metadata][:"gl-listed"] == "true" }]
|
||||
def recording_count
|
||||
bbb(owner.provider).get_recordings(meetingID: bbb_id)[:recordings].length
|
||||
end
|
||||
|
||||
def update_recording(record_id, meta)
|
||||
meta[:recordID] = record_id
|
||||
bbb.send_api_request("updateRecordings", meta)
|
||||
bbb(owner.provider).send_api_request("updateRecordings", meta)
|
||||
end
|
||||
|
||||
# Deletes a recording from a room.
|
||||
def delete_recording(record_id)
|
||||
bbb.delete_recordings(record_id)
|
||||
bbb(owner.provider).delete_recordings(record_id)
|
||||
end
|
||||
|
||||
private
|
||||
@ -156,7 +149,7 @@ class Room < ApplicationRecord
|
||||
|
||||
# Deletes all recordings associated with the room.
|
||||
def delete_all_recordings
|
||||
record_ids = recordings.map { |r| r[:recordID] }
|
||||
record_ids = bbb(owner.provider).get_recordings(meetingID: bbb_id)[:recordings].pluck(:recordID)
|
||||
delete_recording(record_ids) unless record_ids.empty?
|
||||
end
|
||||
|
||||
|
@ -20,7 +20,6 @@ require 'bbb_api'
|
||||
|
||||
class User < ApplicationRecord
|
||||
rolify
|
||||
include ::APIConcern
|
||||
include ::BbbApi
|
||||
|
||||
attr_accessor :reset_token
|
||||
@ -119,7 +118,7 @@ class User < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def self.admins_search(string)
|
||||
def self.admins_search(string, role)
|
||||
active_database = Rails.configuration.database_configuration[Rails.env]["adapter"]
|
||||
# Postgres requires created_at to be cast to a string
|
||||
created_at_query = if active_database == "postgresql"
|
||||
@ -128,38 +127,29 @@ class User < ApplicationRecord
|
||||
"created_at"
|
||||
end
|
||||
|
||||
search_query = "users.name LIKE :search OR email LIKE :search OR username LIKE :search" \
|
||||
" OR users.#{created_at_query} LIKE :search OR provider LIKE :search"
|
||||
search_query = ""
|
||||
role_search_param = ""
|
||||
if role.present?
|
||||
search_query = "(users.name LIKE :search OR email LIKE :search OR username LIKE :search" \
|
||||
" OR users.#{created_at_query} LIKE :search OR provider LIKE :search)" \
|
||||
" AND roles.name = :roles_search"
|
||||
role_search_param = role
|
||||
else
|
||||
search_query = "users.name LIKE :search OR email LIKE :search OR username LIKE :search" \
|
||||
" OR users.#{created_at_query} LIKE :search OR provider LIKE :search" \
|
||||
" OR roles.name LIKE :roles_search"
|
||||
role_search_param = "%#{string}%".downcase
|
||||
end
|
||||
|
||||
search_param = "%#{string}%"
|
||||
where(search_query, search: search_param)
|
||||
joins("LEFT OUTER JOIN users_roles ON users_roles.user_id = users.id LEFT OUTER JOIN roles " \
|
||||
"ON roles.id = users_roles.role_id").distinct
|
||||
.where(search_query, search: search_param, roles_search: role_search_param)
|
||||
end
|
||||
|
||||
def self.admins_order(column, direction)
|
||||
order("#{column} #{direction}")
|
||||
end
|
||||
|
||||
def all_recordings(search_params = {}, ret_search_params = false)
|
||||
pag_num = Rails.configuration.pagination_number
|
||||
|
||||
pag_loops = rooms.length / pag_num - 1
|
||||
|
||||
res = { recordings: [] }
|
||||
|
||||
(0..pag_loops).each do |i|
|
||||
pag_rooms = rooms[pag_num * i, pag_num]
|
||||
|
||||
# bbb.get_recordings returns an object
|
||||
# take only the array portion of the object that is returned
|
||||
full_res = bbb.get_recordings(meetingID: pag_rooms.pluck(:bbb_id))
|
||||
res[:recordings].push(*full_res[:recordings])
|
||||
end
|
||||
|
||||
last_pag_room = rooms[pag_num * (pag_loops + 1), rooms.length % pag_num]
|
||||
|
||||
full_res = bbb.get_recordings(meetingID: last_pag_room.pluck(:bbb_id))
|
||||
res[:recordings].push(*full_res[:recordings])
|
||||
|
||||
format_recordings(res, search_params, ret_search_params)
|
||||
# Arel.sql to avoid sql injection
|
||||
order(Arel.sql("#{column} #{direction}"))
|
||||
end
|
||||
|
||||
# Activates an account and initialize a users main room
|
||||
@ -231,13 +221,17 @@ class User < ApplicationRecord
|
||||
|
||||
def admin_of?(user)
|
||||
if Rails.configuration.loadbalanced_configuration
|
||||
if has_role? :super_admin
|
||||
# Pulls in the user roles if they weren't request in the original request
|
||||
# So the has_cached_role? doesn't always return false
|
||||
user.roles
|
||||
if has_cached_role? :super_admin
|
||||
id != user.id
|
||||
else
|
||||
(has_role? :admin) && (id != user.id) && (provider == user.provider) && (!user.has_role? :super_admin)
|
||||
(has_cached_role? :admin) && (id != user.id) && (provider == user.provider) &&
|
||||
(!user.has_cached_role? :super_admin)
|
||||
end
|
||||
else
|
||||
((has_role? :admin) || (has_role? :super_admin)) && (id != user.id)
|
||||
((has_cached_role? :admin) || (has_cached_role? :super_admin)) && (id != user.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
26
app/views/admins/components/_menu_buttons.html.erb
Normal file
26
app/views/admins/components/_menu_buttons.html.erb
Normal file
@ -0,0 +1,26 @@
|
||||
<%
|
||||
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
# This program is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free Software
|
||||
# Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<div class="list-group list-group-transparent mb-0">
|
||||
<%= link_to admins_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "index"}" do %>
|
||||
<span class="icon mr-3"><i class="fas fa-users"></i></span><%= t("administrator.users.title") %>
|
||||
<% end %>
|
||||
<%= link_to admin_site_settings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "site_settings"}" do %>
|
||||
<span class="icon mr-4"><i class="fas fa-cogs"></i></span><%= t("administrator.site_settings.title") %>
|
||||
<% end %>
|
||||
<%= link_to admin_recordings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "server_recordings"}" do %>
|
||||
<span class="icon mr-4"><i class="fas fa-video"></i></i></span><%= t("administrator.recordings.title") %>
|
||||
<% end %>
|
||||
</div>
|
91
app/views/admins/components/_recordings.html.erb
Normal file
91
app/views/admins/components/_recordings.html.erb
Normal file
@ -0,0 +1,91 @@
|
||||
<%
|
||||
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
# This program is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free Software
|
||||
# Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="table-responsive">
|
||||
<table id="recordings-table" class="table table-hover table-outline table-vcenter text-nowrap card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-header="name" data-order="<%= @order_column == "name" ? @order_direction : "none" %>">
|
||||
<%= t("recording.table.name") %>
|
||||
<% if @order_column == "name" && @order_direction == "desc" %>
|
||||
↓
|
||||
<% elsif @order_column == "name" && @order_direction == "asc" %>
|
||||
↑
|
||||
<% end %>
|
||||
</th>
|
||||
<th class="text-left" data-header="length" data-order="<%= @order_column == "length" ? @order_direction : "none" %>">
|
||||
<%= t("recording.table.length") %>
|
||||
<% if @order_column == "length" && @order_direction == "desc" %>
|
||||
↓
|
||||
<% elsif @order_column == "length" && @order_direction == "asc" %>
|
||||
↑
|
||||
<% end %>
|
||||
</th>
|
||||
<th class="text-left" data-header="users" data-order="<%= @order_column == "users" ? @order_direction : "none" %>">
|
||||
<%= t("recording.table.users") %>
|
||||
<% if @order_column == "users" && @order_direction == "desc" %>
|
||||
↓
|
||||
<% elsif @order_column == "users" && @order_direction == "asc" %>
|
||||
↑
|
||||
<% end %>
|
||||
</th>
|
||||
<th class="text-left" data-header="visibility" data-order="<%= @order_column == "visibility" ? @order_direction : "none" %>">
|
||||
<%= t("recording.table.visibility") %>
|
||||
<% if @order_column == "visibility" && @order_direction == "desc" %>
|
||||
↓
|
||||
<% elsif @order_column == "visibility" && @order_direction == "asc" %>
|
||||
↑
|
||||
<% end %>
|
||||
</th>
|
||||
<th data-header="formats" data-order="<%= @order_column == "formats" ? @order_direction : "none" %>">
|
||||
<%= t("recording.table.formats") %>
|
||||
<% if @order_column == "formats" && @order_direction == "desc" %>
|
||||
↓
|
||||
<% elsif @order_column == "formats" && @order_direction == "asc" %>
|
||||
↑
|
||||
<% end %>
|
||||
</th>
|
||||
<th class="text-center"><i class="icon-settings"></i></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="recording-table">
|
||||
<tr id="no_recordings_found" style="display: none;">
|
||||
<td colspan="7" class="text-center h4 p-6 font-weight-normal" >
|
||||
<%= t("recording.no_matched_recordings", inject:"") %>
|
||||
</td>
|
||||
</tr>
|
||||
<% if @recordings.empty? %>
|
||||
<tr>
|
||||
<td colspan="7" class="text-center h4 p-6 font-weight-normal">
|
||||
<%= t("administrator.recordings.no_recordings") %>
|
||||
</td>
|
||||
</tr>
|
||||
<% else %>
|
||||
<% @recordings.each do |recording| %>
|
||||
<%= render "admins/components/server_recording_row", recording: recording %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% if !@recordings.empty?%>
|
||||
<div class="float-right mr-4 mt-4">
|
||||
<%== pagy_bootstrap_nav(@pagy) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
81
app/views/admins/components/_server_recording_row.html.erb
Normal file
81
app/views/admins/components/_server_recording_row.html.erb
Normal file
@ -0,0 +1,81 @@
|
||||
<%
|
||||
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
# This program is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free Software
|
||||
# Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<div id="recording-title" class="form-inline edit_hover_class" data-recordid="<%= recording[:recordID] %>" data-room-uid="<%= room_uid_from_bbb(recording[:meetingID]) %>" data-path="<%= update_room_path(room_uid: room_uid_from_bbb(recording[:meetingID])) %>">
|
||||
<text id='recording-text'>
|
||||
<% if recording[:metadata][:name] %>
|
||||
<%= recording[:metadata][:name] %>
|
||||
<% else %>
|
||||
<%= recording[:name] %>
|
||||
<% end %>
|
||||
</text>
|
||||
<a><i id="edit-record" class="fa fa-edit align-top ml-2" data-edit-recordid="<%= recording[:recordID] %>"></i></a>
|
||||
</div>
|
||||
<div class="small text-muted">
|
||||
<%= t("recording.recorded_on", date: recording_date(recording[:startTime])) %>
|
||||
</div>
|
||||
<div class="small text-muted">
|
||||
<%= recording_owner_email(recording[:meetingID]) %>
|
||||
</div>
|
||||
</td>
|
||||
<td id="recording-length" class="text-left" data-full-length="<%= recording[:playbacks].empty? ? 0 : recording[:playbacks].first[:length]%>">
|
||||
<%= recording_length(recording[:playbacks]) %>
|
||||
</td>
|
||||
<td id="recording-users" class="text-left">
|
||||
<%= recording[:participants] || "-" %>
|
||||
</td>
|
||||
<td class="text-left">
|
||||
<div class="dropdown">
|
||||
<% if recording[:metadata][:"gl-listed"] == "true" %>
|
||||
<button class="btn btn-sm btn-secondary dropdown-toggle" data-toggle="dropdown"><i class="dropdown-icon fas fa-globe px-2"></i> <%= t("recording.visibility.public") %></button>
|
||||
<% else %>
|
||||
<button class="btn btn-sm btn-secondary dropdown-toggle" data-toggle="dropdown"><i class="dropdown-icon fas fa-link px-2"></i> <%= t("recording.visibility.unlisted") %></button>
|
||||
<% end %>
|
||||
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
<%= button_to update_recording_path(meetingID: recording[:meetingID], record_id: recording[:recordID], state: "public"), class: "dropdown-item" do %>
|
||||
<i class="dropdown-icon fas fa-globe"></i> <%= t("recording.visibility.public") %>
|
||||
<% end %>
|
||||
<%= button_to update_recording_path(meetingID: recording[:meetingID], record_id: recording[:recordID], state: "unlisted"), class: "dropdown-item" do %>
|
||||
<i class="dropdown-icon fas fa-link"></i> <%= t("recording.visibility.unlisted") %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<% sorted_formats = recording[:playbacks].sort_by! { |p| p[:type] } %>
|
||||
<% sorted_formats.each do |p| %>
|
||||
<%= link_to t("recording.format.#{p[:type]}"), p[:url], class: "btn btn-sm btn-primary", target: "_blank" %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<div class="item-action dropdown">
|
||||
<a href="javascript:void(0)" data-toggle="dropdown" class="icon">
|
||||
<i class="fas fa-ellipsis-v px-4"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<% p = recording[:playbacks].find do |p| p.key?(:length) end %>
|
||||
<% if p %>
|
||||
<a class="dropdown-item email-link" data-pres-link="<%= p[:url] %>"><i class="dropdown-icon far fa-envelope"></i> <%= t("recording.email") %></a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<% end %>
|
||||
<%= button_to delete_recording_path(meetingID: recording[:meetingID], record_id: recording[:recordID]), method: :delete, class: "dropdown-item" do %>
|
||||
<i class="dropdown-icon far fa-trash-alt"></i> <%= t("delete") %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
26
app/views/admins/components/_setting_view.html.erb
Normal file
26
app/views/admins/components/_setting_view.html.erb
Normal file
@ -0,0 +1,26 @@
|
||||
<%
|
||||
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
# This program is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free Software
|
||||
# Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<%= content_tag(:div, id: setting_id, class: "setting-view card") do %>
|
||||
<div class="card-body p-6">
|
||||
<div class="card-title text-primary">
|
||||
<div class="form-group">
|
||||
<%= render "shared/components/subtitle", subtitle: setting_title, search: search %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "admins/components/#{setting_id}" %>
|
||||
</div>
|
||||
<% end %>
|
@ -98,6 +98,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 row">
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%= t("administrator.site_settings.recording_visibility.title") %></label>
|
||||
<label class="form-label text-muted"><%= t("administrator.site_settings.recording_visibility.info") %></label>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" id="room-auth" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<%= recording_default_visibility_string %>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="room-auth">
|
||||
<%= button_to admin_recording_visibility_path(visibility: "public"), class: "dropdown-item" do %>
|
||||
<%= t("administrator.site_settings.recording_visibility.public") %>
|
||||
<% end %>
|
||||
<%= button_to admin_recording_visibility_path(visibility: "private"), class: "dropdown-item" do %>
|
||||
<%= t("administrator.site_settings.recording_visibility.private") %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
@ -13,6 +13,21 @@
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<%
|
||||
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
# This program is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free Software
|
||||
# Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<% if @role.present? %>
|
||||
<%= render "shared/components/admins_tags" %>
|
||||
<% end %>
|
||||
@ -146,3 +161,4 @@
|
||||
</div>
|
||||
|
||||
<%= render "shared/modals/invite_user_modal" %>
|
||||
|
27
app/views/admins/edit_user.html.erb
Normal file
27
app/views/admins/edit_user.html.erb
Normal file
@ -0,0 +1,27 @@
|
||||
<%
|
||||
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
# This program is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free Software
|
||||
# Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<div class="container pt-6">
|
||||
<%= render "shared/components/subtitle", subtitle: t("administrator.title"), search: false %>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 mb-4">
|
||||
<%= render "admins/components/menu_buttons" %>
|
||||
</div>
|
||||
<div id="edit_user" class="col-lg-9">
|
||||
<%= render "shared/settings/setting_view", setting_id: "account", setting_title: t("settings.account.subtitle") %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -18,26 +18,10 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="list-group list-group-transparent mb-0">
|
||||
<button id="users" class="list-group-item list-group-item-action setting-btn <%= "active" if !params[:setting] || params[:setting] == "users"%>">
|
||||
<span class="icon mr-3"><i class="fas fa-users"></i></span><%= t("administrator.users.title") %>
|
||||
</button>
|
||||
<button id="site_settings" class="list-group-item list-group-item-action setting-btn <%= "active" if params[:setting] == "site_settings"%>">
|
||||
<span class="icon mr-4"><i class="fas fa-cogs"></i></span><%= t("administrator.site_settings.title") %>
|
||||
</button>
|
||||
</div>
|
||||
<%= render "admins/components/menu_buttons" %>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-9">
|
||||
<% if defined?(setting_id) && setting_id == "account" %>
|
||||
<%= render "shared/settings/setting_view", setting_id: "account", setting_title: t("administrator.users.edit.title") %>
|
||||
<% else %>
|
||||
<%= render "shared/settings/setting_view", admin_view: true, setting_id: "users", setting_title: t("administrator.users.title") %>
|
||||
<%= render "shared/settings/setting_view", admin_view: true, setting_id: "site_settings", setting_title: t("administrator.site_settings.subtitle") %>
|
||||
<% end %>
|
||||
|
||||
<%= render "shared/modals/delete_account_modal", delete_location: relative_root %>
|
||||
<div id="users" class="col-lg-9">
|
||||
<%= render "admins/components/setting_view", setting_id: "users", setting_title: t("administrator.users.title"), search: true %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
27
app/views/admins/server_recordings.html.erb
Normal file
27
app/views/admins/server_recordings.html.erb
Normal file
@ -0,0 +1,27 @@
|
||||
<%
|
||||
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
# This program is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free Software
|
||||
# Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<div class="container pt-6">
|
||||
<%= render "shared/components/subtitle", subtitle: t("administrator.title"), search: false %>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 mb-4">
|
||||
<%= render "admins/components/menu_buttons" %>
|
||||
</div>
|
||||
<div id="server_recordings" class="col-lg-9">
|
||||
<%= render "admins/components/setting_view", setting_id: "recordings", setting_title: t("administrator.recordings.title"), search: true %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
27
app/views/admins/site_settings.html.erb
Normal file
27
app/views/admins/site_settings.html.erb
Normal file
@ -0,0 +1,27 @@
|
||||
<%
|
||||
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
|
||||
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
|
||||
# This program is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free Software
|
||||
# Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<div class="container pt-6">
|
||||
<%= render "shared/components/subtitle", subtitle: t("administrator.title"), search: false %>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 mb-4">
|
||||
<%= render "admins/components/menu_buttons" %>
|
||||
</div>
|
||||
<div id="site_settings" class="col-lg-9">
|
||||
<%= render "admins/components/setting_view", setting_id: "settings", setting_title: t("administrator.site_settings.subtitle"), search: false %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -13,9 +13,21 @@
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<%= render 'shared/room_event' do %>
|
||||
<% valid_access_code = @room.access_code.nil? || @room.access_code.empty? || @room.access_code == session[:access_code] %>
|
||||
<%= render 'shared/room_event', render_recordings: valid_access_code do %>
|
||||
<% if room_authentication_required %>
|
||||
<h2><%= t("administrator.site_settings.authentication.user-info") %></h2>
|
||||
<% elsif !valid_access_code %>
|
||||
<%= form_for :room, url: login_room_path(@room.uid) do |f| %>
|
||||
<div class="input-group join-input">
|
||||
<%= f.text_field :access_code,
|
||||
required: true,
|
||||
class: "form-control join-form",
|
||||
placeholder: t("room.enter_the_access_code"),
|
||||
value: "" %>
|
||||
<%= f.submit t("room.login"), class: "btn btn-primary btn-sm col-sm-3 form-control join-form" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= form_for room_path(@room), method: :post do |f| %>
|
||||
<div class="input-group join-input">
|
||||
@ -28,7 +40,7 @@
|
||||
placeholder: t("enter_your_name"),
|
||||
value: "#{@name}",
|
||||
readonly: !current_user.nil? %>
|
||||
<%= f.submit t("room.join"), class: "btn btn-primary btn-sm col-sm-3 form-control join-form" %>
|
||||
<%= f.submit (!@is_running && @anyone_can_start)? t("room.start") : t("room.join"), class: "btn btn-primary btn-sm col-sm-3 form-control join-form" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
@ -36,7 +36,7 @@
|
||||
<% unless exceeds_limit %>
|
||||
<label class="form-label"><%= t("room.invite_participants") %></label>
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-12 mt-2 pr-0">
|
||||
<div class="col-lg-7 col-md-12 mt-2 pr-0">
|
||||
<div class="input-icon invite-link-input">
|
||||
<span class="input-icon-addon">
|
||||
<i class="fas fa-link"></i>
|
||||
@ -44,7 +44,7 @@
|
||||
<input id="invite-url" type="text" class="form-control w-100" value="<%= request.base_url + @room.invite_path %>" readonly="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-7 col-md-12 pr-0">
|
||||
<div class="col-lg-5 col-md-12 pr-0">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<a href="#" id="copy" class="btn btn-primary btn-block mt-2">
|
||||
@ -89,7 +89,7 @@
|
||||
<%= render "shared/components/room_block", room: room %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= render "shared/modals/delete_room_modal", room: room %>
|
||||
<%= render "shared/modals/delete_room_modal", recording_count: room.recording_count, room: room %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% unless room_limit_exceeded %>
|
||||
|
@ -13,7 +13,7 @@
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<%= render 'shared/room_event' do %>
|
||||
<%= render 'shared/room_event', render_recordings: true do %>
|
||||
<div class="row">
|
||||
<div class="col-9">
|
||||
<h3><%= t("room.wait.message") %></h3>
|
||||
|
@ -23,7 +23,7 @@
|
||||
<div class="d-flex ml-auto">
|
||||
<% if current_user %>
|
||||
|
||||
<% if current_user.has_role? :super_admin %>
|
||||
<% if current_user.has_cached_role? :super_admin %>
|
||||
<% admins_page = params[:controller] == "admins" && params[:action] == "index" ? "active" : "" %>
|
||||
<%= link_to admins_path, class: "px-3 mx-1 mt-1 header-nav #{admins_page}" do %>
|
||||
<i class="fas fa-home pr-1 "></i> <%= t("header.dropdown.home") %>
|
||||
@ -56,7 +56,7 @@
|
||||
<%= link_to edit_user_path(current_user), class: "dropdown-item" do %>
|
||||
<i class="dropdown-icon fas fa-id-card mr-3"></i><%= t("header.dropdown.settings") %>
|
||||
<% end %>
|
||||
<% if current_user.has_role? :admin %>
|
||||
<% if current_user.has_cached_role? :admin %>
|
||||
<%= link_to admins_path, class: "dropdown-item" do %>
|
||||
<i class="dropdown-icon fas fa-user-tie mr-3"></i><%= t("header.dropdown.account_settings") %>
|
||||
<% end %>
|
||||
|
@ -40,4 +40,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "shared/sessions", recordings: @public_recordings, pagy: @pagy, only_public: true, user_recordings: false, title: t("room.recordings") %>
|
||||
<% if render_recordings %>
|
||||
<%= render "shared/sessions", recordings: @public_recordings, pagy: @pagy, only_public: true, user_recordings: false, title: t("room.recordings") %>
|
||||
<% end %>
|
||||
|
@ -13,7 +13,7 @@
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
%>
|
||||
|
||||
<div id="<%= if room == current_user.main_room then 'home_room_block' else 'room-block' end %>" data-room-uid="<%= room.uid %>" data-room-settings=<%= room.room_settings %> class="card">
|
||||
<div id="<%= if room == current_user.main_room then 'home_room_block' else 'room-block' end %>" data-room-uid="<%= room.uid %>" data-room-settings=<%= room.room_settings %> data-room-access-code="<%= room.access_code %>" class="card">
|
||||
<div class="card-body p-1">
|
||||
<table class="table table-hover table-vcenter text-wrap table-no-border">
|
||||
<tbody class="no-border-top">
|
||||
|
@ -28,10 +28,21 @@
|
||||
<span class="input-icon-addon">
|
||||
<i class="fas fa-chalkboard-teacher"></i>
|
||||
</span>
|
||||
<%= f.text_field :name, id: "create-room-name", class: "form-control", value: "", placeholder: t("modal.create_room.name_placeholder"), autocomplete: :off %>
|
||||
<%= f.text_field :name, id: "create-room-name", class: "form-control text-center", value: "", placeholder: t("modal.create_room.name_placeholder"), autocomplete: :off %>
|
||||
<div class="invalid-feedback text-left"><%= t("modal.create_room.not_blank") %></div>
|
||||
</div>
|
||||
|
||||
<div class="input-icon mb-2">
|
||||
<span onclick="generateAccessCode()" class="input-icon-addon allow-icon-click">
|
||||
<i class="fas fa-dice"></i>
|
||||
</span>
|
||||
<%= f.label :access_code, t("modal.create_room.access_code_placeholder"), id: "create-room-access-code", class: "form-control" %>
|
||||
<%= f.hidden_field :access_code %>
|
||||
<span onclick="ResetAccessCode()" class="input-icon-addon allow-icon-click">
|
||||
<i class="far fa-trash-alt"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<% if Rails.configuration.room_features.include? "default-client" %>
|
||||
<label class="mt-3 mb-3 w-100 text-left d-inline-block">
|
||||
<input type="hidden" name="room[client]" id="room_client">
|
||||
@ -57,6 +68,14 @@
|
||||
</label>
|
||||
<% end %>
|
||||
|
||||
<% if Rails.configuration.room_features.include? "anyone-can-start" %>
|
||||
<label class="custom-switch pl-0 mt-3 mb-3 w-100 text-left d-inline-block">
|
||||
<span class="custom-switch-description"><%= t("modal.room_settings.start")%></span>
|
||||
<%= f.check_box :anyone_can_start, class: "custom-switch-input", checked: false %>
|
||||
<span class="custom-switch-indicator float-right"></span>
|
||||
</label>
|
||||
<% end %>
|
||||
|
||||
<label id="auto-join-label" class="create-only custom-switch pl-0 mt-3 mb-3 w-100 text-left d-inline-block">
|
||||
<span class="custom-switch-description"><%= t("modal.create_room.auto_join") %></span>
|
||||
<%= f.check_box :auto_join, class: "custom-switch-input", checked: false %>
|
||||
|
@ -34,8 +34,8 @@
|
||||
<div class="card-footer">
|
||||
<p>
|
||||
<%= t("modal.delete_room.warning").html_safe %>
|
||||
<% if room.recordings.length > 0 %>
|
||||
<%= t("modal.delete_room.recording_warning", recordings_num: room.recordings.length).html_safe %>
|
||||
<% if recording_count > 0 %>
|
||||
<%= t("modal.delete_room.recording_warning", recordings_num: recording_count).html_safe %>
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -20,17 +20,17 @@
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="list-group list-group-transparent mb-0">
|
||||
|
||||
<button id="account" class="list-group-item list-group-item-action setting-btn <%= "active" if !params[:setting] || params[:setting] == "account"%>">
|
||||
<button id="account" class="list-group-item list-group-item-action dropdown-item setting-btn <%= "active" if !params[:setting] || params[:setting] == "account"%>">
|
||||
<span class="icon mr-3"><i class="fas fa-user"></i></span><%= t("settings.account.title") %>
|
||||
</button>
|
||||
|
||||
<% if @user.social_uid.nil? %>
|
||||
<button id="password" class="list-group-item list-group-item-action setting-btn <%= "active" if params[:setting] == "password"%>">
|
||||
<button id="password" class="list-group-item list-group-item-action dropdown-item setting-btn <%= "active" if params[:setting] == "password"%>">
|
||||
<span class="icon mr-3"><i class="fas fa-lock"></i></span><%= t("settings.password.title") %>
|
||||
</button>
|
||||
<% end %>
|
||||
|
||||
<button id="delete" class="list-group-item list-group-item-action setting-btn <%= "active" if params[:setting] == "delete"%>">
|
||||
<button id="delete" class="list-group-item list-group-item-action dropdown-item setting-btn <%= "active" if params[:setting] == "delete"%>">
|
||||
<span class="icon mr-3"><i class="fas fa-trash-alt"></i></span><%= t("settings.delete.title") %>
|
||||
</button>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user