GRN2-129: Added server recordings and refactored adminsitrator panel (#662)
* Added server recordings and refactored adminsitrator panel * Fixed some issues * Fixed issue with owner email search * Fixed issue with edit user
This commit is contained in:
parent
8c63f793a5
commit
a055b88eb7
|
@ -43,9 +43,9 @@ $(document).on('turbolinks:load', function(){
|
|||
|
||||
window.location.replace(url);
|
||||
})
|
||||
|
||||
/* COLOR SELECTORS */
|
||||
}
|
||||
|
||||
if (controller == "admins" && action == "site_settings") {
|
||||
loadColourSelectors()
|
||||
}
|
||||
|
||||
|
|
|
@ -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,21 +39,6 @@ $(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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,6 +20,7 @@ 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,
|
||||
|
@ -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,7 +173,7 @@ 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
|
||||
|
||||
private
|
||||
|
|
|
@ -16,11 +16,50 @@
|
|||
# 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] : "desc"
|
||||
|
@ -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,7 +98,8 @@ 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
|
||||
|
|
@ -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,6 +19,7 @@
|
|||
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],
|
||||
|
@ -56,7 +57,7 @@ class RoomsController < ApplicationController
|
|||
def show
|
||||
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)
|
||||
|
||||
|
@ -72,7 +73,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)
|
||||
|
||||
|
@ -135,7 +136,7 @@ class RoomsController < ApplicationController
|
|||
|
||||
search_params = params[@room.invite_path] || params
|
||||
@search, @order_column, @order_direction, pub_recs =
|
||||
@room.public_recordings(search_params.permit(:search, :column, :direction), true)
|
||||
public_recordings(@room.bbb_id, @user_domain, search_params.permit(:search, :column, :direction), true)
|
||||
|
||||
@pagy, @public_recordings = pagy_array(pub_recs)
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
@ -103,6 +104,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 +126,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 +135,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 +168,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
@ -62,7 +61,7 @@ class Room < ApplicationRecord
|
|||
|
||||
# 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, last_session: DateTime.now)
|
||||
|
@ -84,10 +83,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]
|
||||
|
@ -101,7 +100,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.
|
||||
|
@ -111,7 +110,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
|
||||
|
@ -120,27 +119,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
|
||||
|
@ -155,7 +145,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
|
||||
|
@ -118,31 +117,8 @@ class User < ApplicationRecord
|
|||
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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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 %>
|
|
@ -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" %>
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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 %>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -73,6 +73,9 @@ en:
|
|||
registration_method_updated: Registration method successfully updated
|
||||
settings: Site Settings successfully changed
|
||||
unauthorized: You are not authorized to perform actions on this user
|
||||
recordings:
|
||||
title: Server Recordings
|
||||
no_recordings: This server has no recordings.
|
||||
title: Organization Settings
|
||||
users:
|
||||
invite: Invite User
|
||||
|
|
|
@ -37,6 +37,8 @@ Rails.application.routes.draw do
|
|||
resources :admins, only: [:index]
|
||||
|
||||
scope '/admins' do
|
||||
get '/site_settings', to: 'admins#site_settings', as: :admin_site_settings
|
||||
get '/recordings', to: 'admins#server_recordings', as: :admin_recordings
|
||||
post '/branding', to: 'admins#branding', as: :admin_branding
|
||||
post '/coloring', to: 'admins#coloring', as: :admin_coloring
|
||||
post '/room_authentication', to: 'admins#room_authentication', as: :admin_room_authentication
|
||||
|
|
|
@ -12,15 +12,9 @@ module BbbApi
|
|||
end
|
||||
|
||||
# Sets a BigBlueButtonApi object for interacting with the API.
|
||||
def bbb
|
||||
def bbb(user_provider)
|
||||
if Rails.configuration.loadbalanced_configuration
|
||||
if instance_of? Room
|
||||
# currently in the Room Model
|
||||
user_domain = retrieve_provider_info(owner.provider)
|
||||
elsif instance_of? User
|
||||
# currently in the User Model
|
||||
user_domain = retrieve_provider_info(provider)
|
||||
end
|
||||
user_domain = retrieve_provider_info(user_provider)
|
||||
|
||||
BigBlueButton::BigBlueButtonApi.new(remove_slash(user_domain["apiURL"]), user_domain["secret"], "0.8")
|
||||
else
|
||||
|
|
|
@ -0,0 +1,567 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# 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/>.
|
||||
|
||||
require "rails_helper"
|
||||
require 'bigbluebutton_api'
|
||||
|
||||
shared_examples_for "recorder" do
|
||||
let(:controller) { described_class } # the class that includes the concern
|
||||
|
||||
before do
|
||||
@user = create(:user)
|
||||
@room = @user.main_room
|
||||
|
||||
allow_any_instance_of(Room).to receive(:owner).and_return(@user)
|
||||
end
|
||||
|
||||
it "should properly find meeting recordings" do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return(
|
||||
recordings: [
|
||||
{
|
||||
name: "Example",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider)).to contain_exactly(
|
||||
name: "Example",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "gets all filtered and sorted recordings for the user" do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return(
|
||||
recordings: [
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "test",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Exam",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
name: "z",
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
expect(all_recordings(@user.rooms.pluck(:bbb_id), @user.provider, search: "Exam", column: "name",
|
||||
direction: "desc")).to eq(
|
||||
[
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
context '#filtering' do
|
||||
before do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return(
|
||||
recordings: [
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "test",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Exam",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
name: "metadata",
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on name" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, search: "Exam")).to contain_exactly(
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
},
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on participants" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, search: "5")).to contain_exactly(
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on format" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, search: "presentation")).to contain_exactly(
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "test",
|
||||
participants: "1",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on visibility" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, search: "public")).to contain_exactly(
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "test",
|
||||
participants: "1",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
},
|
||||
},
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on metadata name by default" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, search: "metadata")).to contain_exactly(
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Exam",
|
||||
participants: "1",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
name: "metadata",
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context '#sorting' do
|
||||
before do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return(
|
||||
recordings: [
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playback: {
|
||||
format: {
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format: {
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on name" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, column: "name", direction: "asc")).to eq(
|
||||
[
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on participants" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, column: "users", direction: "desc")).to eq(
|
||||
[
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on visibility" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, column: "visibility", direction: "desc")).to eq(
|
||||
[
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on length" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, column: "length", direction: "asc")).to eq(
|
||||
[
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on format" do
|
||||
expect(recordings(@room.bbb_id, @room.owner.provider, column: "formats", direction: "desc")).to eq(
|
||||
[
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
meetingID: @room.bbb_id,
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -52,7 +52,7 @@ describe AdminsController, type: :controller do
|
|||
|
||||
get :edit_user, params: { user_uid: @user.uid }
|
||||
|
||||
expect(response).to render_template(:index)
|
||||
expect(response).to render_template(:edit_user)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -197,7 +197,7 @@ describe AdminsController, type: :controller do
|
|||
feature = Setting.find_by(provider: "provider1").features.find_by(name: "Branding Image")
|
||||
|
||||
expect(feature[:value]).to eq(fake_image_url)
|
||||
expect(response).to redirect_to(admins_path)
|
||||
expect(response).to redirect_to(admin_site_settings_path)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -214,7 +214,7 @@ describe AdminsController, type: :controller do
|
|||
feature = Setting.find_by(provider: "provider1").features.find_by(name: "Primary Color")
|
||||
|
||||
expect(feature[:value]).to eq(primary_color)
|
||||
expect(response).to redirect_to(admins_path)
|
||||
expect(response).to redirect_to(admin_site_settings_path)
|
||||
end
|
||||
|
||||
it "changes the primary-lighten on the page" do
|
||||
|
@ -229,7 +229,7 @@ describe AdminsController, type: :controller do
|
|||
feature = Setting.find_by(provider: "provider1").features.find_by(name: "Primary Color Lighten")
|
||||
|
||||
expect(feature[:value]).to eq(primary_color)
|
||||
expect(response).to redirect_to(admins_path)
|
||||
expect(response).to redirect_to(admin_site_settings_path)
|
||||
end
|
||||
|
||||
it "changes the primary-darken on the page" do
|
||||
|
@ -244,7 +244,7 @@ describe AdminsController, type: :controller do
|
|||
feature = Setting.find_by(provider: "provider1").features.find_by(name: "Primary Color Darken")
|
||||
|
||||
expect(feature[:value]).to eq(primary_color)
|
||||
expect(response).to redirect_to(admins_path)
|
||||
expect(response).to redirect_to(admin_site_settings_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -264,7 +264,7 @@ describe AdminsController, type: :controller do
|
|||
|
||||
expect(feature[:value]).to eq(Rails.configuration.registration_methods[:invite])
|
||||
expect(flash[:success]).to be_present
|
||||
expect(response).to redirect_to(admins_path)
|
||||
expect(response).to redirect_to(admin_site_settings_path)
|
||||
end
|
||||
|
||||
it "does not allow the user to change to invite if emails are off" do
|
||||
|
@ -277,7 +277,7 @@ describe AdminsController, type: :controller do
|
|||
post :registration_method, params: { method: "invite" }
|
||||
|
||||
expect(flash[:alert]).to be_present
|
||||
expect(response).to redirect_to(admins_path)
|
||||
expect(response).to redirect_to(admin_site_settings_path)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -293,7 +293,7 @@ describe AdminsController, type: :controller do
|
|||
feature = Setting.find_by(provider: "provider1").features.find_by(name: "Room Authentication")
|
||||
|
||||
expect(feature[:value]).to eq("true")
|
||||
expect(response).to redirect_to(admins_path)
|
||||
expect(response).to redirect_to(admin_site_settings_path)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -309,7 +309,7 @@ describe AdminsController, type: :controller do
|
|||
feature = Setting.find_by(provider: "provider1").features.find_by(name: "Room Limit")
|
||||
|
||||
expect(feature[:value]).to eq("5")
|
||||
expect(response).to redirect_to(admins_path)
|
||||
expect(response).to redirect_to(admin_site_settings_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,6 +28,8 @@ def random_valid_room_params
|
|||
end
|
||||
|
||||
describe RoomsController, type: :controller do
|
||||
it_behaves_like "recorder"
|
||||
include Recorder
|
||||
describe "GET #show" do
|
||||
before do
|
||||
@user = create(:user)
|
||||
|
@ -39,7 +41,7 @@ describe RoomsController, type: :controller do
|
|||
|
||||
get :show, params: { room_uid: @owner.main_room }
|
||||
|
||||
expect(assigns(:recordings)).to eql(@owner.main_room.recordings)
|
||||
expect(assigns(:recordings)).to eql(recordings(@owner.main_room.bbb_id, @owner.provider))
|
||||
expect(assigns(:is_running)).to eql(@owner.main_room.running?)
|
||||
end
|
||||
|
||||
|
|
|
@ -302,6 +302,7 @@ describe UsersController, type: :controller do
|
|||
describe "PATCH #update" do
|
||||
it "properly updates user attributes" do
|
||||
user = create(:user)
|
||||
@request.session[:user_id] = user.id
|
||||
|
||||
params = random_valid_user_params
|
||||
patch :update, params: params.merge!(user_uid: user)
|
||||
|
@ -315,6 +316,7 @@ describe UsersController, type: :controller do
|
|||
|
||||
it "renders #edit on unsuccessful save" do
|
||||
@user = create(:user)
|
||||
@request.session[:user_id] = @user.id
|
||||
|
||||
patch :update, params: invalid_params.merge!(user_uid: @user)
|
||||
expect(response).to render_template(:edit)
|
||||
|
|
|
@ -133,420 +133,6 @@ describe Room, type: :model do
|
|||
end
|
||||
|
||||
context "#recordings" do
|
||||
it "should properly find meeting recordings" do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return(
|
||||
recordings: [
|
||||
{
|
||||
name: "Example",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
expect(@room.recordings).to contain_exactly(
|
||||
name: "Example",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
context '#filtering' do
|
||||
before do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return(
|
||||
recordings: [
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "test",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Exam",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
name: "z",
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on name" do
|
||||
expect(@room.recordings(search: "Exam")).to contain_exactly(
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
},
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on participants" do
|
||||
expect(@room.recordings(search: "5")).to contain_exactly(
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on format" do
|
||||
expect(@room.recordings(search: "presentation")).to contain_exactly(
|
||||
{
|
||||
name: "test",
|
||||
participants: "1",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on visibility" do
|
||||
expect(@room.recordings(search: "public")).to contain_exactly(
|
||||
{
|
||||
name: "test",
|
||||
participants: "1",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
},
|
||||
},
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it "should filter recordings on metadata name by default" do
|
||||
expect(@room.recordings(search: "z")).to contain_exactly(
|
||||
name: "Exam",
|
||||
participants: "1",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
name: "z",
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context '#sorting' do
|
||||
before do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return(
|
||||
recordings: [
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playback: {
|
||||
format: {
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format: {
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on name" do
|
||||
expect(@room.recordings(column: "name", direction: "asc")).to eq(
|
||||
[
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on participants" do
|
||||
expect(@room.recordings(column: "users", direction: "desc")).to eq(
|
||||
[
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on visibility" do
|
||||
expect(@room.recordings(column: "visibility", direction: "desc")).to eq(
|
||||
[
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on length" do
|
||||
expect(@room.recordings(column: "length", direction: "asc")).to eq(
|
||||
[
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
it "should sort recordings on format" do
|
||||
expect(@room.recordings(column: "formats", direction: "desc")).to eq(
|
||||
[
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks: [
|
||||
{
|
||||
type: "presentation",
|
||||
length: "4"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "1",
|
||||
playbacks: [
|
||||
{
|
||||
type: "other",
|
||||
length: "3"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
name: "Z",
|
||||
"gl-listed": "false"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
it "deletes the recording" do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:delete_recordings).and_return(
|
||||
returncode: true, deleted: true
|
||||
|
|
|
@ -173,97 +173,4 @@ describe User, type: :model do
|
|||
.to raise_exception(ActiveRecord::RecordInvalid, "Validation failed: Email can't be blank")
|
||||
end
|
||||
end
|
||||
|
||||
context '#recordings' do
|
||||
it "gets all filtered and sorted recordings for the user" do
|
||||
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return(
|
||||
recordings: [
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "test",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Exam",
|
||||
participants: "1",
|
||||
playback: {
|
||||
format:
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
name: "z",
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
expect(@user.all_recordings(search: "Exam", column: "name", direction: "desc")).to eq(
|
||||
[
|
||||
{
|
||||
name: "Example",
|
||||
participants: "3",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "presentation"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "true",
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "aExamaaa",
|
||||
participants: "5",
|
||||
playbacks:
|
||||
[
|
||||
{
|
||||
type: "other"
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
"gl-listed": "false",
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Reference in New Issue