Skip to content

Commit 967130e

Browse files
committed
GRN2-253: Added the ability to share rooms across multiple users (bigbluebutton#912)
* Added ability to share rooms with other users * Fixed testcases
1 parent 8cbfc3f commit 967130e

36 files changed

+748
-55
lines changed

app/assets/javascripts/application.js

+1
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@
3434
//= require jquery-ui/widget
3535
//= require jquery-ui/widgets/sortable
3636
//= require pickr.min.js
37+
//= require bootstrap-select.min.js
3738
//= require_tree .

app/assets/javascripts/room.js

+104
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,69 @@ $(document).on('turbolinks:load', function(){
6060
$(".delete-room").click(function() {
6161
showDeleteRoom(this)
6262
})
63+
64+
$('.selectpicker').selectpicker({
65+
liveSearchPlaceholder: "Start searching..."
66+
});
67+
// Fixes turbolinks issue with bootstrap select
68+
$(window).trigger('load.bs.select.data-api');
69+
70+
$(".share-room").click(function() {
71+
// Update the path of save button
72+
$("#save-access").attr("data-path", $(this).data("path"))
73+
74+
// Get list of users shared with and display them
75+
displaySharedUsers($(this).data("users-path"))
76+
})
77+
78+
$("#shareRoomModal").on("show.bs.modal", function() {
79+
$(".selectpicker").selectpicker('val','')
80+
})
81+
82+
$(".bootstrap-select").on("click", function() {
83+
$(".bs-searchbox").siblings().hide()
84+
})
85+
86+
$(".bs-searchbox input").on("input", function() {
87+
if ($(".bs-searchbox input").val() == '' || $(".bs-searchbox input").val().length < 3) {
88+
$(".bs-searchbox").siblings().hide()
89+
} else {
90+
$(".bs-searchbox").siblings().show()
91+
}
92+
})
93+
94+
$(".remove-share-room").click(function() {
95+
$("#remove-shared-confirm").parent().attr("action", $(this).data("path"))
96+
})
97+
98+
// User selects an option from the Room Access dropdown
99+
$(".bootstrap-select").on("changed.bs.select", function(){
100+
// Get the uid of the selected user
101+
let uid = $(".selectpicker").selectpicker('val')
102+
103+
// If the value was changed to blank, ignore it
104+
if (uid == "") return
105+
106+
let currentListItems = $("#user-list li").toArray().map(user => $(user).data("uid"))
107+
108+
// Check to make sure that the user is not already there
109+
if (!currentListItems.includes(uid)) {
110+
// Create the faded list item and display it
111+
let option = $("option[value='" + uid + "']")
112+
113+
let listItem = document.createElement("li")
114+
listItem.setAttribute('class', 'list-group-item text-left not-saved add-access');
115+
listItem.setAttribute("data-uid", uid)
116+
117+
let spanItem = "<span class='avatar float-left mr-2'>" + option.text().charAt(0) + "</span> <span class='shared-user'>" +
118+
option.text() + " <span class='text-muted'>" + option.data("subtext") + "</span></span>" +
119+
"<span class='text-primary float-right shared-user cursor-pointer' onclick='removeSharedUser(this)'><i class='fas fa-times'></i></span>"
120+
121+
listItem.innerHTML = spanItem
122+
123+
$("#user-list").append(listItem)
124+
}
125+
})
63126
}
64127
});
65128

@@ -150,3 +213,44 @@ function ResetAccessCode(){
150213
$("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder"))
151214
$("#room_access_code").val(null)
152215
}
216+
217+
function saveAccessChanges() {
218+
let listItemsToAdd = $("#user-list li:not(.remove-shared)").toArray().map(user => $(user).data("uid"))
219+
220+
$.post($("#save-access").data("path"), {add: listItemsToAdd})
221+
}
222+
223+
// Get list of users shared with and display them
224+
function displaySharedUsers(path) {
225+
$.get(path, function(users) {
226+
// Create list element and add to user list
227+
var user_list_html = ""
228+
229+
users.forEach(function(user) {
230+
user_list_html += "<li class='list-group-item text-left' data-uid='" + user.uid + "'>"
231+
232+
if (user.image) {
233+
user_list_html += "<img id='user-image' class='avatar float-left mr-2' src='" + user.image + "'></img>"
234+
} else {
235+
user_list_html += "<span class='avatar float-left mr-2'>" + user.name.charAt(0) + "</span>"
236+
}
237+
user_list_html += "<span class='shared-user'>" + user.name + "<span class='text-muted ml-1'>" + user.uid + "</span></span>"
238+
user_list_html += "<span class='text-primary float-right shared-user cursor-pointer' onclick='removeSharedUser(this)'><i class='fas fa-times'></i></span>"
239+
user_list_html += "</li>"
240+
})
241+
242+
$("#user-list").html(user_list_html)
243+
});
244+
}
245+
246+
// Removes the user from the list of shared users
247+
function removeSharedUser(target) {
248+
let parentLI = target.closest("li")
249+
250+
if (parentLI.classList.contains("not-saved")) {
251+
parentLI.parentNode.removeChild(parentLI)
252+
} else {
253+
parentLI.removeChild(target)
254+
parentLI.classList.add("remove-shared")
255+
}
256+
}

app/assets/stylesheets/application.scss

+3-1
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@
3636
@import "tabler-custom";
3737
@import "font-awesome-sprockets";
3838
@import "font-awesome";
39+
@import "monolith.min.scss";
40+
@import "bootstrap-select.min.css";
3941

4042
@import "utilities/variables";
4143
@import "admins";
4244
@import "main";
4345
@import "rooms";
4446
@import "sessions";
45-
@import "monolith.min.scss";
4647
@import "utilities/fonts";
48+
@import "users";
4749

4850
* {
4951
outline: none !important;

app/assets/stylesheets/rooms.scss

+17
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,20 @@
8383
margin-top: -6rem;
8484
font-size: 5rem;
8585
}
86+
87+
.bootstrap-select .dropdown-menu li.active small.text-muted{
88+
color: #9aa0ac !important
89+
}
90+
91+
.not-saved {
92+
color: grey;
93+
background: rgba(0, 40, 100, 0.12);
94+
}
95+
96+
.dropdown-menu.show {
97+
min-height: 0px !important;
98+
}
99+
100+
.remove-shared {
101+
text-decoration: line-through;
102+
}

app/assets/stylesheets/users.scss

+8
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,12 @@
2121

2222
.user-role-tag{
2323
color: white !important;
24+
}
25+
26+
.shared-user {
27+
line-height: 30px;
28+
}
29+
30+
.bootstrap-select {
31+
border: 1px solid rgba(0, 40, 100, 0.12);
2432
}

app/controllers/admins_controller.rb

+5-12
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class AdminsController < ApplicationController
2222
include Emailer
2323
include Recorder
2424
include Rolify
25+
include Populator
2526

2627
manage_users = [:edit_user, :promote, :demote, :ban_user, :unban_user, :approve, :reset]
2728
manage_deleted_users = [:undelete]
@@ -49,11 +50,7 @@ def site_settings
4950

5051
# GET /admins/server_recordings
5152
def server_recordings
52-
server_rooms = if Rails.configuration.loadbalanced_configuration
53-
Room.includes(:owner).where(users: { provider: @user_domain }).pluck(:bbb_id)
54-
else
55-
Room.pluck(:bbb_id)
56-
end
53+
server_rooms = rooms_list_for_recordings
5754

5855
@search, @order_column, @order_direction, recs =
5956
all_recordings(server_rooms, params.permit(:search, :column, :direction), true, true)
@@ -67,13 +64,9 @@ def server_rooms
6764
@order_column = params[:column] && params[:direction] != "none" ? params[:column] : "created_at"
6865
@order_direction = params[:direction] && params[:direction] != "none" ? params[:direction] : "DESC"
6966

70-
server_rooms = if Rails.configuration.loadbalanced_configuration
71-
Room.includes(:owner).where(users: { provider: @user_domain })
72-
.admins_search(@search)
73-
.admins_order(@order_column, @order_direction)
74-
else
75-
Room.all.admins_search(@search).admins_order(@order_column, @order_direction)
76-
end
67+
server_rooms = server_rooms_list
68+
69+
@user_list = shared_user_list if shared_access_allowed
7770

7871
@pagy, @rooms = pagy_array(server_rooms)
7972
end

app/controllers/application_controller.rb

+6
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ def configured_providers
172172
end
173173
helper_method :configured_providers
174174

175+
# Indicates whether users are allowed to share rooms
176+
def shared_access_allowed
177+
@settings.get_value("Shared Access") == "true"
178+
end
179+
helper_method :shared_access_allowed
180+
175181
# Parses the url for the user domain
176182
def parse_user_domain(hostname)
177183
return hostname.split('.').first if Rails.configuration.url_host.empty?

app/controllers/concerns/populator.rb

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# frozen_string_literal: true
2+
3+
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
4+
#
5+
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
6+
#
7+
# This program is free software; you can redistribute it and/or modify it under the
8+
# terms of the GNU Lesser General Public License as published by the Free Software
9+
# Foundation; either version 3.0 of the License, or (at your option) any later
10+
# version.
11+
#
12+
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
13+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14+
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public License along
17+
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
18+
19+
module Populator
20+
extend ActiveSupport::Concern
21+
22+
# Returns a list of rooms that are in the same context of the current user
23+
def server_rooms_list
24+
if Rails.configuration.loadbalanced_configuration
25+
Room.includes(:owner).where(users: { provider: @user_domain })
26+
.admins_search(@search)
27+
.admins_order(@order_column, @order_direction)
28+
else
29+
Room.all.admins_search(@search).admins_order(@order_column, @order_direction)
30+
end
31+
end
32+
33+
# Returns list of rooms needed to get the recordings on the server
34+
def rooms_list_for_recordings
35+
if Rails.configuration.loadbalanced_configuration
36+
Room.includes(:owner).where(users: { provider: @user_domain }).pluck(:bbb_id)
37+
else
38+
Room.pluck(:bbb_id)
39+
end
40+
end
41+
42+
# Returns a list of users that are in the same context of the current user
43+
def shared_user_list
44+
roles_can_appear = []
45+
Role.where(provider: @user_domain).each do |role|
46+
roles_can_appear << role.name if role.get_permission("can_appear_in_share_list") && role.name != "super_admin"
47+
end
48+
49+
initial_list = User.where.not(uid: current_user.uid).with_highest_priority_role(roles_can_appear)
50+
51+
return initial_list unless Rails.configuration.loadbalanced_configuration
52+
initial_list.where(provider: @user_domain)
53+
end
54+
end

app/controllers/concerns/rolify.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def update_permissions(role)
142142
role_params = params.require(:role).permit(:name)
143143
permission_params = params.require(:role).permit(:can_create_rooms, :send_promoted_email,
144144
:send_demoted_email, :can_edit_site_settings, :can_edit_roles, :can_manage_users,
145-
:can_manage_rooms_recordings, :colour)
145+
:can_manage_rooms_recordings, :can_appear_in_share_list, :colour)
146146

147147
permission_params.transform_values! do |v|
148148
if v == "0"

0 commit comments

Comments
 (0)